From 1c0f743fbfa5f8211d58d5bb570f4c9e9d74703c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20L=C3=BCpges?= Date: Mon, 9 Mar 2026 11:58:57 +0100 Subject: [PATCH 1/3] use type instead of class --- .../codegen/decorators/GetterDecorator.java | 28 +++++++++---------- .../codegen/decorators/SetterDecorator.java | 20 ++++++------- .../decorators/data/AbstractDecorator.java | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) 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); } From c391a906ee8fdefec13d19b466fafdee48647708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20L=C3=BCpges?= Date: Mon, 9 Mar 2026 15:38:53 +0100 Subject: [PATCH 2/3] remove cd-model-name from exported decorated ST --- .../java/de/monticore/cdgen/CDGenTool.java | 143 ++++++++++-------- .../de/monticore/cdgen/CDGenToolTest.java | 43 ++++-- 2 files changed, 112 insertions(+), 74 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 4bb9f5b26..4848e4979 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; @@ -48,7 +50,7 @@ * cdtool/cdgradle/src/test/java/de/monticore/cdgen/CDGenGradlePluginTest.java */ public class CDGenTool extends CDGeneratorTool { - + /** * Gradle main method of the CDGenTool * @@ -58,7 +60,7 @@ public static void gradleMain(String[] args) { CDGenTool tool = new CDGenTool(); tool.run(args); } - + /** * main method of the CDGenTool * @@ -69,7 +71,7 @@ public static void main(String[] args) { CDGenTool tool = new CDGenTool(); tool.run(args); } - + /** * executes the arguments stated in the command line like parsing a given model to an ast, * creating and printing out a corresponding symbol table, checking cocos or generating java files @@ -80,13 +82,13 @@ public static void main(String[] args) { public void run(String[] args) { CD4CodeMill.reset(); CD4CodeMill.init(); - + Options options = initOptions(); - + try { CommandLineParser cliParser = new DefaultParser(); CommandLine cmd = cliParser.parse(options, args); - + if (cmd.hasOption("v")) { printVersion(); // do not continue when version is printed @@ -96,31 +98,31 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { printHelp(options); return; } - + final boolean c2mc = cmd.hasOption("c2mc"); - + initializeSymbolTable(c2mc); - + Log.enableFailQuick(false); Collection asts = this.parse(".cd", this.createModelPath(cmd) .getEntries()); Log.enableFailQuick(true); - + // Run CoCos if (cmd.hasOption("c")) { Log.enableFailQuick(false); asts.forEach(this::runBeforeSTCoCos); Log.enableFailQuick(true); } - + // apply trafos needed for symbol table creation asts = this.trafoBeforeSymtab(asts); - + if (cmd.hasOption("path")) { String[] paths = splitPathEntries(cmd.getOptionValue("path")); CD4CodeMill.globalScope().setSymbolPath(new MCPath(paths)); } - + // Create the symbol-table (symbol table creation phase 1) List scopes = new ArrayList<>(asts.size()); for (ASTCDCompilationUnit ast : asts) { @@ -128,28 +130,28 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { scopes.add(this.createSymbolTable(ast, c2mc)); Log.enableFailQuick(true); } - + // Complete the symbol-table (symbol table creation phase 2) for (ASTCDCompilationUnit ast : asts) { Log.enableFailQuick(false); // ST completition might report multiple errors this.completeSymbolTable(ast); Log.enableFailQuick(true); } - + // Run CoCos if (cmd.hasOption("c")) { Log.enableFailQuick(false); asts.forEach(this::runCoCos); Log.enableFailQuick(true); } - + // Export original symbol table if (cmd.hasOption("s")) { for (ICD4CodeArtifactScope scope : scopes) { this.storeSymTab(scope, cmd.getOptionValue("s")); } } - + if (cmd.hasOption("o")) { // Where to load additional templates from List additionalTemplatePaths = cmd.hasOption("fp") ? Arrays.stream(cmd @@ -161,11 +163,11 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { // output directory String outputPath = (cmd.hasOption("o")) ? Paths.get(cmd.getOptionValue("o")).toString() : ""; - + GlobalExtensionManagement glex = new GlobalExtensionManagement(); GeneratorSetup generatorSetup = newConfiguredGeneratorSetup(additionalTemplatePaths, handcodedPath, outputPath, glex); - + // Finally, invoke the decorating generator decorateAndGenerate(glex, // Initialize the decorator config @@ -191,11 +193,11 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { } CD4CodeMill.globalScope().clear(); } - + public void initializeSymbolTable(boolean c2mc) { BasicSymbolsMill.initializePrimitives(); MCCollectionSymTypeRelations.init(); - + if (c2mc) { initializeClass2MC(); } @@ -204,7 +206,7 @@ public void initializeSymbolTable(boolean c2mc) { BasicSymbolsMill.initializeObject(); } } - + public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig decConfig, CommandLine cmd, GeneratorSetup setup) { // Setup CLI config overrides @@ -220,7 +222,7 @@ public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig de TemplateHookPoint hpp = new TemplateHookPoint(configTemplate); hpp.processValue(tc, new ArrayList<>()); } - + public void decorateAndGenerate(GlobalExtensionManagement glex, Consumer initializeDecConf, GeneratorSetup setup, Runnable initDecoratedGlobalScope, Consumer postDecorate, @@ -229,41 +231,41 @@ public void decorateAndGenerate(GlobalExtensionManagement glex, glex.setGlobalValue("mcTypeFacade", MCTypeFacade.getInstance()); // TODO: Remove from templates glex.setGlobalValue("cdGenService", new CDGenService()); glex.setGlobalValue("cd4AnalysisTypeDispatcher", new CD4AnalysisTypeDispatcher()); // TODO: Remove from templates - + CDGenerator generator = new CDGenerator(setup); DecoratorConfig decSetup = new DecoratorConfig(); - + CDAssociationCreateFieldsFromAllRoles roleTrafo = performFieldsFromRolesTrafo(asts); - + // Load the initial decorator config initializeDecConf.accept(decSetup); - + // e.g., prepare the global scope for decorated symbol table initDecoratedGlobalScope.run(); - + for (ASTCDCompilationUnit ast : asts) { var decorated = decSetup.decorate(ast, roleTrafo.getFieldToRoles(), Optional.of(glex)); - + if (decorated.isEmpty()) { Log.error("0xCDD12: Failed generation for " + ast.getCDDefinition().getName()); continue; } - + // Post-Decorate: apply trafos needed for code generation CD4CodeTraverser t = CD4CodeMill.inheritanceTraverser(); t.add4CDBasis(new CDBasisDefaultPackageTrafo()); decorated.get().accept(t); // Post-Decorate: map import statements to classes this.mapCD4CImports(decorated.get()); - + // The following imports (cf. Imports.ftl) have to be added decorated.get().addMCImportStatement(CDBasisMill.mCImportStatementBuilder() .setMCQualifiedName(MCTypeFacade.getInstance().createQualifiedName("java.util")).setStar( true).build()); - + // If required, we can also output the symbol table of the *decorated* AST postDecorate.accept(decorated.get()); - + // Post-Decorate: TOP Decorator // TODO: #4310 - make this TOP transformation configurable via the config // template @@ -271,22 +273,22 @@ public void decorateAndGenerate(GlobalExtensionManagement glex, t = CD4CodeMill.inheritanceTraverser(); topTransformer.addToTraverser(t); decorated.get().accept(t); - + generator.generate(decorated.get()); } } - + public GeneratorSetup newConfiguredGeneratorSetup(List additionalTemplatePaths, Optional handcodedPath, String outputPath, GlobalExtensionManagement glex) { GeneratorSetup setup = new GeneratorSetup(); - + setup.setAdditionalTemplatePaths(additionalTemplatePaths); handcodedPath.ifPresent(setup::setHandcodedPath); setup.setGlex(glex); setup.setOutputDirectory(new File(outputPath)); return setup; } - + public CDAssociationCreateFieldsFromAllRoles performFieldsFromRolesTrafo( Collection asts) { CDAssociationCreateFieldsFromAllRoles roleTrafo = @@ -297,7 +299,7 @@ public CDAssociationCreateFieldsFromAllRoles performFieldsFromRolesTrafo( asts.forEach(roleTrafo::transform); return roleTrafo; } - + /** * Without Class2MC, we have to load symbols used in the generated CD * @@ -316,13 +318,13 @@ public void initDecoratedGlobalScope(boolean c2mc) { registerFakeType("ICDObserver", "de.monticore.cd.ICDObserver"); } } - + protected void registerFakeType(String simplename, String fullName) { CDBasisMill.globalScope().add(CDBasisMill.typeSymbolBuilder().setName(simplename).setFullName( fullName).setSpannedScope(CDBasisMill.scope()).setEnclosingScope(CDBasisMill.globalScope()) .build()); } - + /** * Create, complete, and export the symbol table of a decorated CD * @@ -333,50 +335,69 @@ public void createAndExportDecoratedSymbolTable(ASTCDCompilationUnit decorated, String symbolOutPath) { // Create the symbol-table (symbol table creation phase 1) var decoratedScope = this.createSymbolTable(decorated, true); - + // 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 } - + /** * adds additional options to the cli tool * * @param options collection of all the possible options */ public Options addAdditionalOptions(Options options) { - + options.addOption(Option.builder("c").longOpt("checkcococs").desc( "Checks all CoCos on the given mode.").build()); - + options.addOption(Option.builder("o").longOpt("output").argName("dir").hasArg().desc( "Sets the output path.").build()); - + options.addOption(Option.builder("ct").longOpt("configtemplate").hasArg().argName("template") .desc("Sets a template for configuration.").build()); - + options.addOption(Option.builder("fp").longOpt("template").hasArg().argName("path").desc( "Sets the path for additional templates.").build()); - + options.addOption(Option.builder("hwc").longOpt("handwrittencode").hasArg().argName("hwcpath") .desc("Sets the path for additional, handwritten classes.").build()); - + options.addOption(Option.builder("c2mc").longOpt("class2mc").desc( "Enables to resolve java classes in the model path").build()); - + options.addOption(Option.builder("cliconfig").desc("Configures additional").hasArgs().argName( "fqn:key[=value]").build()); - + options.addOption(org.apache.commons.cli.Option.builder("sd").longOpt("symboltabledecorated") .argName("file").hasArg().desc( "Serializes the decorated symbol table of the given artifact.").build()); - + return options; } - + /** * checks all cocos on the original ast before the symbol table is created * @@ -385,7 +406,7 @@ public Options addAdditionalOptions(Options options) { public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { // Nothing yet, decide how we expose them } - + /** * checks all cocos on the original ast * @@ -394,7 +415,7 @@ public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { public void runCoCos(ASTCDCompilationUnit ast) { super.runCoCos(ast); } - + @Override public Collection trafoBeforeSymtab(Collection asts) { super.trafoBeforeSymtab(asts); @@ -404,7 +425,7 @@ public Collection trafoBeforeSymtab(Collection ast.accept(t)); return asts; } - + /** * Updates the map of cd types to import statement in the given cd4c object, adding the imports * for each cd type (classes, enums, and interfaces) defined in the given ast. @@ -414,7 +435,7 @@ public Collection trafoBeforeSymtab(Collection imports = ast.getMCImportStatementList(); - + for (ASTCDClass cdClass : ast.getCDDefinition().getCDClassesList()) { for (ASTMCImportStatement i : imports) { String qName = i.getQName(); @@ -434,5 +455,5 @@ public void mapCD4CImports(ASTCDCompilationUnit ast) { } } } - + } 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) { From a7f607a40852477715642146dc4260c22bdc9e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20L=C3=BCpges?= Date: Mon, 9 Mar 2026 23:18:05 +0100 Subject: [PATCH 3/3] spotless --- .../java/de/monticore/cdgen/CDGenTool.java | 120 +++++++++--------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 4848e4979..7059e8f7c 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java +++ b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java @@ -50,7 +50,7 @@ * cdtool/cdgradle/src/test/java/de/monticore/cdgen/CDGenGradlePluginTest.java */ public class CDGenTool extends CDGeneratorTool { - + /** * Gradle main method of the CDGenTool * @@ -60,7 +60,7 @@ public static void gradleMain(String[] args) { CDGenTool tool = new CDGenTool(); tool.run(args); } - + /** * main method of the CDGenTool * @@ -71,7 +71,7 @@ public static void main(String[] args) { CDGenTool tool = new CDGenTool(); tool.run(args); } - + /** * executes the arguments stated in the command line like parsing a given model to an ast, * creating and printing out a corresponding symbol table, checking cocos or generating java files @@ -82,13 +82,13 @@ public static void main(String[] args) { public void run(String[] args) { CD4CodeMill.reset(); CD4CodeMill.init(); - + Options options = initOptions(); - + try { CommandLineParser cliParser = new DefaultParser(); CommandLine cmd = cliParser.parse(options, args); - + if (cmd.hasOption("v")) { printVersion(); // do not continue when version is printed @@ -98,31 +98,31 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { printHelp(options); return; } - + final boolean c2mc = cmd.hasOption("c2mc"); - + initializeSymbolTable(c2mc); - + Log.enableFailQuick(false); Collection asts = this.parse(".cd", this.createModelPath(cmd) .getEntries()); Log.enableFailQuick(true); - + // Run CoCos if (cmd.hasOption("c")) { Log.enableFailQuick(false); asts.forEach(this::runBeforeSTCoCos); Log.enableFailQuick(true); } - + // apply trafos needed for symbol table creation asts = this.trafoBeforeSymtab(asts); - + if (cmd.hasOption("path")) { String[] paths = splitPathEntries(cmd.getOptionValue("path")); CD4CodeMill.globalScope().setSymbolPath(new MCPath(paths)); } - + // Create the symbol-table (symbol table creation phase 1) List scopes = new ArrayList<>(asts.size()); for (ASTCDCompilationUnit ast : asts) { @@ -130,28 +130,28 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { scopes.add(this.createSymbolTable(ast, c2mc)); Log.enableFailQuick(true); } - + // Complete the symbol-table (symbol table creation phase 2) for (ASTCDCompilationUnit ast : asts) { Log.enableFailQuick(false); // ST completition might report multiple errors this.completeSymbolTable(ast); Log.enableFailQuick(true); } - + // Run CoCos if (cmd.hasOption("c")) { Log.enableFailQuick(false); asts.forEach(this::runCoCos); Log.enableFailQuick(true); } - + // Export original symbol table if (cmd.hasOption("s")) { for (ICD4CodeArtifactScope scope : scopes) { this.storeSymTab(scope, cmd.getOptionValue("s")); } } - + if (cmd.hasOption("o")) { // Where to load additional templates from List additionalTemplatePaths = cmd.hasOption("fp") ? Arrays.stream(cmd @@ -163,11 +163,11 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { // output directory String outputPath = (cmd.hasOption("o")) ? Paths.get(cmd.getOptionValue("o")).toString() : ""; - + GlobalExtensionManagement glex = new GlobalExtensionManagement(); GeneratorSetup generatorSetup = newConfiguredGeneratorSetup(additionalTemplatePaths, handcodedPath, outputPath, glex); - + // Finally, invoke the decorating generator decorateAndGenerate(glex, // Initialize the decorator config @@ -193,11 +193,11 @@ else if (!cmd.hasOption("i") || cmd.hasOption("h")) { } CD4CodeMill.globalScope().clear(); } - + public void initializeSymbolTable(boolean c2mc) { BasicSymbolsMill.initializePrimitives(); MCCollectionSymTypeRelations.init(); - + if (c2mc) { initializeClass2MC(); } @@ -206,7 +206,7 @@ public void initializeSymbolTable(boolean c2mc) { BasicSymbolsMill.initializeObject(); } } - + public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig decConfig, CommandLine cmd, GeneratorSetup setup) { // Setup CLI config overrides @@ -222,7 +222,7 @@ public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig de TemplateHookPoint hpp = new TemplateHookPoint(configTemplate); hpp.processValue(tc, new ArrayList<>()); } - + public void decorateAndGenerate(GlobalExtensionManagement glex, Consumer initializeDecConf, GeneratorSetup setup, Runnable initDecoratedGlobalScope, Consumer postDecorate, @@ -231,41 +231,41 @@ public void decorateAndGenerate(GlobalExtensionManagement glex, glex.setGlobalValue("mcTypeFacade", MCTypeFacade.getInstance()); // TODO: Remove from templates glex.setGlobalValue("cdGenService", new CDGenService()); glex.setGlobalValue("cd4AnalysisTypeDispatcher", new CD4AnalysisTypeDispatcher()); // TODO: Remove from templates - + CDGenerator generator = new CDGenerator(setup); DecoratorConfig decSetup = new DecoratorConfig(); - + CDAssociationCreateFieldsFromAllRoles roleTrafo = performFieldsFromRolesTrafo(asts); - + // Load the initial decorator config initializeDecConf.accept(decSetup); - + // e.g., prepare the global scope for decorated symbol table initDecoratedGlobalScope.run(); - + for (ASTCDCompilationUnit ast : asts) { var decorated = decSetup.decorate(ast, roleTrafo.getFieldToRoles(), Optional.of(glex)); - + if (decorated.isEmpty()) { Log.error("0xCDD12: Failed generation for " + ast.getCDDefinition().getName()); continue; } - + // Post-Decorate: apply trafos needed for code generation CD4CodeTraverser t = CD4CodeMill.inheritanceTraverser(); t.add4CDBasis(new CDBasisDefaultPackageTrafo()); decorated.get().accept(t); // Post-Decorate: map import statements to classes this.mapCD4CImports(decorated.get()); - + // The following imports (cf. Imports.ftl) have to be added decorated.get().addMCImportStatement(CDBasisMill.mCImportStatementBuilder() .setMCQualifiedName(MCTypeFacade.getInstance().createQualifiedName("java.util")).setStar( true).build()); - + // If required, we can also output the symbol table of the *decorated* AST postDecorate.accept(decorated.get()); - + // Post-Decorate: TOP Decorator // TODO: #4310 - make this TOP transformation configurable via the config // template @@ -273,22 +273,22 @@ public void decorateAndGenerate(GlobalExtensionManagement glex, t = CD4CodeMill.inheritanceTraverser(); topTransformer.addToTraverser(t); decorated.get().accept(t); - + generator.generate(decorated.get()); } } - + public GeneratorSetup newConfiguredGeneratorSetup(List additionalTemplatePaths, Optional handcodedPath, String outputPath, GlobalExtensionManagement glex) { GeneratorSetup setup = new GeneratorSetup(); - + setup.setAdditionalTemplatePaths(additionalTemplatePaths); handcodedPath.ifPresent(setup::setHandcodedPath); setup.setGlex(glex); setup.setOutputDirectory(new File(outputPath)); return setup; } - + public CDAssociationCreateFieldsFromAllRoles performFieldsFromRolesTrafo( Collection asts) { CDAssociationCreateFieldsFromAllRoles roleTrafo = @@ -299,7 +299,7 @@ public CDAssociationCreateFieldsFromAllRoles performFieldsFromRolesTrafo( asts.forEach(roleTrafo::transform); return roleTrafo; } - + /** * Without Class2MC, we have to load symbols used in the generated CD * @@ -318,13 +318,13 @@ public void initDecoratedGlobalScope(boolean c2mc) { registerFakeType("ICDObserver", "de.monticore.cd.ICDObserver"); } } - + protected void registerFakeType(String simplename, String fullName) { CDBasisMill.globalScope().add(CDBasisMill.typeSymbolBuilder().setName(simplename).setFullName( fullName).setSpannedScope(CDBasisMill.scope()).setEnclosingScope(CDBasisMill.globalScope()) .build()); } - + /** * Create, complete, and export the symbol table of a decorated CD * @@ -335,10 +335,10 @@ public void createAndExportDecoratedSymbolTable(ASTCDCompilationUnit decorated, String symbolOutPath) { // Create the symbol-table (symbol table creation phase 1) var decoratedScope = this.createSymbolTable(decorated, true); - + // Complete the symbol-table (symbol table creation phase 2) this.completeSymbolTable(decorated); - + // 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()) { @@ -349,7 +349,7 @@ public void createAndExportDecoratedSymbolTable(ASTCDCompilationUnit decorated, 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()); @@ -359,45 +359,45 @@ public void createAndExportDecoratedSymbolTable(ASTCDCompilationUnit decorated, .getClass()); } } - + // Note: The packagename + full name might be really weird in the exported file } - + /** * adds additional options to the cli tool * * @param options collection of all the possible options */ public Options addAdditionalOptions(Options options) { - + options.addOption(Option.builder("c").longOpt("checkcococs").desc( "Checks all CoCos on the given mode.").build()); - + options.addOption(Option.builder("o").longOpt("output").argName("dir").hasArg().desc( "Sets the output path.").build()); - + options.addOption(Option.builder("ct").longOpt("configtemplate").hasArg().argName("template") .desc("Sets a template for configuration.").build()); - + options.addOption(Option.builder("fp").longOpt("template").hasArg().argName("path").desc( "Sets the path for additional templates.").build()); - + options.addOption(Option.builder("hwc").longOpt("handwrittencode").hasArg().argName("hwcpath") .desc("Sets the path for additional, handwritten classes.").build()); - + options.addOption(Option.builder("c2mc").longOpt("class2mc").desc( "Enables to resolve java classes in the model path").build()); - + options.addOption(Option.builder("cliconfig").desc("Configures additional").hasArgs().argName( "fqn:key[=value]").build()); - + options.addOption(org.apache.commons.cli.Option.builder("sd").longOpt("symboltabledecorated") .argName("file").hasArg().desc( "Serializes the decorated symbol table of the given artifact.").build()); - + return options; } - + /** * checks all cocos on the original ast before the symbol table is created * @@ -406,7 +406,7 @@ public Options addAdditionalOptions(Options options) { public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { // Nothing yet, decide how we expose them } - + /** * checks all cocos on the original ast * @@ -415,7 +415,7 @@ public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { public void runCoCos(ASTCDCompilationUnit ast) { super.runCoCos(ast); } - + @Override public Collection trafoBeforeSymtab(Collection asts) { super.trafoBeforeSymtab(asts); @@ -425,7 +425,7 @@ public Collection trafoBeforeSymtab(Collection ast.accept(t)); return asts; } - + /** * Updates the map of cd types to import statement in the given cd4c object, adding the imports * for each cd type (classes, enums, and interfaces) defined in the given ast. @@ -435,7 +435,7 @@ public Collection trafoBeforeSymtab(Collection imports = ast.getMCImportStatementList(); - + for (ASTCDClass cdClass : ast.getCDDefinition().getCDClassesList()) { for (ASTMCImportStatement i : imports) { String qName = i.getQName(); @@ -455,5 +455,5 @@ public void mapCD4CImports(ASTCDCompilationUnit ast) { } } } - + }