diff --git a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/GetterDecorator.java b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/GetterDecorator.java index c1d55f96e..176a46da8 100644 --- a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/GetterDecorator.java +++ b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/GetterDecorator.java @@ -11,7 +11,7 @@ import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.cd4codebasis._ast.ASTCDParameter; import de.monticore.cdbasis._ast.ASTCDAttribute; -import de.monticore.cdbasis._ast.ASTCDClass; +import de.monticore.cdbasis._ast.ASTCDType; import de.monticore.cdbasis._visitor.CDBasisVisitor2; import de.monticore.generating.templateengine.HookPoint; import de.monticore.generating.templateengine.TemplateHookPoint; @@ -39,28 +39,28 @@ public void visit(ASTCDAttribute attribute) { // Retrieve the parent of the attribute var originalClazz = decoratorData.getParent(attribute).get(); // - var decClazz = (ASTCDClass) decoratorData.getAsDecorated(originalClazz); + var decType = (ASTCDType) decoratorData.getAsDecorated(originalClazz); if (MCTypeFacade.getInstance().isBooleanType(attribute.getMCType())) { - decorateMandatory(decClazz, attribute); + decorateMandatory(decType, attribute); } else if (MCCollectionSymTypeRelations.isList(attribute.getSymbol().getType())) { - decorateList(decClazz, attribute); - decorateWithAssocFunctions(decClazz, attribute, true); + decorateList(decType, attribute); + decorateWithAssocFunctions(decType, attribute, true); } else if (MCCollectionSymTypeRelations.isSet(attribute.getSymbol().getType())) { - decorateSet(decClazz, attribute); - decorateWithAssocFunctions(decClazz, attribute, false); + decorateSet(decType, attribute); + decorateWithAssocFunctions(decType, attribute, false); } else if (MCCollectionSymTypeRelations.isOptional(attribute.getSymbol().getType())) { - decorateOptional(decClazz, attribute); + decorateOptional(decType, attribute); } else { - decorateMandatory(decClazz, attribute); + decorateMandatory(decType, attribute); } } } - protected void decorateMandatory(ASTCDClass decoratedClazz, ASTCDAttribute attribute) { + protected void decorateMandatory(ASTCDType decoratedClazz, ASTCDAttribute attribute) { String name = (MCTypeFacade.getInstance().isBooleanType(attribute.getMCType()) ? "is" : "get") + StringTransformations.capitalize(attribute.getName()); ASTMCType type = attribute.getMCType().deepClone(); @@ -75,7 +75,7 @@ protected void decorateMandatory(ASTCDClass decoratedClazz, ASTCDAttribute attri this.updateModifier(attribute); } - protected void decorateOptional(ASTCDClass decoratedClazz, ASTCDAttribute attribute) { + protected void decorateOptional(ASTCDType decoratedClazz, ASTCDAttribute attribute) { String name = "get" + StringTransformations.capitalize(attribute.getName()); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -102,7 +102,7 @@ protected void decorateOptional(ASTCDClass decoratedClazz, ASTCDAttribute attrib this.updateModifier(attribute); } - protected void decorateSet(ASTCDClass decoratedClazz, ASTCDAttribute attribute) { + protected void decorateSet(ASTCDType decoratedClazz, ASTCDAttribute attribute) { String name = "get" + StringTransformations.capitalize(attribute.getName()); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -116,7 +116,7 @@ protected void decorateSet(ASTCDClass decoratedClazz, ASTCDAttribute attribute) this.updateModifier(attribute); } - protected void decorateList(ASTCDClass decoratedClazz, ASTCDAttribute attribute) { + protected void decorateList(ASTCDType decoratedClazz, ASTCDAttribute attribute) { String name = "get" + StringTransformations.capitalize(attribute.getName()); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -130,7 +130,7 @@ protected void decorateList(ASTCDClass decoratedClazz, ASTCDAttribute attribute) this.updateModifier(attribute); } - protected void decorateWithAssocFunctions(ASTCDClass decoratedClazz, ASTCDAttribute attribute, + protected void decorateWithAssocFunctions(ASTCDType decoratedClazz, ASTCDAttribute attribute, boolean isList) { ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); diff --git a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/SetterDecorator.java b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/SetterDecorator.java index 0e59e4d7e..451d0a466 100644 --- a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/SetterDecorator.java +++ b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/SetterDecorator.java @@ -11,7 +11,7 @@ import de.monticore.cd4codebasis._ast.ASTCDMethod; import de.monticore.cd4codebasis._ast.ASTCDParameter; import de.monticore.cdbasis._ast.ASTCDAttribute; -import de.monticore.cdbasis._ast.ASTCDClass; +import de.monticore.cdbasis._ast.ASTCDType; import de.monticore.cdbasis._visitor.CDBasisVisitor2; import de.monticore.generating.templateengine.GlobalExtensionManagement; import de.monticore.generating.templateengine.TemplateHookPoint; @@ -48,7 +48,7 @@ public void visit(ASTCDAttribute attribute) { if (decoratorData.shouldDecorate(this.getClass(), attribute)) { var originalClazz = decoratorData.getParent(attribute); - var decClazz = (ASTCDClass) decoratorData.getAsDecorated(originalClazz.get()); + var decClazz = (ASTCDType) decoratorData.getAsDecorated(originalClazz.get()); var info = decoratorData.getAttrHelper().getFromSymTypeExpr(attribute.getSymbol().getType()); @@ -80,14 +80,14 @@ public void visit(ASTCDAttribute attribute) { } } - protected MethodInformation decorateMandatory(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateMandatory(ASTCDType clazz, ASTCDAttribute attribute) { String name = "set" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); return decorate(clazz, attribute, SetterMethodKind.SET_MANDATORY_OR_OPT, "methods.Set", name, CDParameterFacade.getInstance().createParameters(attribute), attribute); } - protected MethodInformation decorateOptSet(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateOptSet(ASTCDType clazz, ASTCDAttribute attribute) { String name = "set" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -96,14 +96,14 @@ protected MethodInformation decorateOptSet(ASTCDClass clazz, ASTCDAttribute attr attribute, "--unused--"); } - protected MethodInformation decorateOptionalAbsent(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateOptionalAbsent(ASTCDType clazz, ASTCDAttribute attribute) { String name = "set" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())) + "Absent"; return decorate(clazz, attribute, SetterMethodKind.UNSET_OPTIONAL, "methods.opt.SetAbsent", name, List.of(), attribute); } - protected MethodInformation decorateAddWithIndex(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateAddWithIndex(ASTCDType clazz, ASTCDAttribute attribute) { String name = "add" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -112,7 +112,7 @@ protected MethodInformation decorateAddWithIndex(ASTCDClass clazz, ASTCDAttribut .getInstance().createParameter(type, attribute.getName())), attribute); } - protected MethodInformation decorateRemoveWithIndex(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateRemoveWithIndex(ASTCDType clazz, ASTCDAttribute attribute) { String name = "remove" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -123,7 +123,7 @@ protected MethodInformation decorateRemoveWithIndex(ASTCDClass clazz, ASTCDAttri return m; } - protected MethodInformation decorateAddUnordered(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateAddUnordered(ASTCDType clazz, ASTCDAttribute attribute) { String name = "add" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -134,7 +134,7 @@ protected MethodInformation decorateAddUnordered(ASTCDClass clazz, ASTCDAttribut return m; } - protected MethodInformation decorateRemoveUnordered(ASTCDClass clazz, ASTCDAttribute attribute) { + protected MethodInformation decorateRemoveUnordered(ASTCDType clazz, ASTCDAttribute attribute) { String name = "remove" + StringUtils.capitalize(StringTransformations.capitalize(attribute .getName())); ASTMCType type = getCDGenService().getFirstTypeArgument(attribute.getMCType()).deepClone(); @@ -145,7 +145,7 @@ protected MethodInformation decorateRemoveUnordered(ASTCDClass clazz, ASTCDAttri return m; } - protected MethodInformation decorate(ASTCDClass decParent, ASTCDAttribute attribute, + protected MethodInformation decorate(ASTCDType decParent, ASTCDAttribute attribute, SetterMethodKind kind, String templateName, String methodName, List params, Object... templateParams) { diff --git a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/data/AbstractDecorator.java b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/data/AbstractDecorator.java index 98b61af79..db0337954 100644 --- a/cdlang/src/main/java/de/monticore/cd/codegen/decorators/data/AbstractDecorator.java +++ b/cdlang/src/main/java/de/monticore/cd/codegen/decorators/data/AbstractDecorator.java @@ -35,7 +35,7 @@ else if (decoratedParent instanceof ASTCDPackage) .getName()); } - protected void addToClass(ASTCDClass clazz, ASTCDMember member) { + protected void addToClass(ASTCDType clazz, ASTCDMember member) { // TODO: Only add iff not yet present (#4310) clazz.addCDMember(member); } diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 4bb9f5b26..7059e8f7c 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java +++ b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java @@ -9,6 +9,7 @@ import de.monticore.cd.codegen.trafo.DefaultVisibilityPublicTrafo; import de.monticore.cd.codegen.trafo.TOPTrafo; import de.monticore.cd.methodtemplates.CD4C; +import de.monticore.cd4analysis._symboltable.ICD4AnalysisScope; import de.monticore.cd4analysis._util.CD4AnalysisTypeDispatcher; import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromAllRoles; import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromNavigableRoles; @@ -18,6 +19,7 @@ import de.monticore.cdbasis.CDBasisMill; import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; +import de.monticore.cdbasis._symboltable.CDPackageSymbol; import de.monticore.cdbasis.trafo.CDBasisDefaultPackageTrafo; import de.monticore.cdinterfaceandenum._ast.ASTCDEnum; import de.monticore.cdinterfaceandenum._ast.ASTCDInterface; @@ -337,9 +339,28 @@ public void createAndExportDecoratedSymbolTable(ASTCDCompilationUnit decorated, // Complete the symbol-table (symbol table creation phase 2) this.completeSymbolTable(decorated); - // Store the decorated symbol table - this.storeSymbols(decoratedScope, Paths.get(symbolOutPath, Names.getPathFromPackage( - decoratedScope.getFullName()) + ".deccdsym").toString()); + // The generated code does not have a larger "diagram" (symbol/scope) + // we thus output one symbol table per root-package + for (ICD4AnalysisScope subScope : decoratedScope.getSubScopes()) { + if (subScope.getSpanningSymbol() instanceof CDPackageSymbol) { + CDPackageSymbol symbol = (CDPackageSymbol) subScope.getSpanningSymbol(); + // Extract the package diagram into its own artifact + ICD4CodeArtifactScope as2store = CD4CodeMill.artifactScope(); + as2store.setName(subScope.getName()); + // do not set a package name + as2store.add(symbol); + + // Store the decorated symbol table of this package + this.storeSymbols(as2store, Paths.get(symbolOutPath, Names.getPathFromPackage(as2store + .getFullName()) + ".deccdsym").toString()); + } + else { + Log.warn("0xTODO: Skipping export of symbol type " + subScope.getSpanningSymbol() + .getClass()); + } + } + + // Note: The packagename + full name might be really weird in the exported file } /** diff --git a/cdlang/src/test/java/de/monticore/cdgen/CDGenToolTest.java b/cdlang/src/test/java/de/monticore/cdgen/CDGenToolTest.java index 4dbd1e49f..eda1d1630 100644 --- a/cdlang/src/test/java/de/monticore/cdgen/CDGenToolTest.java +++ b/cdlang/src/test/java/de/monticore/cdgen/CDGenToolTest.java @@ -5,14 +5,17 @@ import static org.junit.jupiter.api.Assertions.fail; import de.monticore.cd4code.CD4CodeMill; +import de.monticore.io.paths.MCPath; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.se_rwth.commons.Names; import de.se_rwth.commons.logging.LogStub; + import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -27,14 +30,13 @@ class CDGenToolTest { @BeforeEach public void before() { - CD4CodeMill.globalScope().clear(); CD4CodeMill.reset(); BasicSymbolsMill.reset(); LogStub.init(); } @Test - void testTransfersImportStatements() { + void testTransfersImportStatementsAndDecSym() throws IOException { // Given String packageName = "P"; String diagramName = "D"; @@ -42,7 +44,7 @@ void testTransfersImportStatements() { String importStatement = "import java.nio.file.Path;"; - String model = String.format("package %s;" + "%s" + "classdiagram %s {" + " class %s { " + String model = String.format("package %s;" + "%s\n" + "classdiagram %s {" + " class %s { " + "void voidMethod();" + "String stringMethod();" + "static void staticVoidMethod();" + "static String staticStringMethod();" + " }" + "}", packageName, importStatement, diagramName, className); @@ -51,23 +53,38 @@ void testTransfersImportStatements() { CDGenTool tool = new CDGenTool(); + Path codeOutput = outputDir.resolve("code"); + Path decSymbolOutput = outputDir.resolve("decsym"); + // When - tool.run(new String[] { "-i", inputDir.toAbsolutePath().toString(), "-o", outputDir - .toAbsolutePath().toString(), "-c2mc" }); + tool.run(new String[] { "-i", inputDir.toAbsolutePath().toString(), "-o", codeOutput + .toAbsolutePath().toString(), "-c2mc", "-sd", decSymbolOutput.toAbsolutePath() + .toString(), }); // Then - Path diagramTgtPath = outputDir.toAbsolutePath().resolve(Names.getPathFromPackage(packageName)) + Path diagramTgtPath = codeOutput.toAbsolutePath().resolve(Names.getPathFromPackage(packageName)) .resolve(diagramName).resolve(className + ".java"); assertTrue(diagramTgtPath.toFile().isFile()); - try { - String generated = Files.readString(diagramTgtPath, StandardCharsets.UTF_8); - assertTrue(generated.contains(importStatement), () -> "Missing import in: " + generated); - } - catch (IOException e) { - fail(e.getMessage()); - } + // Test that the import statement is there + String generated = Files.readString(diagramTgtPath, StandardCharsets.UTF_8); + assertTrue(generated.contains(importStatement), () -> "Missing import in: " + generated); + + // Test that the symbol exists + assertTrue(decSymbolOutput.resolve(packageName).toFile().isDirectory(), + "failed to find decsym package"); + assertTrue(decSymbolOutput.resolve(packageName).resolve(diagramName + ".deccdsym").toFile() + .exists(), "failed to find decsym classname"); + + // Test that the decorated symbol table can be used + CD4CodeMill.reset(); + CD4CodeMill.init(); + CD4CodeMill.globalScope().setSymbolPath(new MCPath(decSymbolOutput)); + + assertTrue(CD4CodeMill.globalScope().resolveCDType("P.D.C").isPresent(), + "Failed to look for P.D.C"); + assertTrue(LogStub.getFindings().isEmpty()); } protected void createModelInInputDir(String model, String packageName, String diagramName) {