Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c50f54e
Merge remote-tracking branch 'origin/feature/migrate-diagrams-to-view…
devin-ai-integration[bot] Sep 22, 2026
4ddb859
feat(query): unbounded maxDepth, RelatedColumn targets and isIndividu…
devin-ai-integration[bot] Sep 22, 2026
ccb6569
feat(docplan): bind packages and definitions to query parameters thro…
devin-ai-integration[bot] Sep 22, 2026
1b28565
feat(query): add Named, resolving elements by qualified name
devin-ai-integration[bot] Sep 22, 2026
a1c9bb4
Revert "feat(docplan): bind packages and definitions to query paramet…
devin-ai-integration[bot] Sep 22, 2026
84e4750
feat(migrate): read MagicDraw table, matrix, relation map and DocGen …
devin-ai-integration[bot] Sep 22, 2026
1140700
fix(migrate): lower every table definition attached to one diagram
devin-ai-integration[bot] Sep 22, 2026
c201d60
Merge remote-tracking branch 'origin/feature/migrate-diagrams-to-view…
devin-ai-integration[bot] Sep 22, 2026
9519719
fix(queryexec): drop the unused integer argument reader
devin-ai-integration[bot] Sep 22, 2026
94845a0
fix(migrate): list whole-model roots and keep projected column names …
devin-ai-integration[bot] Sep 22, 2026
d05a2b5
Merge remote-tracking branch 'origin/feature/migrate-diagrams-to-view…
devin-ai-integration[bot] Sep 22, 2026
ae3844b
Merge branch 'develop' into feature/migrate-tables-and-documents
devin-ai-integration[bot] Sep 23, 2026
ff585c7
Merge remote-tracking branch 'origin/feature/migrate-tables-and-docum…
devin-ai-integration[bot] Sep 23, 2026
5cfe6a4
feat(migrate): order collaborator paragraphs, filter rows by user met…
devin-ai-integration[bot] Sep 23, 2026
1d8a653
feat(migrate): flatten generated row queries
devin-ai-integration[bot] Sep 23, 2026
94520af
Merge remote-tracking branch 'origin/develop' into feature/migrate-ta…
devin-ai-integration[bot] Sep 23, 2026
88dc153
fix(migrate): keep a property a table column reads reachable
devin-ai-integration[bot] Sep 23, 2026
a5e9e67
feat(parser): parse a $::-rooted qualified name where an expression s…
devin-ai-integration[bot] Sep 23, 2026
e15088a
feat(migrate): write DocGen documents as Document, Section and query-…
devin-ai-integration[bot] Sep 23, 2026
812053b
feat(migrate): read MagicDraw «typeModifier» on properties and parame…
devin-ai-integration[bot] Sep 23, 2026
f5c08c1
feat(migrate): lower DocGen documents to Document definitions with a …
devin-ai-integration[bot] Sep 23, 2026
3458bda
feat(migrate): execute and render migrated tables and documents
devin-ai-integration[bot] Sep 23, 2026
5275b9d
test(migrate): pin table homonyms and malformed table refusals
devin-ai-integration[bot] Sep 23, 2026
8e47bae
test(migrate): pin layout annotations on a table diagram's view
devin-ai-integration[bot] Sep 23, 2026
42cce50
docs(migrate): document table, matrix, relation map and DocGen loweri…
devin-ai-integration[bot] Sep 23, 2026
35288d3
fix(migrate): qualify document references past synthesized members
devin-ai-integration[bot] Sep 23, 2026
f403d8e
fix(migrate): reach a document's diagram view by a feature chain
devin-ai-integration[bot] Sep 23, 2026
2fb0bde
fix(migrate): write the Table Document of a diagram owned by the mode…
devin-ai-integration[bot] Sep 23, 2026
e6f9bed
fix(migrate): refuse a typeModifier over a malformed multiplicity
devin-ai-integration[bot] Sep 23, 2026
96194b1
test(xmi): pin the DocGen view tree's aggregation semantics
devin-ai-integration[bot] Sep 23, 2026
9ba2a10
fix(migrate): list what an abstract UML metaclass holds in a generic …
devin-ai-integration[bot] Sep 23, 2026
aef702e
test(libs): pin isAbstract and isIndividual across every library load…
devin-ai-integration[bot] Sep 23, 2026
861db43
fix(queryexec): refuse a dangling or cyclic alias in Named
devin-ai-integration[bot] Sep 23, 2026
466a931
fix(migrate): refuse a DocGen chain with a dangling control flow
devin-ai-integration[bot] Sep 23, 2026
1e80103
fix(migrate): follow only control flows through a DocGen method
devin-ai-integration[bot] Sep 23, 2026
9933d29
fix(migrate): refuse a DocGen view whose viewpoint method resolves to…
devin-ai-integration[bot] Sep 23, 2026
cd80d9c
fix(migrate): filter DocGen names with one WhereName so the rows keep…
devin-ai-integration[bot] Sep 23, 2026
69fcccb
fix(migrate): keep a table's column order and unique column names wit…
devin-ai-integration[bot] Sep 23, 2026
0ecc383
fix(migrate): write a table's built-in columns first and note the reo…
devin-ai-integration[bot] Sep 23, 2026
14585b3
Merge branch 'develop' into feature/migrate-tables-and-documents
devin-ai-integration[bot] Sep 23, 2026
c92d08a
Merge remote-tracking branch 'origin/develop' into feature/migrate-ta…
devin-ai-integration[bot] Sep 23, 2026
202eaf8
fix(migrate): start a whole-model table from the top-level views too
devin-ai-integration[bot] Sep 23, 2026
8fcf5b6
Merge remote-tracking branch 'origin/feature/migrate-tables-and-docum…
devin-ai-integration[bot] Sep 23, 2026
0816ca8
fix(migrate): drop a DocGen caption when showCaptions is false
devin-ai-integration[bot] Sep 23, 2026
5c2895c
fix(migrate): carry a DocGen chain's diagrams through its filters, so…
devin-ai-integration[bot] Sep 23, 2026
08a479b
fix(migrate): root a DocGen chain in each exposed element once
devin-ai-integration[bot] Sep 23, 2026
f05ce87
fix(migrate): refuse a bare module id several modules' hrefs share
devin-ai-integration[bot] Sep 23, 2026
fa431bf
fix(migrate): report a criterion excluding walked subtypes, walk Deri…
devin-ai-integration[bot] Sep 23, 2026
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
4 changes: 4 additions & 0 deletions changes/unreleased/migrate-tables-and-documents.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- **The SysML v1 migrator writes a Cameo/MagicDraw table, dependency matrix or relation map as an executable query and a renderable document.** A diagram carrying «InstanceTable», «DiagramTable» or «RelationMap» from the MagicDraw profile, or «DependencyMatrix» with its «MatrixFilter», is written beside its `view` as a `calc def '<Diagram> Rows' :> DocumentQueries::Query` — the scope as `Descendants` of the named roots, explicit rows in one `Union`, the row type as `WhereType` (and `isIndividual` for an instance table) or `WhereMetadata` for a migrated user stereotype, columns as `Project` and `Column`, sorts as `OrderBy(missing = "last", multiple = "first")`, a matrix criterion as a `RelatedColumn` over the column scope, a relation map as `RelatedElements` — and a `part def '<Diagram> Document' :> DocumentQueries::Document` holding the `Table`, so `-run-query` lists the rows and `-render-document` renders the table. Only the exact profile namespaces define a table; a same-named user stereotype elsewhere is ordinary metadata. A «DeriveReqt» criterion is walked from the original requirement, as the v2 `derivation` runs, and a criterion excluding subtypes of a stereotype the model specializes is approximated with the specializing stereotypes named, since their relationships are written as the same v2 relationship. A criterion no relationship kind spells, a malformed scope, sort, depth or criterion XML, or a table naming no row type is refused with every fault stated and the view kept.
- **The migrator writes an MDK DocGen «Document» as a `DocumentQueries::Document`.** The document's view tree becomes nested `Section`s in declaration order, and each view's viewpoint method activity is lowered from its initial node along control flow: the «Expose» suppliers are the root, `CollectOwnedElements`, `CollectOwners`, `CollectByDirectedRelationshipStereotypes`, `FilterByMetaclasses`, `FilterByStereotypes` (`include = false` as `Except`), `FilterByNames`, `SortByName`, `SortByAttribute`, `Union` forks and nested groups wrap the query, and `TableStructure`, `BulletedList`, `Paragraph`, collaborator paragraphs, `Image` and `Dynamic View` end it as a `Table`, `List`, `Paragraph`, view-backed `Diagram` or nested `Section`. A step with no query spelling (`CollectTypes`, OCL expressions, user scripts…), a recursive dynamic view, a viewpoint that names no method or a collaborator paragraph that names no view is refused with the construct quoted, and the sections around it are still written.
- **`DocumentQueries` gains `Named`, unbounded walks, matrix targets and `isIndividual`.** `Named(qualifiedName = (…))` resolves qualified names to elements, so a query can be rooted at a package or definition; `maxDepth` on `Descendants`, `Ancestors`, `RelatedElements`, `WhereRelated` and `RelatedColumn` may be omitted or `null` for no bound; `RelatedColumn(targets = …)` keeps only the related elements a second query lists, which is a dependency matrix's cell; and `WhereFeature('feature' = "isIndividual", …)` selects individuals. A declared `satisfy`/`verify` assertion typed by a requirement definition now relates its subject to that definition as well as to the assertion usage, so a matrix over requirement definitions finds its satisfiers.
- **The migrator reads MagicDraw's «typeModifier».** `[]` on a property or parameter with no collection multiplicity writes `[0..*] ordered nonunique`, `[n]` writes `[n] ordered nonunique`, and `*` on a part or item property writes it `ref`; a two-dimensional shape, `[]` on an existing collection and `*` on an attribute or parameter stay comments with the reason reported.
14 changes: 14 additions & 0 deletions cmd/sysml/manual_examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ func TestManualCookbookModelAnalysesCleanly(t *testing.T) {
t.Fatalf("cookbook query %s: %v\n%s", query, err, output)
}
}
named := exec.Command(binary, source, "-run-query", "Cookbook::NamedParts")
output, err := named.CombinedOutput()
if err != nil {
t.Fatalf("cookbook query Cookbook::NamedParts: %v\n%s", err, output)
}
for _, want := range []string{
"returned 12 rows",
"Row 1: Cookbook::telescope::primaryMirror",
"Row 6: Cookbook::Traceability::gimbal",
} {
if !strings.Contains(string(output), want) {
t.Errorf("cookbook query Cookbook::NamedParts output is missing %q:\n%s", want, output)
}
}
}

