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
Original file line number Diff line number Diff line change
@@ -1 +1 @@
- The implied `ConjugatedPortDefinition` a port definition owns (SysML v2 8.3.12.3) now answers its plain Type attributes natively — `isAbstract`, `isSufficient`, `isConstant`, `isParallel` read `false`, as the RDF export states them — where the reflective read left them underived.
- The implied `ConjugatedPortDefinition` a port definition owns (SysML v2 8.3.12.3) now answers its Type attributes `isAbstract` and `isSufficient` natively as `false`, where the reflective read left them underived.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Reflective reads no longer answer `isConstant` on definitions or `isParallel` outside `StateDefinition` and `StateUsage`.
12 changes: 7 additions & 5 deletions internal/semantic/semantics/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -2282,7 +2282,7 @@ func (m *Model) reflectiveFeatureValue(sym *symbols.Symbol, feature string) (sym
// so its plain Type attributes read their defaults.
if sym.IsConjugatedPortDefinition() {
switch feature {
case "isAbstract", "isSufficient", "isConstant", "isParallel":
case "isAbstract", "isSufficient":
return boolValue(false), true
}
}
Expand All @@ -2292,10 +2292,10 @@ func (m *Model) reflectiveFeatureValue(sym *symbols.Symbol, feature string) (sym
return boolValue(d.IsAbstract || IsVariation(sym)), true
case "isSufficient":
return boolValue(d.IsAll || m.reflectiveMetaclassConforms(sym, "ConnectionDefinition")), true
case "isConstant":
return boolValue(d.IsConstant), true
case "isParallel":
return boolValue(d.IsParallel), true
if m.reflectiveMetaclassConforms(sym, "StateDefinition") {
return boolValue(d.IsParallel), true
}
}
case *ast.Usage:
switch feature {
Expand All @@ -2304,7 +2304,9 @@ func (m *Model) reflectiveFeatureValue(sym *symbols.Symbol, feature string) (sym
case "isVariant":
return boolValue(IsVariant(sym)), true
case "isParallel":
return boolValue(d.IsParallel), true
if m.reflectiveMetaclassConforms(sym, "StateUsage") {
return boolValue(d.IsParallel), true
}
}
}
if sym.Recorded() && feature == "isIndividual" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ func TestPortDefinitionOwnsItsConjugate(t *testing.T) {
if got, ok := m.LookupMember(q, "~Q"); !ok || got != conjugate {
t.Errorf("Q::'~Q' resolves to %v, want the conjugate", got)
}
// Declared by nothing, the conjugate's plain attributes read false, as the conversion states them.
for _, feature := range []string{"isAbstract", "isSufficient", "isConstant", "isParallel", "isIndividual", "isVariation"} {
for _, feature := range []string{"isAbstract", "isSufficient", "isIndividual", "isVariation"} {
if got, ok := m.ReflectiveFeatureValue(conjugate, feature); !ok || got.Kind != symbols.FilterValueBool || got.Bool {
t.Errorf("%s of ~Q = %+v (ok %v), want false", feature, got, ok)
}
}
for _, feature := range []string{"isConstant", "isParallel"} {
if got, ok := m.ReflectiveFeatureValue(conjugate, feature); ok {
t.Errorf("%s of ~Q = %+v, want absent", feature, got)
}
}

rels := m.OwnedRelationships(conjugate)
if len(rels) != 1 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package semantics

import (
"testing"

"github.com/Open-MBEE/OpenSysML/internal/semantic/symbols"
)

func TestReflectiveAttributesBelongToTheirMetaclasses(t *testing.T) {
m, root := buildModelWithStdlib(t, `package P {
part def Part;
port def Port;
state def Parallel parallel { state a; state b; }
state def Plain;
part p {
state parallelState parallel { state a; state b; }
state plainState;
}
constant part frozen;
}`)
for _, tc := range []struct {
path string
feature string
present bool
value bool
}{
{path: "P::Part", feature: "isConstant"},
{path: "P::Port", feature: "isConstant"},
{path: "P::Part", feature: "isParallel"},
{path: "P::Port", feature: "isParallel"},
{path: "P::Parallel", feature: "isParallel", present: true, value: true},
{path: "P::Plain", feature: "isParallel", present: true},
{path: "P::p::parallelState", feature: "isParallel", present: true, value: true},
{path: "P::p::plainState", feature: "isParallel", present: true},
{path: "P::p", feature: "isParallel"},
{path: "P::p", feature: "isConstant", present: true},
{path: "P::frozen", feature: "isConstant", present: true, value: true},
} {
t.Run(tc.path+"."+tc.feature, func(t *testing.T) {
sym := nestedSym(t, root, tc.path)
got, ok := m.ReflectiveFeatureValue(sym, tc.feature)
if ok != tc.present {
t.Fatalf("%s.%s = %+v (ok %t), want ok %t", tc.path, tc.feature, got, ok, tc.present)
}
if ok && (got.Kind != symbols.FilterValueBool || got.Bool != tc.value) {
t.Errorf("%s.%s = %+v, want %t", tc.path, tc.feature, got, tc.value)
}
})
}
}
Loading