diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag index 21456331346ac897ee8f597c52e93c1ac8edb498..19172227128b427e9cd19858a83e86cbf225ed8a 100644 --- a/src/main/jastadd/Analysis.jrag +++ b/src/main/jastadd/Analysis.jrag @@ -97,19 +97,20 @@ aspect ComponentAnalysis { // find a matching component on the RHS of the (current) super type Component c = findComponent(td, getID()); - if (c != null && !this.isEqual(c)) return c; + if (c != null && !this.usesSameTypeAs(c)) return c; } return null; } - //--- isEqual --- - syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse()); + //--- usesSameTypeAs --- + syn boolean Component.usesSameTypeAs(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse()); /** * TokenComponents may be specialized by NTATokenComponents and vice versa */ - eq TokenComponent.isEqual(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse()); + eq TokenComponent.usesSameTypeAs(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse()); + // --- isEqual --- syn boolean TypeUse.isEqual(TypeUse u); eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID()); eq ParameterizedTypeUse.isEqual(TypeUse u) { @@ -123,6 +124,8 @@ aspect ComponentAnalysis { return true; } + syn boolean Component.isEqual(Component other) = this.usesSameTypeAs(other) && this.getID().equals(other.getID()); + //--- matches --- /** * @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name @@ -225,14 +228,20 @@ aspect Constructors { //--- componentsTransitive --- syn Collection<Component> TypeDecl.componentsTransitive() { ArrayList<Component> list = new ArrayList<>(); - if (hasSuper() && getSuper().decl() != null) { - list.addAll(getSuper().decl().componentsTransitive()); - } for (Component c: getComponents()) { if (c.inConstructor()) { list.add(c); } } + int insertionIndex = 0; + if (hasSuper() && getSuper().decl() != null) { + for (Component c : getSuper().decl().componentsTransitive()) { + if (!list.stream().anyMatch(c::isEqual)) { + list.add(insertionIndex, c); + insertionIndex++; + } + } + } return list; } diff --git a/src/test/jastadd/constructors/Constructors.relast b/src/test/jastadd/constructors/Constructors.relast index 5b3d5a9eda5af27ecaef5382c3d83fb65ee3a7cf..23f473bb76ef111781f76f544555884b76cd6629 100644 --- a/src/test/jastadd/constructors/Constructors.relast +++ b/src/test/jastadd/constructors/Constructors.relast @@ -3,6 +3,7 @@ S ::= S1:A S2:A* [S3:A] /S4:A/ /S5:A*/ /[S6:A]/ /<S7>/ /<S8:long>/; B : S ::= B1:A B2:A* [B3:A] /B4:A/ /B5:A*/ /[B6:A]/ /<B7>/ /<B8:long>/; X; Y; +C : B ::= /<B8:long>/ /<B7>/ /[B6:A]/ /B5:A*/ /B4:A/ [B3:A] B2:A* B1:A; rel A.r1 -> X; rel S.r2* <-> Y.r2; diff --git a/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java b/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java index 689e991ea44e38f6cd96c6211a797b34c9041905..ba22042fa6bd4e043a523f2e0991ba6859c5a533 100644 --- a/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java +++ b/src/test/java/org/jastadd/relast/tests/ConstructorsTest.java @@ -39,6 +39,9 @@ public class ConstructorsTest { A a = new A(); S s0 = new S(); S s1 = new S(a, new List<>(), new Opt<>()); + + // S1:A S2:A* [S3:A] S.r2* + // \------ S ------/ \- rel of S -/ S s2 = new S(a, new List<>(), new Opt<>(), new ArrayList<>()); Assertions.assertEquals(3, numberOfConstructors(S.class)); } @@ -48,10 +51,25 @@ public class ConstructorsTest { A a = new A(); B b0 = new B(); B b1 = new B(a, new List<>(), new Opt<>(), a, new List<>(), new Opt<>()); + + // S1:A S2:A* [S3:A] S.r2* B1:A B2:A* [B3:A] B.r3? + // \------ S ------/ \- rel of S -/ \------ B ------/ \- rel of B -/ B b2 = new B(a, new List<>(), new Opt<>(), new ArrayList<>(), a, new List<>(), new Opt<>(), null); Assertions.assertEquals(3, numberOfConstructors(B.class)); } + @Test + public void testC() { + A a = new A(); + C c0 = new C(); + C c1 = new C(a, new List<>(), new Opt<>(), new Opt<>(), new List<>(), a); + + // S1:A S2:A* [S3:A] S.r2* B.r3? [B3:A] B2:A* B1:A + // \------ S ------/ \- rel of S -/ \- rel of B -/ \------ C ------/ + C c2 = new C(a, new List<>(), new Opt<>(), new ArrayList<>(), null, new Opt<>(), new List<>(), a); + Assertions.assertEquals(3, numberOfConstructors(B.class)); + } + private int numberOfConstructors(Class<?> clazz) { return clazz.getConstructors().length; }