Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 44 additions & 25 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,50 @@ expressions, general feature-chain navigation, or a syntax error — produces an
"unsupported filter construct" (or syntax-error) diagnostic and falls back to rendering the
resolved (`expose`) scope unfiltered, exactly as Phase 0 did for every filter expression.

**Phase 2 — deferred:**

- The bracketed `expose <path>::**[<expr>]` filter form: Phase 1 only captures its raw
expression text (mirroring the pre-Phase-1 standalone-`filter` behavior) and emits an
"unevaluated" warning; it is never evaluated. Phase 2 should extend the Phase 1 evaluator (or a
successor) to cover this form too.
- The Phase 1-excluded construct list above: `istype`/`hastype`/`all`, arithmetic operators,
conditional (`if`/`else`) expressions, and general feature-chain navigation (attribute/feature
reads not anchored by an `(as Type)` cast). Each currently produces a clear, non-crashing
"unsupported filter construct" diagnostic rather than silently doing nothing — full evaluation
of these constructs is future work.
- Metadata annotations on **usages** (as opposed to definitions) are captured in the semantic
model (`SysmlMetadataNode` is attached wherever `metadataFeature` appears), but
`GeneralViewLayoutStrategy`'s Phase 1 filter narrowing only evaluates classification
tests/attribute reads against rendered `SysmlDefinitionNode` candidates (matching
`CollectDefinitions`'s existing scope) — extending filter evaluation to usage-level candidates
is future work if a future view kind renders usages directly.

**Scope:** `SysmlNode.cs`/`AstBuilder.cs`/`ReferenceResolver.cs`/`SysmlEdge.cs` (metadata
capture); `DemaConsulting.SysML2Tools.Core.Filtering` (new subsystem); `GeneralViewLayoutStrategy`/
`LayoutWarnings` (filter application, dual unevaluated-bracket-filter warning).
**Visual gate:** a view with a standalone `filter @Type;`-style Phase 1 statement renders only
the elements satisfying the predicate, with no "not yet evaluated" warning for that statement;
an unsupported construct or a bracket-form filter still falls back to the resolved scope with an
explicit diagnostic.
**Phase 2a — done.** The bracketed `expose <path>::**[<expr>]` filter form is now evaluated too,
reusing the identical Phase 1 parser/evaluator unchanged. Fixed a Phase 1 pairing defect first:
`SysmlViewNode` previously captured a view's `expose` entries as two flattened, unpaired parallel
lists (`ExposedNames`/`ExposeBracketFilterTexts`), making it impossible to tell which bracket
filter belonged to which exposed path once a view declared more than one `expose` member; both
are now replaced by a single `ExposeMembers` list of paired `ExposeMember(QualifiedName,
BracketFilterExpressionText)` records. `ExposeScopeResolver` re-pairs each resolved `Expose` edge
with its originating `ExposeMember` and, for an entry carrying a bracket filter, parses and
evaluates it against a candidate set restricted to that entry's own target's containment subtree
of definitions (mirroring `GeneralViewLayoutStrategy.CollectDefinitions`'s existing restriction);
a successfully-evaluated filter narrows that entry's contribution to only the matched
definitions, while every other `expose` entry in the same view continues to contribute its whole
subtree unaffected. A bracket expression that fails to parse or evaluate degrades gracefully to
the previous whole-subtree behavior for that entry, with `LayoutWarnings.ForUnevaluatedExposeBracketFilter`
now warning only on that failure (mirroring `ForUnevaluatedFilter`'s existing failure-only
pattern) instead of unconditionally warning whenever any bracket filter was merely present.

**Phase 2b — deferred (zero corpus evidence):** the Phase 1-excluded construct list —
`istype`/`hastype`/`all`, arithmetic operators, conditional (`if`/`else`) expressions, and general
feature-chain navigation (attribute/feature reads not anchored by an `(as Type)` cast). Each
currently produces a clear, non-crashing "unsupported filter construct" diagnostic rather than
silently doing nothing. Across all 251 OMG corpus files sampled during Phase 2 planning, every
real `filter`/bracket-form-`expose` expression already fell within the Phase 1/2a supported
subset — there is no observed real-world need to implement these constructs yet, so they remain
deferred until a concrete corpus example demonstrates a need.

**Phase 2c — deferred (no current consumer):** metadata annotations on **usages** (as opposed to
definitions) are captured in the semantic model (`SysmlMetadataNode` is attached wherever
`metadataFeature` appears), but filter/bracket-filter narrowing only evaluates classification
tests/attribute reads against `SysmlDefinitionNode` candidates (matching
`CollectDefinitions`'s/`ExposeScopeResolver`'s existing definition-only restriction) — extending
evaluation to usage-level candidates is future work. Today, only `GeneralViewLayoutStrategy` uses
definition-scoped filter candidates at all; no other view kind or consumer currently needs
usage-level candidate filtering, so there is no concrete driver to implement it yet.

**Scope:** `SysmlNode.cs`/`AstBuilder.cs`/`ReferenceResolver.cs`/`SysmlEdge.cs` (metadata capture,
paired `ExposeMember` model); `DemaConsulting.SysML2Tools.Core.Filtering` (Phase 1 subsystem,
reused unchanged for Phase 2a); `ExposeScopeResolver` (Phase 2a bracket-filter evaluation, shared
by all 7 layout strategies); `GeneralViewLayoutStrategy`/`LayoutWarnings` (filter application,
failure-only bracket-filter warning).
**Visual gate:** a view with a standalone `filter @Type;`-style Phase 1 statement, or a bracketed
`expose <path>::**[<expr>]` Phase 2a statement, renders only the elements satisfying the
predicate, with no "unevaluated"/"not yet evaluated" warning for that statement; an unsupported
construct still falls back to the resolved scope with an explicit diagnostic.

---

Expand Down
18 changes: 14 additions & 4 deletions docs/design/sysml2-tools-core/filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
### Overview

The Filtering subsystem parses and evaluates the Phase 1 subset of standalone view
`filter [<expr>];` expressions captured on `SysmlViewNode.FilterExpressionText`. It contains one
unit, `FilterExpressionEvaluator`, whose implementation spans three tightly-coupled source files:
`FilterExpression` (the abstract syntax tree), `FilterExpressionParser` (the ANTLR-backed parser
adapter), and `FilterExpressionEvaluator` (the metadata-driven boolean evaluator).
`filter [<expr>];` expressions captured on `SysmlViewNode.FilterExpressionText`, and (Phase 2a)
the same subset of bracket-form `expose <path>::**[<expr>];` expressions captured per-entry on
`SysmlViewNode.ExposeMembers`. It contains one unit, `FilterExpressionEvaluator`, whose
implementation spans three tightly-coupled source files: `FilterExpression` (the abstract syntax
tree), `FilterExpressionParser` (the ANTLR-backed parser adapter), and `FilterExpressionEvaluator`
(the metadata-driven boolean evaluator).

This subsystem is intentionally narrow in Phase 1: it supports metadata classification tests,
boolean connectives, parenthesization, and `(as Type).attribute` reads (bare or compared against a
Expand Down Expand Up @@ -79,6 +81,13 @@ flowchart TD
7. The subsystem never throws for malformed or unsupported filter text. `GeneralViewLayoutStrategy`
uses parser diagnostics as the reason string when it falls back to rendering the unfiltered
resolved scope.
8. (Phase 2a) `ExposeScopeResolver` reuses `Parse`/`Evaluate` unchanged for bracket-form
`expose <path>::**[<expr>];` entries: it computes a per-entry candidate set restricted to
`SysmlDefinitionNode`s within that entry's own target containment subtree (mirroring
`GeneralViewLayoutStrategy.CollectDefinitions`'s existing restriction), calls `Evaluate` with
that candidate set, and adds the matched subset to the resolved scope's `ExplicitMembers`. No
change was required in this subsystem to support the second caller, confirming the evaluator's
candidate-set-agnostic design.

### Design Constraints

Expand All @@ -94,3 +103,4 @@ flowchart TD
| Requirement ID | Satisfied by |
| --- | --- |
| SysML2Tools-Core-Filtering-StandaloneViewFilterEvaluation | `Parse`, `Evaluate`, and `FilterExpression.ToString()` |
| SysML2Tools-Core-Filtering-BracketFormExposeEvaluation | `ExposeScopeResolver` reusing `Parse`/`Evaluate` |
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ shape leaves room for future evaluation-time diagnostics without a breaking API
`FilterExpressionParser.Parse`, evaluates successful ASTs with `FilterExpressionEvaluator.Evaluate`,
narrows its candidate definition set to the matched subset, and falls back to an unfiltered
render with a warning when parsing produces diagnostics.
- (Phase 2a) `ExposeScopeResolver.ResolveExposedScope` parses each `ExposeMember`'s
`BracketFilterExpressionText` with `FilterExpressionParser.Parse`, evaluates successful ASTs
with `FilterExpressionEvaluator.Evaluate` against that entry's own containment-subtree
candidate set, adds matches to the resolved `ExposedScope.ExplicitMembers`, and falls back to
whole-subtree inclusion (`PrefixSubjects`) plus a recorded `BracketFilterFailure` on parse or
evaluation failure. No change was required in this unit to support this second caller.
- `FilterExpressionParserTests` and `FilterExpressionEvaluatorTests` exercise the parser,
pretty-printer, and evaluator directly.

Expand Down
Loading
Loading