diff --git a/monticore-grammar-emf/build.gradle b/monticore-grammar-emf/build.gradle index b485f71808..ed5623c7bd 100644 --- a/monticore-grammar-emf/build.gradle +++ b/monticore-grammar-emf/build.gradle @@ -92,6 +92,7 @@ test { exclude '**/SynthesizeSymTypeFromMCFullGenericTypesTest.class' exclude '**/SynthesizeSymTypeFromMCArrayTypesTest.class' exclude '**/MCType2SymTypeExpressionTest.class' + exclude '**/ComponentSymbolDeSerTest.class' } diff --git a/monticore-grammar/src/main/grammars/de/monticore/symbols/CompSymbols.mc4 b/monticore-grammar/src/main/grammars/de/monticore/symbols/CompSymbols.mc4 index 25a4fc4a71..ca1110ffac 100644 --- a/monticore-grammar/src/main/grammars/de/monticore/symbols/CompSymbols.mc4 +++ b/monticore-grammar/src/main/grammars/de/monticore/symbols/CompSymbols.mc4 @@ -14,6 +14,7 @@ component grammar CompSymbols extends de.monticore.symbols.BasicSymbols { symbolrule Component = superComponents: de.monticore.types.check.CompKindExpression* refinements: de.monticore.types.check.CompKindExpression* + parameter: de.monticore.symbols.basicsymbols._symboltable.VariableSymbol* method public List getTypeParameters() { return this.getSpannedScope().getLocalTypeVarSymbols(); diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbol.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbol.java index f4c8e2e800..ecae0c0bc7 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbol.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbol.java @@ -2,7 +2,6 @@ package de.monticore.symbols.compsymbols._symboltable; import com.google.common.base.Preconditions; -import de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol; import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; import de.monticore.types.check.CompKindExpression; import de.se_rwth.commons.logging.Log; @@ -18,32 +17,26 @@ public class ComponentSymbol extends ComponentSymbolTOP { - protected List parameters = new ArrayList<>(); - public ComponentSymbol(String name) { super(name); } - public List getParameters() { - return this.parameters; - } - public Optional getParameter(@NonNull String name) { Preconditions.checkNotNull(name); - for (VariableSymbol parameter : this.getParameters()) { + for (VariableSymbol parameter : this.getParameterList()) { if (parameter.getName().equals(name)) return Optional.of(parameter); } return Optional.empty(); } - public void addParameter(@NonNull VariableSymbol parameter) { + public boolean addParameter(@NonNull VariableSymbol parameter) { Preconditions.checkNotNull(parameter); Preconditions.checkArgument(this.getSpannedScope().getLocalVariableSymbols().contains(parameter)); - this.parameters.add(parameter); + return super.addParameter(parameter); } public boolean hasParameters() { - return !this.getParameters().isEmpty(); + return !this.getParameterList().isEmpty(); } public boolean hasTypeParameter() { diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSer.java index 6f481c6113..12689baeb1 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSer.java @@ -23,10 +23,7 @@ public class ComponentSymbolDeSer extends ComponentSymbolDeSerTOP { public static final String PARAMETERS = "parameters"; - public static final String PORTS = "ports"; - public static final String TYPE_PARAMETERS = "typeParameters"; public static final String SUPER = "super"; - public static final String SUBCOMPONENTS = "subcomponents"; public static final String REFINEMENTS = "refinements"; private FullCompKindExprDeSer compTypeExprDeSer; @@ -47,23 +44,8 @@ protected FullCompKindExprDeSer getCompTypeExprDeSer() { } @Override - public String serialize(@NonNull ComponentSymbol toSerialize, @NonNull CompSymbolsSymbols2Json s2j) { - JsonPrinter printer = s2j.getJsonPrinter(); - printer.beginObject(); - printer.member(JsonDeSers.KIND, getSerializedKind()); - printer.member(JsonDeSers.NAME, toSerialize.getName()); - - // serialize symbolrule attributes - serializeSuperComponents(toSerialize.getSuperComponentsList(), s2j); - - // Don't serialize the spanned scope (because it carries private information) - // Instead, serialize type parameters and normal parameters separately. - s2j.getTraverser().addTraversedElement(toSerialize.getSpannedScope()); // So the spanned scope is not visited - - serializeAddons(toSerialize, s2j); - printer.endObject(); - - return printer.toString(); + protected void deserializeAddons(ComponentSymbol symbol, JsonObject symbolJson) { + symbol.getParameterList().forEach(symbol.getSpannedScope()::add); } @Override @@ -90,131 +72,35 @@ protected List deserializeSuperComponents(JsonObject symbolJ } @Override - protected void serializeAddons(ComponentSymbol toSerialize, CompSymbolsSymbols2Json s2j) { - serializeParameters(toSerialize, s2j); - serializePorts(toSerialize, s2j); - serializeTypeParameters(toSerialize, s2j); - serializeSubcomponents(toSerialize, s2j); - } - - @Override - protected void deserializeAddons(ComponentSymbol symbol, JsonObject symbolJson) { - deserializeParameters(symbol, symbolJson); - deserializePorts(symbol, symbolJson); - deserializeTypeParameters(symbol, symbolJson); - } - - protected void serializeParameters(@NonNull ComponentSymbol paramOwner, @NonNull CompSymbolsSymbols2Json s2j) { + protected void serializeParameter(List parameter, CompSymbolsSymbols2Json s2j) { JsonPrinter printer = s2j.getJsonPrinter(); printer.beginArray(PARAMETERS); - paramOwner.getParameters().forEach(p -> p.accept(s2j.getTraverser())); + parameter.forEach(p -> p.accept(s2j.getTraverser())); printer.endArray(); } - protected void serializePorts(@NonNull ComponentSymbol portOwner, @NonNull CompSymbolsSymbols2Json s2j) { - JsonPrinter printer = s2j.getJsonPrinter(); - - printer.beginArray(PORTS); - portOwner.getPorts().forEach(p -> p.accept(s2j.getTraverser())); - printer.endArray(); - } - - /** - * @param paramOwner the component which owns the parameter. - * @param paramOwnerJson the component which owns the parameters, encoded as JSON. - */ - protected void deserializeParameters(@NonNull ComponentSymbol paramOwner, @NonNull JsonObject paramOwnerJson) { + @Override + protected List deserializeParameter(JsonObject symbolJson) { final String varSerializeKind = VariableSymbol.class.getCanonicalName(); - List params = paramOwnerJson.getArrayMemberOpt(PARAMETERS).orElseGet(Collections::emptyList); + List params = symbolJson.getArrayMemberOpt(PARAMETERS).orElseGet(Collections::emptyList); + List parameterResult = new ArrayList<>(params.size()); for (JsonElement param : params) { String paramJsonKind = JsonDeSers.getKind(param.getAsJsonObject()); ISymbolDeSer deSer = CompSymbolsMill.globalScope().getSymbolDeSer(paramJsonKind); if (deSer != null && deSer.getSerializedKind().equals(varSerializeKind)) { VariableSymbol paramSym = (VariableSymbol) deSer.deserialize(param.getAsJsonObject()); - - paramOwner.getSpannedScope().add(paramSym); - paramOwner.addParameter(paramSym); + parameterResult.add(paramSym); } else { Log.error(String.format( - "0xD0101 Malformed json, parameter '%s' of unsupported kind '%s'", - param.getAsJsonObject().getStringMember(JsonDeSers.NAME), paramJsonKind + "0xD0101 Malformed json, parameter '%s' of unsupported kind '%s'", + param.getAsJsonObject().getStringMember(JsonDeSers.NAME), paramJsonKind )); } } - } - - /** - * @param portOwner the component which owns the parameter. - * @param paramOwnerJson the component which owns the parameters, encoded as JSON. - */ - protected void deserializePorts(@NonNull ComponentSymbol portOwner, @NonNull JsonObject paramOwnerJson) { - final String portSerializeKind = PortSymbol.class.getCanonicalName(); - - List ports = paramOwnerJson.getArrayMemberOpt(PORTS).orElseGet(Collections::emptyList); - - for (JsonElement port : ports) { - String portJsonKind = JsonDeSers.getKind(port.getAsJsonObject()); - ISymbolDeSer deSer = CompSymbolsMill.globalScope().getSymbolDeSer(portJsonKind); - if (deSer != null && deSer.getSerializedKind().equals(portSerializeKind)) { - PortSymbol portSym = (PortSymbol) deSer.deserialize(port.getAsJsonObject()); - - portOwner.getSpannedScope().add(portSym); - } else { - Log.error(String.format( - "0xD0102 Malformed json, port '%s' of unsupported kind '%s'", - port.getAsJsonObject().getStringMember(JsonDeSers.NAME), portJsonKind - )); - } - } - } - - protected void serializeTypeParameters(@NonNull ComponentSymbol typeParamOwner, CompSymbolsSymbols2Json s2j) { - JsonPrinter printer = s2j.getJsonPrinter(); - - printer.beginArray(TYPE_PARAMETERS); - typeParamOwner.getTypeParameters().forEach(tp -> tp.accept(s2j.getTraverser())); - printer.endArray(); - } - - /** - * @param typeParamOwner the component which owns the parameter. - * @param typeParamOwnerJson the component which owns the type parameters, encoded as JSON. - */ - protected void deserializeTypeParameters(@NonNull ComponentSymbol typeParamOwner, - @NonNull JsonObject typeParamOwnerJson) { - final String typeVarSerializedKind = "de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol"; - - List typeParams = - typeParamOwnerJson - .getArrayMemberOpt(TYPE_PARAMETERS) - .orElseGet(Collections::emptyList); - - for (JsonElement typeParam : typeParams) { - String typeParamJsonKind = JsonDeSers.getKind(typeParam.getAsJsonObject()); - ISymbolDeSer deSer = CompSymbolsMill.globalScope().getSymbolDeSer(typeParamJsonKind); - if (deSer != null && deSer.getSerializedKind().equals(typeVarSerializedKind)) { - TypeVarSymbol typeParamSym = (TypeVarSymbol) deSer.deserialize(typeParam.getAsJsonObject()); - - typeParamOwner.getSpannedScope().add(typeParamSym); - } else { - Log.error(String.format( - "0xD0103 Malformed json, type parameter '%s' of unsupported kind '%s'", - typeParam.getAsJsonObject().getStringMember(JsonDeSers.NAME), typeParamJsonKind - )); - - } - } - } - - protected void serializeSubcomponents(@NonNull ComponentSymbol portOwner, @NonNull CompSymbolsSymbols2Json s2j) { - JsonPrinter printer = s2j.getJsonPrinter(); - - printer.beginArray(SUBCOMPONENTS); - portOwner.getSubcomponents().forEach(p -> p.accept(s2j.getTraverser())); - printer.endArray(); + return parameterResult; } @Override diff --git a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/SubcomponentSymbolDeSer.java b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/SubcomponentSymbolDeSer.java index a91a015d5c..fd5401686d 100644 --- a/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/SubcomponentSymbolDeSer.java +++ b/monticore-grammar/src/main/java/de/monticore/symbols/compsymbols/_symboltable/SubcomponentSymbolDeSer.java @@ -33,6 +33,6 @@ protected void serializeType(CompKindExpression type, CompSymbolsSymbols2Json s2 @Override protected CompKindExpression deserializeType(JsonObject symbolJson) { - return null; + return this.getCompKindExprDeSer().deserialize(symbolJson.getObjectMember("type")); } } diff --git a/monticore-grammar/src/main/java/de/monticore/types/check/CompKindExpression.java b/monticore-grammar/src/main/java/de/monticore/types/check/CompKindExpression.java index 59496cec3e..c6d48d08e2 100644 --- a/monticore-grammar/src/main/java/de/monticore/types/check/CompKindExpression.java +++ b/monticore-grammar/src/main/java/de/monticore/types/check/CompKindExpression.java @@ -74,25 +74,25 @@ public void bindParams() { LinkedHashMap parameterBindings = new LinkedHashMap<>(); // We know LinkedHashMaps are ordered by insertion time. As we rely on the fact that the ordering of the // arguments is consistent with the ordering in the map, the following iteration ensures it: - for (int i = 0; i < this.getTypeInfo().getParameters().size(); i++) { + for (int i = 0; i < this.getTypeInfo().getParameterList().size(); i++) { if (i < parameterArguments.size()) // Deal with wrong number of parameters through cocos if (parameterArguments.get(i) instanceof ASTAssignmentExpression && ((ASTAssignmentExpression) parameterArguments.get(i)).getLeft() instanceof ASTNameExpression) { keywordExpressionMap.put(((ASTNameExpression) ((ASTAssignmentExpression) parameterArguments.get(i)) .getLeft()).getName(), parameterArguments.get(i)); } else { - parameterBindings.put(this.getTypeInfo().getParameters().get(i), parameterArguments.get(i)); + parameterBindings.put(this.getTypeInfo().getParameterList().get(i), parameterArguments.get(i)); firstKeywordArgument++; } } // iterate over keyword-based arguments (CoCo assures that no position-based argument occurs // after the first keyword-based argument) - for (int j = firstKeywordArgument; j < this.getTypeInfo().getParameters().size(); j++) { - if (keywordExpressionMap.containsKey(this.getTypeInfo().getParameters().get(j).getName()) && - !parameterBindings.containsKey(this.getTypeInfo().getParameters().get(j))) { - parameterBindings.put(this.getTypeInfo().getParameters().get(j), - keywordExpressionMap.get(this.getTypeInfo().getParameters().get(j).getName())); + for (int j = firstKeywordArgument; j < this.getTypeInfo().getParameterList().size(); j++) { + if (keywordExpressionMap.containsKey(this.getTypeInfo().getParameterList().get(j).getName()) && + !parameterBindings.containsKey(this.getTypeInfo().getParameterList().get(j))) { + parameterBindings.put(this.getTypeInfo().getParameterList().get(j), + keywordExpressionMap.get(this.getTypeInfo().getParameterList().get(j).getName())); } } diff --git a/monticore-grammar/src/test/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSerTest.java b/monticore-grammar/src/test/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSerTest.java new file mode 100644 index 0000000000..a4c8f79aae --- /dev/null +++ b/monticore-grammar/src/test/java/de/monticore/symbols/compsymbols/_symboltable/ComponentSymbolDeSerTest.java @@ -0,0 +1,361 @@ +/* (c) https://github.com/MontiCore/monticore */ +package de.monticore.symbols.compsymbols._symboltable; + + +import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol; +import de.monticore.symbols.compsymbols.CompSymbolsMill; +import de.monticore.symboltable.serialization.json.JsonElement; +import de.monticore.types.check.CompKindExpression; +import de.monticore.types.check.FullCompKindExprDeSer; +import de.monticore.types.check.KindOfComponent; +import de.monticore.types.check.KindOfComponentDeSer; +import de.monticore.types.check.SymTypeExpressionFactory; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Path; + +import static java.nio.file.Files.readString; + +public class ComponentSymbolDeSerTest { + + protected static final String RELATIVE_DIR = "src/test/resources/de/monticore/symbols/compsymbols/_symboltable/"; + + protected ComponentSymbolDeSer deSer; + protected CompSymbolsSymbols2Json arc2json; + + @BeforeEach + void setup() { + CompSymbolsMill.reset(); + CompSymbolsMill.init(); + BasicSymbolsMill.initializePrimitives(); + + deSer = new ComponentSymbolDeSer(new FullTestCompKindDeser()); + CompSymbolsMill.globalScope().putSymbolDeSer(deSer.getSerializedKind(), deSer); + SubcomponentSymbolDeSer subDeSer = new SubcomponentSymbolDeSer(new FullTestCompKindDeser()); + CompSymbolsMill.globalScope().putSymbolDeSer(subDeSer.getSerializedKind(), subDeSer); + arc2json = new CompSymbolsSymbols2Json(); + } + + @Test + void shouldSerializeSuperComponentType() throws IOException { + // Given + // create a symbol for the super component type + ComponentSymbol superCType = CompSymbolsMill.componentSymbolBuilder() + .setName("SuperCType") + .setSpannedScope(CompSymbolsMill.scope()) + .build(); + + // create a reference to the super component type + CompKindExpression parentType = new KindOfComponent(superCType) {}; + + // create a symbol for a component type, reference its super type + ComponentSymbol cType = CompSymbolsMill.componentSymbolBuilder() + .setName("CompTypeWithSuper1") + .setSpannedScope(CompSymbolsMill.scope()) + .addSuperComponents(parentType) + .build(); + + // When + String actual = deSer.serialize(cType, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithSuper1.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, actual); + } + + @Test + void shouldSerializeSuperComponentType2() throws IOException { + // Given + // create symbols for the two super component types + ComponentSymbol superCType1 = CompSymbolsMill.componentSymbolBuilder() + .setName("SuperCType1") + .setSpannedScope(CompSymbolsMill.scope()) + .build(); + ComponentSymbol superCType2 = CompSymbolsMill.componentSymbolBuilder() + .setName("SuperCType2") + .setSpannedScope(CompSymbolsMill.scope()) + .build(); + + // create a reference for to each of the two super component types + CompKindExpression parentType1 = new KindOfComponent(superCType1); + CompKindExpression parentType2 = new KindOfComponent(superCType2); + + // symbol for a component type, reference its super types + ComponentSymbol cType = CompSymbolsMill.componentSymbolBuilder() + .setName("CompTypeWithSuper2") + .setSpannedScope(CompSymbolsMill.scope()) + .addSuperComponents(parentType1) + .addSuperComponents(parentType2) + .build(); + + // When + String actual = deSer.serialize(cType, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithSuper2.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, actual); + } + + @Test + void shouldNotSerializeAbsent() throws IOException { + // Given + ComponentSymbol comp = createSimpleComp(); + + // When + String createdJson = deSer.serialize(comp, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "Simple.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, createdJson); + } + + @Test + void shouldSerializeTypeParameters() throws IOException { + // Given + ComponentSymbol comp = createSimpleComp(); + comp.getSpannedScope().add( + CompSymbolsMill.typeVarSymbolBuilder() + .setName("A") + .setSpannedScope(CompSymbolsMill.scope()) + .build() + ); + comp.getSpannedScope().add( + CompSymbolsMill.typeVarSymbolBuilder() + .setName("B") + .setSpannedScope(CompSymbolsMill.scope()) + .build() + ); + + // When + String createdJson = deSer.serialize(comp, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithTypeParams.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, createdJson); + } + + @Test + void shouldSerializeParameters() throws IOException { + // Given + ComponentSymbol comp = createSimpleComp(); + VariableSymbol paramA = CompSymbolsMill.variableSymbolBuilder() + .setName("a") + .setType(SymTypeExpressionFactory.createPrimitive("int")) + .build(); + VariableSymbol paramB = CompSymbolsMill.variableSymbolBuilder() + .setName("b") + .setType(SymTypeExpressionFactory.createPrimitive("int")) + .build(); + + comp.getSpannedScope().add(paramA); + comp.getSpannedScope().add(paramB); + comp.addParameter(paramA); + comp.addParameter(paramB); + + // When + String createdJson = deSer.serialize(comp, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithParams.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, createdJson); + } + + @Test + void shouldSerializePorts() throws IOException { + // Given + ComponentSymbol comp = createSimpleComp(); + PortSymbol portIncoming = CompSymbolsMill.portSymbolBuilder() + .setName("inc") + .setIncoming(true) + .setType(SymTypeExpressionFactory.createPrimitive("int")) + .setTiming(Timing.TIMED) + .setStronglyCausal(false) + .build(); + PortSymbol portOutgoing = CompSymbolsMill.portSymbolBuilder() + .setName("outg") + .setOutgoing(true) + .setType(SymTypeExpressionFactory.createPrimitive("int")) + .setTiming(Timing.TIMED) + .setStronglyCausal(false) + .build(); + + comp.getSpannedScope().add(portIncoming); + comp.getSpannedScope().add(portOutgoing); + + + // When + String createdJson = deSer.serialize(comp, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithPorts.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, createdJson); + } + + @Test + void shouldDeserializeParent() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "WithParent.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertFalse(comp.isEmptySuperComponents(), "Parent not present"); + Assertions.assertEquals("Parent", comp.getSuperComponents(0).printName()); + } + + @Test + void shouldNotDeserializeAbsentParent() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "Simple.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertTrue(comp.isEmptySuperComponents(), "Parent is present"); + } + + @Test + void shouldDeserializeTypeParameters() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "WithTypeParams.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertEquals(2, comp.getTypeParameters().size()); + Assertions.assertAll( + () -> Assertions.assertEquals("A", comp.getTypeParameters().get(0).getName()), + () -> Assertions.assertEquals("B", comp.getTypeParameters().get(1).getName()) + ); + } + + @Test + void shouldDeserializeParameters() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "WithParams.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertEquals(2, comp.getParameterList().size()); + Assertions.assertEquals(2, comp.getSpannedScope().getLocalVariableSymbols().size()); + Assertions.assertAll( + () -> Assertions.assertEquals("a", comp.getParameterList().get(0).getName()), + () -> Assertions.assertEquals("b", comp.getParameterList().get(1).getName()), + () -> Assertions.assertTrue(comp.getSpannedScope().resolveVariable("a").isPresent()), + () -> Assertions.assertTrue(comp.getSpannedScope().resolveVariable("b").isPresent()), + () -> Assertions.assertEquals(comp.getSpannedScope().resolveVariable("a").get(), comp.getParameterList().get(0)), + () -> Assertions.assertEquals(comp.getSpannedScope().resolveVariable("b").get(), comp.getParameterList().get(1)) + ); + } + + @Test + void shouldDeserializePorts() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "WithPorts.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertEquals(2, comp.getPorts().size()); + Assertions.assertEquals(2, comp.getSpannedScope().getLocalPortSymbols().size()); + Assertions.assertAll( + () -> Assertions.assertEquals("inc", comp.getPorts().get(0).getName()), + () -> Assertions.assertEquals("outg", comp.getPorts().get(1).getName()), + () -> Assertions.assertTrue(comp.getSpannedScope().resolvePort("inc").isPresent()), + () -> Assertions.assertTrue(comp.getSpannedScope().resolvePort("outg").isPresent()), + () -> Assertions.assertEquals(comp.getSpannedScope().resolvePort("inc").get(), comp.getPorts().get(0)), + () -> Assertions.assertEquals(comp.getSpannedScope().resolvePort("outg").get(), comp.getPorts().get(1)) + ); + } + + @Test + void shouldSerializeSubComponents() throws IOException { + // Given + ComponentSymbol comp = createParentComp(); + comp.getSpannedScope().add( + CompSymbolsMill.subcomponentSymbolBuilder() + .setName("inst") + .setType(new KindOfComponent(createSimpleComp())) + .build() + ); + + // When + String createdJson = deSer.serialize(comp, arc2json); + + // the expected result + Path json = Path.of(RELATIVE_DIR, "WithSub.json"); + String expected = readString(json).replaceAll("\\s+", ""); + + // Then + Assertions.assertEquals(expected, createdJson); + } + + @Test + void shouldDeserializeSubComponents() throws IOException { + // When + Path json = Path.of(RELATIVE_DIR, "WithSub.json"); + String jsonString = readString(json).replaceAll("\\s+", ""); + ComponentSymbol comp = deSer.deserialize(jsonString); + + // Then + Assertions.assertEquals(1, comp.getSubcomponents().size()); + Assertions.assertEquals(1, comp.getSpannedScope().getLocalSubcomponentSymbols().size()); + Assertions.assertAll( + () -> Assertions.assertEquals("inst", comp.getSubcomponents().get(0).getName()), + () -> Assertions.assertTrue(comp.getSpannedScope().resolveSubcomponent("inst").isPresent()), + () -> Assertions.assertEquals(comp.getSpannedScope().resolveSubcomponent("inst").get(), comp.getSubcomponents().get(0)) + ); + } + + protected static ComponentSymbol createSimpleComp() { + return CompSymbolsMill.componentSymbolBuilder() + .setName("Comp") + .setSpannedScope(CompSymbolsMill.scope()) + .build(); + } + + protected static ComponentSymbol createParentComp() { + return CompSymbolsMill.componentSymbolBuilder() + .setName("Parent") + .setSpannedScope(CompSymbolsMill.scope()) + .build(); + } + + static class FullTestCompKindDeser implements FullCompKindExprDeSer { + KindOfComponentDeSer kindOfComponentDeSer = new KindOfComponentDeSer(); + + @Override + public String serializeAsJson(@NonNull CompKindExpression toSerialize) { + return kindOfComponentDeSer.serializeAsJson((KindOfComponent) toSerialize); + } + + @Override + public CompKindExpression deserialize(@NonNull JsonElement serialized) { + return kindOfComponentDeSer.deserialize(serialized.getAsJsonObject()); + } + } +} diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/Simple.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/Simple.json new file mode 100644 index 0000000000..f365b5ede7 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/Simple.json @@ -0,0 +1,5 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Comp", + "fullName": "Comp" +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParams.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParams.json new file mode 100644 index 0000000000..32242dab69 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParams.json @@ -0,0 +1,25 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Comp", + "fullName": "Comp", + "parameters": [ + { + "kind": "de.monticore.symbols.basicsymbols._symboltable.VariableSymbol", + "name": "a", + "fullName": "Comp.a", + "type": { + "kind": "de.monticore.types.check.SymTypePrimitive", + "primitiveName": "int" + } + }, + { + "kind": "de.monticore.symbols.basicsymbols._symboltable.VariableSymbol", + "name": "b", + "fullName": "Comp.b", + "type": { + "kind": "de.monticore.types.check.SymTypePrimitive", + "primitiveName": "int" + } + } + ] +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParent.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParent.json new file mode 100644 index 0000000000..d2ebe9ea53 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithParent.json @@ -0,0 +1,11 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Comp", + "fullName": "Comp", + "super": [ + { + "kind": "de.monticore.types.check.KindOfComponent", + "componentName": "Parent" + } + ] +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithPorts.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithPorts.json new file mode 100644 index 0000000000..d1542eb4dc --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithPorts.json @@ -0,0 +1,31 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Comp", + "fullName": "Comp", + "spannedScope": { + "symbols": [ + { + "kind": "de.monticore.symbols.compsymbols._symboltable.PortSymbol", + "name": "inc", + "fullName": "Comp.inc", + "type": { + "kind": "de.monticore.types.check.SymTypePrimitive", + "primitiveName": "int" + }, + "incoming": true, + "timing": "timed" + }, + { + "kind": "de.monticore.symbols.compsymbols._symboltable.PortSymbol", + "name": "outg", + "fullName": "Comp.outg", + "type": { + "kind": "de.monticore.types.check.SymTypePrimitive", + "primitiveName": "int" + }, + "outgoing": true, + "timing": "timed" + } + ] + } +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSub.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSub.json new file mode 100644 index 0000000000..77c7547128 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSub.json @@ -0,0 +1,18 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Parent", + "fullName": "Parent", + "spannedScope": { + "symbols": [ + { + "kind": "de.monticore.symbols.compsymbols._symboltable.SubcomponentSymbol", + "name": "inst", + "fullName": "Parent.inst", + "type": { + "kind": "de.monticore.types.check.KindOfComponent", + "componentName": "Comp" + } + } + ] + } +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper1.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper1.json new file mode 100644 index 0000000000..7e0f9c062f --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper1.json @@ -0,0 +1,11 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "CompTypeWithSuper1", + "fullName": "CompTypeWithSuper1", + "super": [ + { + "kind": "de.monticore.types.check.KindOfComponent", + "componentName": "SuperCType" + } + ] +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper2.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper2.json new file mode 100644 index 0000000000..5045fd3b35 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithSuper2.json @@ -0,0 +1,15 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "CompTypeWithSuper2", + "fullName": "CompTypeWithSuper2", + "super": [ + { + "kind": "de.monticore.types.check.KindOfComponent", + "componentName": "SuperCType1" + }, + { + "kind": "de.monticore.types.check.KindOfComponent", + "componentName": "SuperCType2" + } + ] +} \ No newline at end of file diff --git a/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithTypeParams.json b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithTypeParams.json new file mode 100644 index 0000000000..0a0cfb79e3 --- /dev/null +++ b/monticore-grammar/src/test/resources/de/monticore/symbols/compsymbols/_symboltable/WithTypeParams.json @@ -0,0 +1,19 @@ +{ + "kind": "de.monticore.symbols.compsymbols._symboltable.ComponentSymbol", + "name": "Comp", + "fullName": "Comp", + "spannedScope": { + "symbols": [ + { + "kind": "de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol", + "name": "A", + "fullName": "Comp.A" + }, + { + "kind": "de.monticore.symbols.basicsymbols._symboltable.TypeVarSymbol", + "name": "B", + "fullName": "Comp.B" + } + ] + } +} \ No newline at end of file