diff --git a/.gitignore b/.gitignore index db09229..c022c2a 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,4 @@ out/ *.png *.dot *.scxml.xml -./Combined.java \ No newline at end of file +Combined.java \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index fbc3e52..9b994c1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'statemachinedemo' +rootProject.name = 'state machine exporter' diff --git a/src/main/java/click/kamil/filecombine/JavaConcatenator.java b/src/main/java/click/kamil/filecombine/JavaConcatenator.java new file mode 100644 index 0000000..4dd7d19 --- /dev/null +++ b/src/main/java/click/kamil/filecombine/JavaConcatenator.java @@ -0,0 +1,131 @@ +package click.kamil.filecombine; + +import click.kamil.springstatemachineexporter.ast.common.FileUtils; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jface.text.Document; +import org.eclipse.text.edits.TextEdit; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +public class JavaConcatenator { + + public static void main(String[] args) throws IOException { + Path sourceDir = Path.of("./src/main/java/click/kamil/springstatemachineexporter/ast"); + Path outputFile = Path.of("./Combined.java"); + + String targetPackage = "click.kamil"; + + List javaFiles = FileUtils.findFilesWithExtension(sourceDir, ".java"); + + Set uniqueImports = new TreeSet<>(); + List classBodies = new ArrayList<>(); + + for (Path javaFile : javaFiles) { + String source = Files.readString(javaFile); + FileParseResult result = parseAndTransform(source); + uniqueImports.addAll(result.imports); + classBodies.add(result.classBody); + } + + StringBuilder combinedSource = new StringBuilder(); + + // Add package declaration + combinedSource.append("package ").append(targetPackage).append(";\n\n"); + + // Filter and append imports excluding any from com.example.* + for (String imp : uniqueImports) { + String normalizedImport = imp.replaceFirst("^import\\s+static\\s+", "") + .replaceFirst("^import\\s+", "") + .replaceFirst(";$", ""); + + if (!normalizedImport.startsWith(targetPackage)) { + combinedSource.append(imp).append("\n"); + } + } + combinedSource.append("\n"); + + // Append all class bodies + for (String body : classBodies) { + combinedSource.append(body).append("\n"); + } + + Files.writeString(outputFile, combinedSource.toString()); + + System.out.println("Combined Java source written to: " + outputFile); + } + + private static FileParseResult parseAndTransform(String source) { + ASTParser parser = ASTParser.newParser(AST.JLS17); + parser.setSource(source.toCharArray()); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + parser.setResolveBindings(false); + + CompilationUnit cu = (CompilationUnit) parser.createAST(null); + + AST ast = cu.getAST(); + ASTRewrite rewrite = ASTRewrite.create(ast); + + // Collect imports as strings + List imports = new ArrayList<>(); + for (Object obj : cu.imports()) { + ImportDeclaration imp = (ImportDeclaration) obj; + imports.add(imp.toString().trim()); + rewrite.remove(imp, null); // Remove from AST + } + + // Remove package declaration + if (cu.getPackage() != null) { + rewrite.remove(cu.getPackage(), null); + } + + // Remove 'public' from type declarations + cu.accept(new ASTVisitor() { + @Override + public boolean visit(TypeDeclaration node) { + removePublicModifier(node.modifiers(), rewrite); + return true; + } + + @Override + public boolean visit(EnumDeclaration node) { + removePublicModifier(node.modifiers(), rewrite); + return true; + } + + private void removePublicModifier(List modifiers, ASTRewrite rewrite) { + for (IExtendedModifier mod : new ArrayList<>(modifiers)) { + if (mod.isModifier()) { + Modifier m = (Modifier) mod; + if (m.isPublic()) { + rewrite.remove(m, null); + } + } + } + } + }); + + try { + Document document = new Document(source); + TextEdit edits = rewrite.rewriteAST(document, null); + edits.apply(document); + String transformedSource = document.get(); + return new FileParseResult(imports, transformedSource); + } catch (Exception e) { + throw new RuntimeException("Failed to apply AST edits", e); + } + } + + private static class FileParseResult { + List imports; + String classBody; + + public FileParseResult(List imports, String classBody) { + this.imports = imports; + this.classBody = classBody; + } + } +}