diff --git a/cdlang/src/main/java/de/monticore/CDGeneratorTool.java b/cdlang/src/main/java/de/monticore/CDGeneratorTool.java index 356bfa7f9..d6c0bec73 100644 --- a/cdlang/src/main/java/de/monticore/CDGeneratorTool.java +++ b/cdlang/src/main/java/de/monticore/CDGeneratorTool.java @@ -62,7 +62,7 @@ * This class is scheduled for removal/replacement by the decorating {@link * de.monticore.cdgen.CDGenTool} */ -@Deprecated +@Deprecated(forRemoval = true) public class CDGeneratorTool extends CD4CodeTool { /** diff --git a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java index 0385d838a..f101af407 100644 --- a/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java +++ b/cdlang/src/main/java/de/monticore/cdgen/CDGenTool.java @@ -1,7 +1,6 @@ /* (c) https://github.com/MontiCore/monticore */ package de.monticore.cdgen; -import de.monticore.CDGeneratorTool; import de.monticore.cd.codegen.CDGenService; import de.monticore.cd.codegen.CDGenerator; import de.monticore.cd.codegen.CdUtilsPrinter; @@ -13,20 +12,26 @@ import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromAllRoles; import de.monticore.cd4analysis.trafo.CDAssociationCreateFieldsFromNavigableRoles; import de.monticore.cd4code.CD4CodeMill; +import de.monticore.cd4code.CD4CodeTool; +import de.monticore.cd4code._cocos.CD4CodeCoCoChecker; +import de.monticore.cd4code._symboltable.CD4CodeScopesGenitorDelegatorTOP; +import de.monticore.cd4code._symboltable.CD4CodeSymbolTableCompleter; import de.monticore.cd4code._symboltable.ICD4CodeArtifactScope; import de.monticore.cd4code._visitor.CD4CodeTraverser; +import de.monticore.cd4code.cocos.CD4CodeCoCosDelegator; +import de.monticore.cd4code.trafo.CD4CodeAfterParseTrafo; import de.monticore.cdbasis.CDBasisMill; import de.monticore.cdbasis._ast.ASTCDClass; import de.monticore.cdbasis._ast.ASTCDCompilationUnit; import de.monticore.cdbasis.trafo.CDBasisDefaultPackageTrafo; import de.monticore.cdinterfaceandenum._ast.ASTCDEnum; import de.monticore.cdinterfaceandenum._ast.ASTCDInterface; +import de.monticore.class2mc.OOClass2MCResolver; import de.monticore.generating.GeneratorSetup; -import de.monticore.generating.templateengine.GlobalExtensionManagement; -import de.monticore.generating.templateengine.TemplateController; -import de.monticore.generating.templateengine.TemplateHookPoint; +import de.monticore.generating.templateengine.*; import de.monticore.io.paths.MCPath; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; +import de.monticore.symboltable.ImportStatement; import de.monticore.types.MCTypeFacade; import de.monticore.types.mcbasictypes._ast.ASTMCImportStatement; import de.monticore.types.mccollectiontypes.types3.MCCollectionSymTypeRelations; @@ -34,22 +39,25 @@ import de.se_rwth.commons.logging.Log; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.function.Consumer; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.cli.*; /** - * This class is a further development of the {@link CDGeneratorTool} and meant as a replacement. It - * provides configurable decorator functionality in addition to generation. This tool is tested via + * This tool provides configurable decorator functionality in addition to generation. This tool is + * tested via * the CDGenGradlePluginTest: * cdtool/cdgradle/src/test/java/de/monticore/cdgen/CDGenGradlePluginTest.java */ -public class CDGenTool extends CDGeneratorTool { +public class CDGenTool extends CD4CodeTool { /** * Gradle main method of the CDGenTool @@ -68,8 +76,18 @@ public static void gradleMain(String[] args) { */ public static void main(String[] args) { Log.init(); - CDGenTool tool = new CDGenTool(); - tool.run(args); + try { + CD4CodeTool tool = new CDGenTool(); + tool.run(args); + } + catch (Exception exception) { + // ensure a sane exit + Log.error("0xEEEEE an internal error occurred" + " during the execution of the CD4CodeTool." + + System.lineSeparator() + "This error is unexpected" + + " and does not indicate an issue with any provided models.", exception); + } + // properly exit with a code + System.exit(Log.getErrorCount() == 0 ? 0 : 1); } /** @@ -207,6 +225,11 @@ public void initializeSymbolTable(boolean c2mc) { } } + public void initializeClass2MC() { + CD4CodeMill.globalScope().addAdaptedTypeSymbolResolver(new OOClass2MCResolver()); + CD4CodeMill.globalScope().addAdaptedOOTypeSymbolResolver(new OOClass2MCResolver()); + } + public void initializeDecConf(GlobalExtensionManagement glex, DecoratorConfig decConfig, CommandLine cmd, GeneratorSetup setup) { // Setup CLI config overrides @@ -397,12 +420,13 @@ public void runBeforeSTCoCos(ASTCDCompilationUnit ast) { * @param ast the original ast */ public void runCoCos(ASTCDCompilationUnit ast) { - super.runCoCos(ast); + CD4CodeCoCoChecker checker = new CD4CodeCoCosDelegator().getCheckerForAllCoCos(); + checker.checkAll(ast); } - @Override public Collection trafoBeforeSymtab(Collection asts) { - super.trafoBeforeSymtab(asts); + CD4CodeAfterParseTrafo trafo = new CD4CodeAfterParseTrafo(); + asts.forEach(ast -> ast.accept(trafo.getTraverser())); // TODO: Have this be done via the config-options (#4310) var t = CD4CodeMill.inheritanceTraverser(); t.add4UMLModifier(new DefaultVisibilityPublicTrafo()); @@ -440,4 +464,101 @@ public void mapCD4CImports(ASTCDCompilationUnit ast) { } } + public MCPath createModelPath(CommandLine cl) { + if (cl.hasOption("i")) { + return new MCPath(splitPathEntries(cl.getOptionValues("i"))); + } + else { + return new MCPath(); + } + } + + public String[] splitPathEntries(String composedPath) { + Objects.requireNonNull(composedPath); + + return composedPath.split(Pattern.quote(File.pathSeparator)); + } + + public final String[] splitPathEntries(String[] composedPaths) { + Objects.requireNonNull(composedPaths); + return Arrays.stream(composedPaths).map(this::splitPathEntries).flatMap(Arrays::stream).toArray( + String[]::new); + } + + public Collection parse(String fileExt, Collection filesAndDirs) { + return filesAndDirs.stream().flatMap(dirOrFile -> this.parse(fileExt, dirOrFile).stream()) + .collect(Collectors.toList()); + } + + /** + * Parses all class diagrams in the given path. + * In case the path is a file, the file is parsed regardless of its extension + * Otherwise, all files within the path-directory are parsed if their extension matches + * + * @param fileExt recursively parses all files with this extension in a directory + * @param fileOrDir directory or file + * @return a collection of nested files + */ + public Collection parse(String fileExt, Path fileOrDir) { + if (Files.isRegularFile(fileOrDir)) { + // In case a file is within the ModelPath: parse the file + return Collections.singleton(this.parse(fileOrDir.toString())); + } + // Otherwise: Traverse the directory & parse all matching files + try ( + Stream paths = Files.walk(fileOrDir) + ) { + return paths.filter(Files::isRegularFile).filter(file -> file.getFileName().toString() + .endsWith(fileExt)).map(Path::toString).map(this::parse).collect(Collectors.toSet()); + } + catch (IOException e) { + Log.error("0xA1063 Error while traversing the file structure `" + fileOrDir + "`.", e); + } + return Collections.emptySet(); + } + + /** + * creates the symboltable for the given ast + * + * @param ast the input ast + * @param java whether to add java default imports + * @return the symbol-table of the ast + */ + public ICD4CodeArtifactScope createSymbolTable(ASTCDCompilationUnit ast, boolean java) { + CD4CodeScopesGenitorDelegatorTOP genitor = CD4CodeMill.scopesGenitorDelegator(); + ICD4CodeArtifactScope scope = genitor.createFromAST(ast); + this.addDefaultImports(scope, java); + return scope; + } + + public void addDefaultImports(ICD4CodeArtifactScope scope, boolean java) { + if (java) + scope.addImports(new ImportStatement("java.lang", true)); + } + + /** + * prints the symboltable of the given scope out to a file + * + * @param scope symboltable to store + * @param path location of the file or directory containing the printed table + */ + public void storeSymTab(ICD4CodeArtifactScope scope, String path) { + if (Path.of(path).toFile().isFile()) { + this.storeSymbols(scope, path); + } + else { + this.storeSymbols(scope, Paths.get(path, Names.getPathFromPackage(scope.getFullName()) + + ".cdsym").toString()); + } + } + + /** + * completes the symboltable for the given ast + * + * @param ast the input ast + */ + public void completeSymbolTable(ASTCDCompilationUnit ast) { + ast.accept(new CD4CodeSymbolTableCompleter(ast).getTraverser()); + } + } diff --git a/cdlang/src/test/java/de/monticore/CDGeneratorToolTest.java b/cdlang/src/test/java/de/monticore/CDGeneratorToolTest.java index 5347bf94b..5320fb61d 100644 --- a/cdlang/src/test/java/de/monticore/CDGeneratorToolTest.java +++ b/cdlang/src/test/java/de/monticore/CDGeneratorToolTest.java @@ -7,6 +7,8 @@ import de.monticore.cd4code.CD4CodeMill; import de.monticore.cd4code._symboltable.CD4CodeSymbols2Json; import de.monticore.cd4code._symboltable.ICD4CodeArtifactScope; +import de.monticore.cdgen.CDGenTool; +import de.monticore.runtime.junit.MCAssertions; import de.monticore.symbols.basicsymbols.BasicSymbolsMill; import de.se_rwth.commons.logging.LogStub; import java.io.File; @@ -16,6 +18,7 @@ import java.nio.file.Paths; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class CDGeneratorToolTest { @@ -30,14 +33,13 @@ public void before() { @Test public void testGeneratorToolWithCoCos() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-c" }); - assertTrue(true); } @Test public void testGeneratorToolWithSymbolTable() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-s", "target/generated/example/symboltable" }); assertTrue(new File("target/generated/example/symboltable/model/Example.cdsym").isFile()); @@ -45,7 +47,7 @@ public void testGeneratorToolWithSymbolTable() { @Test public void testGeneratorToolWithJavaGeneration() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-o", "target/generated/example/standard", }); assertTrue(new File("target/generated/example/standard/model/Example/A.java").isFile()); @@ -53,7 +55,7 @@ public void testGeneratorToolWithJavaGeneration() { @Test public void testGeneratorToolWithEmptyCDWithPackage() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/EmptyWithPackage.cd", "-c2mc", "-o", "target/generated/example/standard", }); @@ -63,23 +65,25 @@ public void testGeneratorToolWithEmptyCDWithPackage() { @Test public void testGeneratorToolWithEmptyCDWithoutPackage() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/EmptyWithoutPackage.cd", "-c2mc", "-o", "target/generated/example/standard", }); assertTrue(new File("target/generated/example/standard/EmptyWithoutPackage").isDirectory()); } @Test + @Disabled // The new generator has a different configTemplate opinion public void testGeneratorToolWithCustomGeneratorTemplate() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-o", "target/generated/example/ct", "-ct", "de.monticore.cdgentool.NewCustomTemplate" }); assertTrue(new File("target/generated/example/ct/model/Example/A.java").isFile()); } @Test + @Disabled // New generator has a different CLI options public void testGeneratorToolWithAdditionalTemplates() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-o", "target/generated/example/tp", "-tp", "src/test/resources/de/monticore/cdgentool/templates" }); @@ -88,7 +92,7 @@ public void testGeneratorToolWithAdditionalTemplates() { @Test public void testGeneratorToolWithHWC() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-o", "target/generated/example/hwc", "-hwc", "src/test/resources/de/monticore/cdgentool/hwc" }); assertTrue(new File("target/generated/example/hwc/model/Example/ATOP.java").isFile()); @@ -96,20 +100,18 @@ public void testGeneratorToolWithHWC() { @Test public void testToolPrintHelpOptions() { - CDGeneratorTool.main(new String[] { "-h" }); - assertTrue(true); + new CDGenTool().run(new String[] { "-h" }); } @Test public void testToolPrintVersion() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-v" }); - assertTrue(true); } @Test public void testGeneratorToolWithPkgSymTab() throws IOException { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/pkg/ExampleWithPkg.cd", "-c2mc", "-o", "target/generated/example/examplewithpkg", "-s", "target/generated/example/examplewithpkg" }); @@ -120,8 +122,9 @@ public void testGeneratorToolWithPkgSymTab() throws IOException { } @Test + @Disabled // The new generated uses a different set of decorators public void testDefaultConstructorDecorator() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-o", "target/generated/example/defaultctor", "-ct", "de.monticore.cdgentool.DefaultCtorTemplate", }); @@ -131,21 +134,20 @@ public void testDefaultConstructorDecorator() { @Test public void testImportStatements() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-o", "target/generated/example/imports", "-c2mc", "-s", "target/generated/example/imports/" }); - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/ImportTest.cd", "-o", "target/generated/example/imports", "-c2mc", "-path", "target/generated/example/imports/" }); - - assertTrue(true); } @Test + @Disabled // The new generator does not have a "fieldfromrole" option public void testAttributesForAssociations() { - CDGeneratorTool.main(new String[] { "-i", + new CDGenTool().run(new String[] { "-i", "src/test/resources/de/monticore/cdgentool/model/Example.cd", "-c2mc", "-s", "target/generated/example/rolefield/", "-fieldfromrole", "navigable" }); File symtab = new File("target/generated/example/rolefield/model/Example.cdsym"); @@ -159,8 +161,8 @@ public void testAttributesForAssociations() { @AfterEach public void after() { + MCAssertions.assertNoFindings(); CD4CodeMill.globalScope().clear(); - assertTrue(LogStub.getFindings().isEmpty()); } }