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
1 change: 1 addition & 0 deletions .cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ words:
- setlocal
- Skia
- Subsetting
- subsettings
- Sugiyama
- Tagawa
- Toda
Expand Down
20 changes: 1 addition & 19 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,12 @@ The work falls into three themes:

## Notation & view conformance

### Connector-end & line-style conformance

Bring routed connectors into line with the SysML v2 notation — the highest-value, broadest-impact
change.

- Wire the already-defined end markers to relationships: **filled/hollow diamonds** for
composite/reference membership; **redefinition** crossbar variant.
- Switch succession/transition/message end markers to the spec style (**open V**, stroke-only)
and make **successions dashed** — pending confirmation against the training PDF; keep a theme
switch if the training material differs from `clause-8.2.3`.
- Add `LineStyle.Dashed` usage where required; ensure end markers render correctly at clearance
stubs.

**Scope:** `LayoutLine` end-marker/line-style assignments in the view strategies; renderer
marker defs (already present). No new engines.
**Visual gate:** state/action/sequence/general galleries match the spec end shapes; membership
diamonds appear where membership is shown.

### Additional relationship edges (General View)

Render the relationships currently omitted from the General View, each routed via
`ChannelRouter` and carrying the correct spec end shape:

- Redefinition, subsetting (where shown as edges), feature typing, dependency, containment,
- Subsetting (where shown as edges), feature typing, dependency, containment,
connection/binding, allocation.
- Shared-bus generalization (multiple subtypes merging into one line to a supertype) as an
optional readability refinement.
Expand Down
7 changes: 4 additions & 3 deletions docs/design/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ system, subsystem, and unit levels:
- **SysmlNode** (Unit) — public AST node hierarchy: nine types with JSON polymorphism
- **AstBuilder** (Unit) — builds AST from ANTLR4 CST with qualified names and supertype lists
- **SymbolTable** (Unit) — registry mapping qualified names to declaration nodes
- **ReferenceResolver** (Unit) — resolves supertype, typing, import, satisfy, verify,
allocate, and (in a second pass) dotted feature-chain connect/transition references;
- **ReferenceResolver** (Unit) — resolves supertype, typing, redefinition, import, satisfy,
verify, allocate, and (in a second pass) dotted feature-chain connect/transition references;
detects circular imports; returns a `SemanticIndex` of resolved edges
- **SupertypeWalker** (Unit) — walks specialization chains; detects cyclic specialization
- **SysmlEdge** (Unit) — public resolved-reference record (Supertype/Typing/Import/
Expand All @@ -77,7 +77,8 @@ system, subsystem, and unit levels:
`DemaConsulting.Rendering.Layout` layered algorithm
- **Internal** (Subsystem) — per-view layout strategies
- **GeneralViewLayoutStrategy** (Unit) — general view: package-grouped definitions placed by
the layered algorithm with orthogonal specialization and membership edges
the layered algorithm with orthogonal specialization, membership, attribute-typing, and
redefinition edges
- **InterconnectionViewLayoutStrategy** (Unit) — internal structure: nested parts, ports, connectors
- **StateTransitionViewLayoutStrategy** (Unit) — state machine: states and guarded transitions
placed top-to-bottom by the layered algorithm (DOWN direction) with orthogonal transitions
Expand Down
2 changes: 1 addition & 1 deletion docs/design/sysml2-tools-core/layout/internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The subsystem contains one strategy per supported view type:

| Unit | Responsibility |
| --- | --- |
| `GeneralViewLayoutStrategy` | Lays out user definitions grouped by package with specialization edges |
| `GeneralViewLayoutStrategy` | Lays out definitions by package with specialization, membership, typing, redefinition |
| `InterconnectionViewLayoutStrategy` | Lays out the internal parts, ports, and connections of one part definition |
| `StateTransitionViewLayoutStrategy` | Lays out states, an initial marker, and guarded transitions |
| `ActionFlowViewLayoutStrategy` | Lays out actions top-to-bottom with start/done markers and successions |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
renders every user-defined definition (part, port, interface, requirement, action, and so on) as
a keyword-labeled box, groups the boxes that belong to a package inside a folder-shaped
container, lists each definition's owned usages in compartments, and draws specialization,
membership, and attribute-typing edges orthogonally between the boxes. The whole diagram — package
membership, attribute-typing, and redefinition edges orthogonally between the boxes. The whole diagram — package
folders and definitions alike — is expressed as a single `DemaConsulting.Rendering` `LayoutGraph`
and placed with one `HierarchicalLayoutAlgorithm.Apply` call: the root scope packs package folders
and top-level definitions by reading order (`ContainmentLayoutAlgorithm`), while each folder's own
Expand All @@ -21,14 +21,19 @@ box title and folder-tab geometry come from `BoxMetrics` in `DemaConsulting.Rend
parameters. Layout constants (`MinBoxWidth`, `CharWidthFactor`) are declared as `private const`
fields. Private records carry intermediate data: `DefBox` (a user definition with its computed
size, keyword, supertype names, memberships, and compartments), `ModelEdge` (a resolved
specialization/membership/attribute-typing relationship expressed by qualified name, together with
its target end marker and edge kind), `Location` (a located definition's graph node and owning
package, used to resolve and scope edges), and `TruncatedFolder` (a depth-truncated package folder's
leaf graph node and hidden-definition count, used to stamp its ellipsis label onto the placed box
after layout). The private `EdgeKind` enumeration classifies each edge as `Specialization`,
`Membership`, or `Typing`; the `LineStyleForKind` helper maps this kind to a rendered line style
(dashed for `Typing`, solid for the others), so an attribute-typing dependency is visually distinct
from the structural relationships.
specialization/membership/attribute-typing/redefinition relationship expressed by qualified
name, together with its target end marker and edge kind), `Location` (a located definition's
graph node and owning package, used to resolve and scope edges), and `TruncatedFolder` (a
depth-truncated package folder's leaf graph node and hidden-definition count, used to stamp its
ellipsis label onto the placed box after layout). `FeatureMembership` (a private record) carries
each owned feature's keyword, raw type reference (`TypeName`, nullable — a feature may declare a
redefinition with no explicit type annotation), simple `Name`, and raw
`RedefinedFeatureName` reference; `CollectMemberships` includes a feature when either `TypeName`
or `RedefinedFeatureName` is present. The private `EdgeKind` enumeration classifies each edge as
`Specialization`, `Membership`, `Typing`, or `Redefinition`; the `LineStyleForKind` helper maps
this kind to a rendered line style (dashed for `Typing`, solid for the others — including
`Redefinition`), so an attribute-typing dependency is visually distinct from the structural
relationships.

##### Key Methods

Expand All @@ -39,8 +44,8 @@ Entry point. First resolves the view's exposed-name scope via the shared
`CollectDefinitions` to gather user definitions restricted to that scope (or every definition when
no scope applies); returns a minimal 200×100 empty `LayoutTree` when none are found. Otherwise
groups the definitions by package with `GroupByPackage`, resolves the specialization/membership/
attribute-typing relationships into qualified-name edges with `BuildModelEdges`, builds the single
input `LayoutGraph` with `BuildGraph`, and places the whole graph with one
attribute-typing/redefinition relationships into qualified-name edges with `BuildModelEdges`,
builds the single input `LayoutGraph` with `BuildGraph`, and places the whole graph with one
`HierarchicalLayoutAlgorithm().Apply(graph, LayoutOptions.ForAlgorithm("containment"))`
call — passing the desired root-scope leaf algorithm through the options parameter (not
`graph.Set(CoreOptions.Algorithm, …)`) so a caller going through `LayoutEngine.Layout(graph)` later
Expand All @@ -67,8 +72,9 @@ Top-level definitions (no package prefix) become plain leaves directly on the ro

###### `BuildModelEdges(defs)`

Resolves every specialization (subtype → supertype), structural membership (member-type → owner), and
attribute-typing (owner → attribute-type) relationship — across every definition, regardless of
Resolves every specialization (subtype → supertype), structural membership (member-type → owner),
attribute-typing (owner → attribute-type), and redefinition (subtype → the owning definition of
the redefined feature) relationship — across every definition, regardless of
package — into a flat list of qualified-name `ModelEdge`s. Specialization edges carry an open
triangular end marker at the supertype; `part`/`port` memberships carry a filled diamond and `ref`
memberships a hollow diamond at the owner; other memberships are not drawn. In addition, each
Expand All @@ -78,7 +84,19 @@ chevron at the type end and rendered as a dashed line. Attribute typing is a usa
not composition, so it uses the OMG dependency notation (dashed line with an open arrowhead) rather
than a membership diamond, and it connects otherwise-disconnected attribute and enumeration
definitions into the cluster near the definitions that reference them. Unresolved types and
self-references are skipped. Whether an edge's endpoints actually receive a graph node — i.e.,
self-references are skipped. Finally, each feature with a non-null `RedefinedFeatureName`
contributes a **redefinition** edge from the subtype to the owning definition of the redefined
feature, carrying a hollow-triangle-crossbar end marker at the owner and rendered as a solid line
via `ResolveRedefinitionOwner`: a qualified reference (containing `::`) strips the text before the
*last* `::` segment and resolves it directly via `TryResolveQualified`; a bare-name reference
instead walks the redefining definition's own `SupertypeNames` (resolved the same way), checking
each resolved supertype's own `Memberships` for a matching simple `Name`, and recurses
transitively up the chain (guarded by a `HashSet<string>` of visited qualified names to prevent an
infinite loop on a malformed cyclic supertype graph) when the immediate supertype does not declare
it. Neither resolving nor a self-referential result (`owner == def.QualifiedName`) produces an
edge or a diagnostic — consistent with the existing `TryResolveQualified`-failure-is-silent
convention used by the other three edge kinds in this method. Whether an edge's endpoints actually
receive a graph node — i.e.,
were not depth-truncated — is decided later, in `BuildGraph`.

###### `BuildGraph(groups, modelEdges, theme, depthLimit)`
Expand Down Expand Up @@ -142,7 +160,8 @@ produces valid geometry, so no crossing warnings are emitted.
"parsed but not yet evaluated" filter-expression warning text.
- The `LayoutTree`, `LayoutBox`, `LayoutCompartment`, `LayoutLine`, `LayoutLabel`, and `Point2D` data
types (`DemaConsulting.Rendering`).
- `FeatureMembership` (private record) — carries the keyword and type reference of one owned feature.
- `FeatureMembership` (private record) — carries the keyword, nullable type reference, simple
name, and nullable redefined-feature reference of one owned feature.

##### Callers

Expand Down
4 changes: 2 additions & 2 deletions docs/design/sysml2-tools-language/semantic.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ optionally seeded with a pre-populated symbol table.
- *Contract*: Exposes `IReadOnlyList<string> Files`, `IReadOnlySet<string> StdlibNames`,
`IReadOnlyDictionary<string, SysmlNode> Declarations` mapping qualified names to declaration
nodes, and `SemanticIndex Index` — a reverse-lookup index over all resolved edge kinds
(supertype, typing, import, satisfy, verify, allocate, connect, transition, and expose; see
Semantic Model Subsystem).
(supertype, typing, redefinition, import, satisfy, verify, allocate, connect, transition, and
expose; see Semantic Model Subsystem).

### Design

Expand Down
2 changes: 1 addition & 1 deletion docs/design/sysml2-tools-language/semantic/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ over resolved edges.
| --- | --- |
| `AstBuilder` | Visits ANTLR4 CST; builds typed AST nodes with qualified names and supertype lists |
| `SymbolTable` | Registry mapping fully-qualified names to their AST nodes |
| `ReferenceResolver` | Resolves supertype/typing/import/satisfy/verify/allocate/connect/transition/expose refs |
| `ReferenceResolver` | Resolves supertype/typing/redefinition/import/satisfy/verify/allocate/connect/transition |
| `SupertypeWalker` | Walks specialization chains; detects cyclic specialization |
| `SysmlNode` | Public abstract base record (and subtypes) modeling one parsed AST element |
| `SysmlEdge` | Public record modeling one resolved reference (Supertype/Typing/Import/Satisfy/Verify/Allocate/etc.) |
Expand Down
29 changes: 29 additions & 0 deletions docs/design/sysml2-tools-language/semantic/model/ast-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,35 @@ alongside the existing `ImportedNamespace` property — letting `ReferenceResolv
references uniformly with `SupertypeNames` and `FeatureTyping` without any node-type
special-casing.

`BuildUsageNode` additionally calls `ExtractRedefinedFeature(decl?.featureSpecializationPart())`
alongside `ExtractFeatureTyping`, setting the result on the constructed `SysmlFeatureNode`'s
`RedefinedFeatureName` property. `ExtractRedefinedFeature` mirrors `ExtractFeatureTyping`'s exact
structure: it loops `featureSpecializationPart().featureSpecialization()`, and for each entry
whose `redefinitions()` is non-null, first checks `redefinitions().redefines()?.ownedRedefinition()`
(the first redefined feature, held by the `redefines`/`:>>` clause) and returns its `.GetText()`;
if that clause is absent, it falls back to the first non-null entry of
`redefinitions().ownedRedefinition()` (the `redefines (COMMA ownedRedefinition)*` list's
additional entries). It returns `null` when no `redefinitions()` is present anywhere in the
part — i.e. the feature declares no redefinition. Both the `redefines` keyword form and the
`:>>` operator form parse into the same `RedefinesContext` (they differ only in which terminal —
`REDEFINES` or `COLON_GT_GT` — the grammar matched), so `ExtractRedefinedFeature` handles both
forms identically without needing to branch on which token was used. The raw reference text is
captured verbatim — including qualified `Owner::feature` forms — with no resolution attempted;
resolution happens later, in `ReferenceResolver`.

`BuildUsageNode` also calls `ExtractSubsettingTargetNames(decl?.featureSpecializationPart())`,
setting the result on the constructed `SysmlFeatureNode`'s inherited `SupertypeNames` property —
mirroring `ExtractRedefinedFeature`'s structure (first checking
`subsettings().subsets()?.ownedSubsetting()`, the target held by the `subsets`/`:>` clause, then
falling back to `subsettings().ownedSubsetting()`'s remaining comma-separated entries) but
collecting *every* match into a list rather than returning only the first. Before this, a
usage-level `subsets`/`:>` clause (as opposed to a definition-level `:>` specialization, already
handled by `GetSubclassificationSupertypes`) was never extracted at all, so it produced no
`Supertype` edge and was invisible to `ReferenceResolver` — silently breaking its bare-name
redefinition ancestor-chain walk whenever the redefining feature's owner was itself a
usage-level subsetting rather than a `part def` specialization (the exact shape used by the OMG
corpus fixture `1c-PartsTreeRedefinition.sysml`'s `part vehicle1_c1 :> vehicle1 { ... }`).

`VisitAnnotatingElement(AnnotatingElementContext)` intercepts the `comment` and `documentation`
grammar alternatives of `annotatingElement` (`comment | documentation | textualRepresentation |
metadataFeature`) and returns a private `AnnotationCapture` sentinel node wrapping a
Expand Down
Loading
Loading