// TestManualCookbookObjectRecipes runs the cookbook's recipes over the objects
Expand Down
7 changes: 7 additions & 0 deletions docs/manual/examples/cookbook.sysml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ package Cookbook {
Ancestors(source = leaf, maxDepth = 2)
}

calc def NamedParts :> Query {
WhereType(
source = Descendants(source = Named(qualifiedName = ("Cookbook::telescope", "Cookbook::Traceability"))),
type = "PartUsage"
)
}

calc def Connections :> Query {
in root : Element;
WhereType(
Expand Down
66 changes: 51 additions & 15 deletions docs/manual/query-cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ $ sysml cookbook.sysml -run-query "Cookbook::AllParts root=Cookbook::telescope"
Row 5: Cookbook::telescope::dataPath
```

`maxDepth` bounds the walk; each level is visited in declaration order.
`maxDepth` bounds the walk; each level is visited in declaration order. Omit
it (or pass `null`) to walk the whole subtree — `Ancestors` likewise walks to
the root when unbounded.
Note that the connections are still here: a `connection` usage *is* a
`PartUsage` in the SysML metamodel (its metaclass conforms to it). Use
a feature or name filter, or `type = "ConnectionUsage"`, to separate them —
Expand All @@ -247,13 +249,43 @@ $ sysml cookbook.sysml -run-query "Cookbook::Enclosing leaf=Cookbook::telescope:

Owners are returned nearest-first, up to `maxDepth` levels.

### Elements by qualified name: `Named`

```sysml
calc def NamedParts :> Query {
WhereType(
source = Descendants(source = Named(qualifiedName = ("Cookbook::telescope", "Cookbook::Traceability"))),
type = "PartUsage"
)
}
```

```console
$ sysml cookbook.sysml -run-query "Cookbook::NamedParts"
✓ Query Cookbook::NamedParts returned 12 rows
Row 1: Cookbook::telescope::primaryMirror
Row 2: Cookbook::telescope::instrumentCluster
...
Row 6: Cookbook::Traceability::gimbal
...
```

A query parameter must be bound to a feature, so a walk rooted at a *package*
or a *definition* has nothing to bind `root` to. `Named` resolves qualified
names — spelled as strings, like the types `WhereType` takes — to the elements
they name, in the order given, and any element may be named, a package or
definition included. A name that resolves to nothing, or to more than one
element, fails the query with the name quoted rather than returning fewer rows.
The SysML v1 migration roots every table scope this way.

## Type filters

`WhereType` keeps elements whose *metamodel* type matches — `"PartUsage"`,
`"ConnectionUsage"`, `"RequirementUsage"`, `"AttributeUsage"`, `"PortUsage"`,
`"PartDefinition"` and so on — including metaclass conformance, so
`type = "Usage"` keeps every kind of usage. A name that is neither a known
metamodel type nor resolvable in the model is a typed
`type = "Usage"` keeps every kind of usage. Several names keep the elements of
any of them: `type = ("PartUsage", "PortUsage")`. A name that is neither a
known metamodel type nor resolvable in the model is a typed
`unknown-classification` error rather than a silently-empty result.

```sysml
Expand Down Expand Up @@ -281,8 +313,8 @@ attribute ([property filters](#property-filters)).
## Metadata filters

`WhereMetadata` keeps elements annotated with a metadata definition, matching
specializations of it too. The model marks `primaryMirror` with
`@Critical`:
specializations of it too; several names keep the elements annotated with any
of them. The model marks `primaryMirror` with `@Critical`:

```sysml
calc def CriticalParts :> Query {
Expand Down Expand Up @@ -467,6 +499,7 @@ are always projectable:
| `@type` | The metamodel type (`PartUsage`, ...) |
| `type` | The declared type's qualified name |
| `isAbstract` | Boolean |
| `isIndividual` | Boolean: whether a definition or usage carries the `individual` modifier |
| `multiplicityLower`, `multiplicityUpper` | Integers, `*` as unbounded |

```sysml
Expand Down Expand Up @@ -742,15 +775,15 @@ RelatedElements(
// satisfaction, verification,
// derivation or refinement
direction = "<direction>", // outgoing or incoming
maxDepth = <n>
maxDepth = <n> // omit, or null, for no bound
)
```

Direction is from the relationship's own point of view — `outgoing` follows
it as declared, `incoming` follows it backwards. Traversal is breadth-first
to `maxDepth`, deduplicated, in declaration order, and bounded by a visit
budget so a pathological model terminates with a typed error rather than
hanging.
to `maxDepth` (unbounded when omitted or `null`), deduplicated, in
declaration order, and bounded by a visit budget so a pathological model
terminates with a typed error rather than hanging.

### Connections

Expand Down Expand Up @@ -1170,12 +1203,15 @@ as the last table of its report, [`requirements.md`](examples/requirements.md).
`RelatedElements` answers one requirement at a time. To put every requirement
in one table with its satisfiers and verifiers beside it, derive the columns
from the relationships instead: a `RelatedColumn(name, relationshipKind,
direction, maxDepth, aggregate = "list")` entry of `columns` traverses the
named relationship from each row's element — the same kinds, directions and
depth bound as `RelatedElements` — and fills a cell with what it reaches.
The `aggregate` chooses the cell's shape: `"list"` (the default) holds the
related elements, `"count"` how many there are, `"any"` whether there is at
least one — an existence test that stops at the first element it reaches.
direction, maxDepth, aggregate = "list", targets)` entry of `columns`
traverses the named relationship from each row's element — the same kinds,
directions and depth bound as `RelatedElements` — and fills a cell with what
it reaches. The `aggregate` chooses the cell's shape: `"list"` (the default)
holds the related elements, `"count"` how many there are, `"any"` whether
there is at least one — an existence test that stops at the first element it
reaches. `targets`, when given, keeps only the reached elements among them:
a dependency matrix whose columns are one query and whose rows are another
is `Project(source = <rows>, columns = (RelatedColumn(..., targets = <columns>)))`.

The cookbook model's `Traceability` package holds three requirements, a
`spacecraft` whose parts satisfy them and three verification cases, two of
Expand Down
3 changes: 2 additions & 1 deletion docs/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,8 @@ answer.
| `declaredShortName` | `shortName`, absent when the short name is borrowed from a redefined or subsetted feature | |
| `documentation` | The body text of the element's `doc` comment, delimiters and indentation removed; absent when undocumented. This single-valued record reports the first body of an element declaring several — a document query's `Project` carries every body | |
| `owner` | Qualified name of the owning element; absent for a top-level element, whose owner is the document root | |
| `isAbstract` | `true`/`false` for a definition or usage; absent for anything else, and for a standard-library element restored from cache, which carries no declaration | |
| `isAbstract` | `true`/`false` for a definition or usage; absent for anything else. A standard-library element carries its declaration on every load path (parsed, restored from the on-disk cache or decoded from the bundled snapshot), so it answers too | |
| `isIndividual` | `true`/`false` for a definition or usage (the `individual` modifier); absent for anything else, and present for a standard-library element as `isAbstract` is | |
| `type` | Qualified name of the resolved type of a typed feature; absent when untyped or unresolved | |
| `multiplicityLower` | Declared lower bound | ✅ |
| `multiplicityUpper` | Declared upper bound, `*` when unbounded | ✅ |
Expand Down
1 change: 1 addition & 0 deletions docs/reference/oslc-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ bound predicate that is not in this table:
| `sysml:documentation` | `documentation` |
| `sysml:owner` | `owner` |
| `sysml:isAbstract` | `isAbstract` |
| `sysml:isIndividual` | `isIndividual` |
| `sysml:type` | `type` |
| `sysml:multiplicityLower` | `multiplicityLower` |
| `sysml:multiplicityUpper` | `multiplicityUpper` |
Expand Down
Loading
Loading