Cross-file qualified references through a package's short name fail to resolve (global scope indexes declaredName only)
Summary
A qualified name whose first segment is the short name (<...>) of a top-level package defined in another file fails to resolve. The same reference resolves when written with the package's declaredName, and short names resolve correctly in every same-resource position. The asymmetry comes from the global-scope index being built from declaredName only, while the local scope provider correctly matches both memberName and memberShortName.
Environment
- Reproduced on the pilot as packaged in
jupyter-sysml-kernel 0.59.0 (SysMLInteractive / IResourceValidator.validate(..., CheckMode.ALL, ...)).
- Source references below are from tag
2026-05. The relevant code path is unchanged there (see Root cause), so the behavior is expected to persist on the latest release.
Steps to reproduce
Load each case as one or more .sysml files in the same resource set and validate.
T1 — package short name as first segment, same file → OK
package <P> Alpha { part def Foo; }
package Beta { part x : P::Foo; }
T2 — member short name as a non-first segment → OK
package Alpha { part def <F> Foo; }
package Beta { part x : Alpha::F; }
T3 — member short name, unqualified, same namespace → OK
package Alpha { part def <F> Foo; part x : F; }
T4 — package short name as first segment, references another file → FAILS
// a.sysml
package <P> Alpha { part def Foo; }
// b.sysml
package Beta { part x : P::Foo; }
Actual result
Only T4 fails:
Couldn't resolve reference to Type 'P::Foo'.
An occurrence, item or part must be typed by occurrence definitions. // cascading, from the now-untyped feature
Writing the same reference with the declared name — part x : Alpha::Foo; — resolves. Importing by short name across files (private import P::*;) fails the same way; private import Alpha::*; works.
Expected result
T4 resolves, consistent with T1–T3. A package's short name is a valid memberShortName of its namespace, and per the KerML name-resolution rules a namespace provides names for its members via both memberNames and memberShortNames. There is no stated reason why short-name qualification should work within a resource but not across resources.
Root cause
The local scope provider already handles short names. KerMLScope.xtend checks each membership under both names:
// org.omg.kerml.xtext/.../scoping/KerMLScope.xtend
var memberName = ... else mem.memberName
if (checkElementName(memberName, qn, ...)) return true
...
var memberShortName = ... else mem.memberShortName
if (checkElementName(memberShortName, qn, ...)) return true
That is why T1–T3 (and non-first segments in general) work.
For a cross-resource reference, however, the first segment is resolved through the default global index, not by model traversal:
// org.omg.kerml.xtext/.../scoping/KerMLGlobalScope.xtend (getSingleElement)
val rootName = QualifiedName.create(qualifiedName.firstSegment)
val root = outer.getSingleElement(rootName) // outer == default global scope (the exported index)
...
// subsequent segments are resolved by scopeFor(root as Namespace) — which DOES honor short names
The exported index is produced by KerMLQualifiedNameProvider, which derives qualified names from declaredName only:
// org.omg.kerml.xtext/.../naming/KerMLQualifiedNameProvider.java
private Function<EObject, String> resolver =
SimpleAttributeResolver.newResolver(String.class, "declaredName");
So a top-level element is indexed under its declaredName-based qualified name but never under its declaredShortName. When the first segment of a cross-resource reference is a short name, outer.getSingleElement(rootName) returns null, and resolution stops before the (short-name-aware) local scope is ever consulted.
This is long-standing and deliberate — introduced in the 2022-12 baseline (commit ST6RI-628, "Updated KerMLQualifiedNameProvider to use declaredName for global scope name resolution") and unchanged through 2026-05.
Impact
Multi-file models that reference each other's top-level packages by short name do not validate. A common pattern is a project split into several files, each declaring a package with a short name (package <ABC> SomeLongName { … }) and referring to the others by that short name (ABC::Something). Under the pilot every such cross-file reference fails, and each failure cascades into secondary rule violations (e.g. An occurrence, item or part must be typed by occurrence definitions., A requirement must be typed by one requirement definition.) on the now-untyped features. Rewriting every short-name qualifier to the corresponding declaredName makes the whole model validate with zero errors, which confirms the single root cause.
Suggested fix
Make cross-resource resolution consistent with local resolution by exposing short names to the global index. Options:
- In
KerMLQualifiedNameProvider, also produce a declaredShortName-based qualified name (e.g. override getFullyQualifiedNames / contribute an additional IEObjectDescription), so a top-level element is indexed under both its name and its short name; or
- In
KerMLGlobalScope.getSingleElement, fall back to looking up the first segment by short name when the declaredName lookup misses.
The local scope already honors memberShortName, so the change is isolated to the export/index side.
Cross-file qualified references through a package's short name fail to resolve (global scope indexes
declaredNameonly)Summary
A qualified name whose first segment is the short name (
<...>) of a top-level package defined in another file fails to resolve. The same reference resolves when written with the package'sdeclaredName, and short names resolve correctly in every same-resource position. The asymmetry comes from the global-scope index being built fromdeclaredNameonly, while the local scope provider correctly matches bothmemberNameandmemberShortName.Environment
jupyter-sysml-kernel0.59.0 (SysMLInteractive/IResourceValidator.validate(..., CheckMode.ALL, ...)).2026-05. The relevant code path is unchanged there (see Root cause), so the behavior is expected to persist on the latest release.Steps to reproduce
Load each case as one or more
.sysmlfiles in the same resource set and validate.T1 — package short name as first segment, same file → OK
T2 — member short name as a non-first segment → OK
T3 — member short name, unqualified, same namespace → OK
T4 — package short name as first segment, references another file → FAILS
Actual result
Only T4 fails:
Writing the same reference with the declared name —
part x : Alpha::Foo;— resolves. Importing by short name across files (private import P::*;) fails the same way;private import Alpha::*;works.Expected result
T4 resolves, consistent with T1–T3. A package's short name is a valid
memberShortNameof its namespace, and per the KerML name-resolution rules a namespace provides names for its members via bothmemberNamesandmemberShortNames. There is no stated reason why short-name qualification should work within a resource but not across resources.Root cause
The local scope provider already handles short names.
KerMLScope.xtendchecks each membership under both names:That is why T1–T3 (and non-first segments in general) work.
For a cross-resource reference, however, the first segment is resolved through the default global index, not by model traversal:
The exported index is produced by
KerMLQualifiedNameProvider, which derives qualified names fromdeclaredNameonly:So a top-level element is indexed under its
declaredName-based qualified name but never under itsdeclaredShortName. When the first segment of a cross-resource reference is a short name,outer.getSingleElement(rootName)returnsnull, and resolution stops before the (short-name-aware) local scope is ever consulted.This is long-standing and deliberate — introduced in the 2022-12 baseline (commit ST6RI-628, "Updated KerMLQualifiedNameProvider to use declaredName for global scope name resolution") and unchanged through
2026-05.Impact
Multi-file models that reference each other's top-level packages by short name do not validate. A common pattern is a project split into several files, each declaring a package with a short name (
package <ABC> SomeLongName { … }) and referring to the others by that short name (ABC::Something). Under the pilot every such cross-file reference fails, and each failure cascades into secondary rule violations (e.g.An occurrence, item or part must be typed by occurrence definitions.,A requirement must be typed by one requirement definition.) on the now-untyped features. Rewriting every short-name qualifier to the correspondingdeclaredNamemakes the whole model validate with zero errors, which confirms the single root cause.Suggested fix
Make cross-resource resolution consistent with local resolution by exposing short names to the global index. Options:
KerMLQualifiedNameProvider, also produce adeclaredShortName-based qualified name (e.g. overridegetFullyQualifiedNames/ contribute an additionalIEObjectDescription), so a top-level element is indexed under both its name and its short name; orKerMLGlobalScope.getSingleElement, fall back to looking up the first segment by short name when thedeclaredNamelookup misses.The local scope already honors
memberShortName, so the change is isolated to the export/index side.