better file concatenator
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'application'
|
||||
id 'com.gradleup.shadow' version '8.3.5'
|
||||
}
|
||||
|
||||
group = 'click.kamil.file_combine'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
|
||||
application {
|
||||
mainClass = 'click.kamil.file_combine.JavaConcatenator'
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
@@ -22,6 +28,9 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Picocli
|
||||
implementation 'info.picocli:picocli:4.7.6'
|
||||
|
||||
// deps for parsing java AST
|
||||
implementation 'org.eclipse.jdt:org.eclipse.jdt.core:3.36.0'
|
||||
|
||||
|
||||
@@ -1,61 +1,115 @@
|
||||
package click.kamil.file_combine;
|
||||
|
||||
import click.kamil.file_combine.common.FileUtils;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.compiler.IProblem;
|
||||
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 picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class JavaConcatenator {
|
||||
@Command(name = "java-combine", mixinStandardHelpOptions = true, version = "1.0",
|
||||
description = "Combines multiple Java source files into a single file.")
|
||||
public class JavaConcatenator implements Callable<Integer> {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Path sourceDir = Path.of("./src/main/java/click/kamil/callgraphexporter/domain");
|
||||
Path outputFile = Path.of("./Combined.java");
|
||||
@Parameters(index = "0..*", description = "Directories to search for Java files.")
|
||||
private List<Path> sourceDirs;
|
||||
|
||||
String targetPackage = "click.kamil";
|
||||
@Option(names = {"-o", "--output"}, description = "Output file path.", defaultValue = "./Combined.java")
|
||||
private Path outputFile;
|
||||
|
||||
List<Path> javaFiles = FileUtils.findFilesWithExtension(Set.of(sourceDir), ".java");
|
||||
@Option(names = {"-p", "--package"}, description = "Target package name.", defaultValue = "click.kamil")
|
||||
private String targetPackage;
|
||||
|
||||
Set<String> uniqueImports = new TreeSet<>();
|
||||
List<String> classBodies = new ArrayList<>();
|
||||
public static void main(String[] args) {
|
||||
int exitCode = new CommandLine(new JavaConcatenator()).execute(args);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer call() throws IOException {
|
||||
if (sourceDirs == null || sourceDirs.isEmpty()) {
|
||||
System.err.println("At least one source directory must be specified.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
List<Path> javaFiles = FileUtils.findFilesWithExtension(new HashSet<>(sourceDirs), ".java");
|
||||
|
||||
if (javaFiles.isEmpty()) {
|
||||
System.out.println("No Java files found in specified directories.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set<String> internalPackages = new HashSet<>();
|
||||
Set<String> internalClasses = new HashSet<>();
|
||||
List<FileParseResult> results = new ArrayList<>();
|
||||
|
||||
for (Path javaFile : javaFiles) {
|
||||
String source = Files.readString(javaFile);
|
||||
FileParseResult result = parseAndTransform(source);
|
||||
uniqueImports.addAll(result.imports);
|
||||
classBodies.add(result.classBody);
|
||||
if (result.packageName != null) {
|
||||
internalPackages.add(result.packageName);
|
||||
}
|
||||
internalClasses.addAll(result.topLevelTypes);
|
||||
results.add(result);
|
||||
}
|
||||
|
||||
Set<String> uniqueImports = new TreeSet<>();
|
||||
for (FileParseResult result : results) {
|
||||
for (String imp : result.imports) {
|
||||
String normalizedImport = imp.replaceFirst("^import\\s+static\\s+", "")
|
||||
.replaceFirst("^import\\s+", "")
|
||||
.replaceFirst(";$", "");
|
||||
|
||||
boolean isInternal = false;
|
||||
for (String pkg : internalPackages) {
|
||||
if (normalizedImport.startsWith(pkg + ".")) {
|
||||
isInternal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInternal && (targetPackage == null || !normalizedImport.startsWith(targetPackage + "."))) {
|
||||
uniqueImports.add(imp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder combinedSource = new StringBuilder();
|
||||
|
||||
// Add package declaration
|
||||
combinedSource.append("package ").append(targetPackage).append(";\n\n");
|
||||
if (targetPackage != null && !targetPackage.isEmpty()) {
|
||||
combinedSource.append("package ").append(targetPackage).append(";\n\n");
|
||||
}
|
||||
|
||||
// Filter and append imports excluding any from com.example.*
|
||||
// Append imports
|
||||
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(imp).append("\n");
|
||||
}
|
||||
combinedSource.append("\n");
|
||||
|
||||
// Append all class bodies
|
||||
for (String body : classBodies) {
|
||||
combinedSource.append(body).append("\n");
|
||||
for (FileParseResult result : results) {
|
||||
combinedSource.append(result.classBody).append("\n");
|
||||
}
|
||||
|
||||
if (outputFile.getParent() != null) {
|
||||
Files.createDirectories(outputFile.getParent());
|
||||
}
|
||||
Files.writeString(outputFile, combinedSource.toString());
|
||||
|
||||
System.out.println("Combined Java source written to: " + outputFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static FileParseResult parseAndTransform(String source) {
|
||||
@@ -64,11 +118,25 @@ public class JavaConcatenator {
|
||||
parser.setKind(ASTParser.K_COMPILATION_UNIT);
|
||||
parser.setResolveBindings(false);
|
||||
|
||||
Map<String, String> options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_21, options);
|
||||
parser.setCompilerOptions(options);
|
||||
|
||||
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
|
||||
|
||||
if (cu.getProblems().length > 0) {
|
||||
for (IProblem problem : cu.getProblems()) {
|
||||
if (problem.isError()) {
|
||||
System.err.println("Error parsing AST: " + problem.getMessage() + " at line " + problem.getSourceLineNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AST ast = cu.getAST();
|
||||
ASTRewrite rewrite = ASTRewrite.create(ast);
|
||||
|
||||
String packageName = cu.getPackage() != null ? cu.getPackage().getName().getFullyQualifiedName() : null;
|
||||
|
||||
// Collect imports as strings
|
||||
List<String> imports = new ArrayList<>();
|
||||
for (Object obj : cu.imports()) {
|
||||
@@ -82,23 +150,49 @@ public class JavaConcatenator {
|
||||
rewrite.remove(cu.getPackage(), null);
|
||||
}
|
||||
|
||||
// Remove 'public' from type declarations
|
||||
List<String> topLevelTypes = new ArrayList<>();
|
||||
|
||||
// Remove 'public' from top-level type declarations
|
||||
cu.accept(new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(TypeDeclaration node) {
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
if (node.getParent() instanceof CompilationUnit) {
|
||||
topLevelTypes.add(node.getName().getIdentifier());
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(EnumDeclaration node) {
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
if (node.getParent() instanceof CompilationUnit) {
|
||||
topLevelTypes.add(node.getName().getIdentifier());
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void removePublicModifier(List<IExtendedModifier> modifiers, ASTRewrite rewrite) {
|
||||
for (IExtendedModifier mod : new ArrayList<>(modifiers)) {
|
||||
if (mod.isModifier()) {
|
||||
@Override
|
||||
public boolean visit(AnnotationTypeDeclaration node) {
|
||||
if (node.getParent() instanceof CompilationUnit) {
|
||||
topLevelTypes.add(node.getName().getIdentifier());
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(RecordDeclaration node) {
|
||||
if (node.getParent() instanceof CompilationUnit) {
|
||||
topLevelTypes.add(node.getName().getIdentifier());
|
||||
removePublicModifier(node.modifiers(), rewrite);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void removePublicModifier(List modifiers, ASTRewrite rewrite) {
|
||||
for (Object mod : modifiers) {
|
||||
if (mod instanceof Modifier) {
|
||||
Modifier m = (Modifier) mod;
|
||||
if (m.isPublic()) {
|
||||
rewrite.remove(m, null);
|
||||
@@ -113,17 +207,21 @@ public class JavaConcatenator {
|
||||
TextEdit edits = rewrite.rewriteAST(document, null);
|
||||
edits.apply(document);
|
||||
String transformedSource = document.get();
|
||||
return new FileParseResult(imports, transformedSource);
|
||||
return new FileParseResult(packageName, topLevelTypes, imports, transformedSource);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to apply AST edits", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileParseResult {
|
||||
String packageName;
|
||||
List<String> topLevelTypes;
|
||||
List<String> imports;
|
||||
String classBody;
|
||||
|
||||
public FileParseResult(List<String> imports, String classBody) {
|
||||
public FileParseResult(String packageName, List<String> topLevelTypes, List<String> imports, String classBody) {
|
||||
this.packageName = packageName;
|
||||
this.topLevelTypes = topLevelTypes;
|
||||
this.imports = imports;
|
||||
this.classBody = classBody;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
package click.kamil.file_combine;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class JavaConcatenatorTest {
|
||||
|
||||
@TempDir
|
||||
Path tempDir;
|
||||
|
||||
@Test
|
||||
void testCombineSimpleFiles() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("A.java"),
|
||||
"package pkg1;\n" +
|
||||
"public class A {\n" +
|
||||
" public void hello() { System.out.println(\"Hello from A\"); }\n" +
|
||||
"}");
|
||||
|
||||
Path pkg2 = tempDir.resolve("pkg2");
|
||||
Files.createDirectories(pkg2);
|
||||
Files.writeString(pkg2.resolve("B.java"),
|
||||
"package pkg2;\n" +
|
||||
"import pkg1.A;\n" +
|
||||
"public class B {\n" +
|
||||
" public void run() { new A().hello(); }\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("Combined.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
assertTrue(Files.exists(outputFile));
|
||||
|
||||
String content = Files.readString(outputFile);
|
||||
assertTrue(content.contains("package combined;"));
|
||||
assertTrue(content.contains("class A"));
|
||||
assertTrue(content.contains("class B"));
|
||||
assertFalse(content.contains("import pkg1.A;"));
|
||||
|
||||
// Verify compilation
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertEquals(0, compilationResult, "Combined file should compile successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCollisionSameClassName() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("Utils.java"),
|
||||
"package pkg1;\n" +
|
||||
"public class Utils {\n" +
|
||||
" public static void log() { System.out.println(\"pkg1\"); }\n" +
|
||||
"}");
|
||||
|
||||
Path pkg2 = tempDir.resolve("pkg2");
|
||||
Files.createDirectories(pkg2);
|
||||
Files.writeString(pkg2.resolve("Utils.java"),
|
||||
"package pkg2;\n" +
|
||||
"public class Utils {\n" +
|
||||
" public static void log() { System.out.println(\"pkg2\"); }\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedCollision.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.collision");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
// This should produce a file with two 'class Utils' which is invalid Java
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertNotEquals(0, compilationResult, "Combined file with name collision should NOT compile successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStaticImportCollision() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("Utils1.java"),
|
||||
"package pkg1;\n" +
|
||||
"public class Utils1 {\n" +
|
||||
" public static void log(String s) { System.out.println(\"1: \" + s); }\n" +
|
||||
"}");
|
||||
|
||||
Path pkg2 = tempDir.resolve("pkg2");
|
||||
Files.createDirectories(pkg2);
|
||||
Files.writeString(pkg2.resolve("Utils2.java"),
|
||||
"package pkg2;\n" +
|
||||
"public class Utils2 {\n" +
|
||||
" public static void log(String s) { System.out.println(\"2: \" + s); }\n" +
|
||||
"}");
|
||||
|
||||
Path pkg3 = tempDir.resolve("pkg3");
|
||||
Files.createDirectories(pkg3);
|
||||
Files.writeString(pkg3.resolve("App.java"),
|
||||
"package pkg3;\n" +
|
||||
"import pkg1.Utils1;\n" +
|
||||
"public class App {\n" +
|
||||
" public void run() { Utils1.log(\"hello\"); }\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedStatic.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.static_test");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
String content = Files.readString(outputFile);
|
||||
// Both static imports should be present if they are not from internal packages
|
||||
// Actually, Utils1 and Utils2 ARE from internal packages in this test setup
|
||||
// So the concatenator should remove 'import static pkg1.Utils1.log'
|
||||
assertFalse(content.contains("import static pkg1.Utils1.log;"));
|
||||
|
||||
// Verify compilation
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertEquals(0, compilationResult, "Combined file with static imports should compile successfully if imports are resolved internally");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNestedClasses() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("Outer.java"),
|
||||
"package pkg1;\n" +
|
||||
"public class Outer {\n" +
|
||||
" public static class Inner {\n" +
|
||||
" public void doIt() {}\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
|
||||
Path pkg2 = tempDir.resolve("pkg2");
|
||||
Files.createDirectories(pkg2);
|
||||
Files.writeString(pkg2.resolve("Client.java"),
|
||||
"package pkg2;\n" +
|
||||
"import pkg1.Outer;\n" +
|
||||
"public class Client {\n" +
|
||||
" public void use() { new Outer.Inner().doIt(); }\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedNested.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.nested");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
// Verify compilation
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertEquals(0, compilationResult, "Combined file with nested classes should compile successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImportCollision() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("A.java"),
|
||||
"package pkg1;\n" +
|
||||
"import java.util.List;\n" +
|
||||
"public class A {\n" +
|
||||
" public List<String> list;\n" +
|
||||
"}");
|
||||
|
||||
Path pkg2 = tempDir.resolve("pkg2");
|
||||
Files.createDirectories(pkg2);
|
||||
Files.writeString(pkg2.resolve("B.java"),
|
||||
"package pkg2;\n" +
|
||||
"import java.awt.List;\n" +
|
||||
"public class B {\n" +
|
||||
" public List awtList;\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedImportCollision.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.import_collision");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
// This should fail compilation because 'List' is ambiguous
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertNotEquals(0, compilationResult, "Combined file with ambiguous imports should NOT compile successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecordsAndEnums() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("Data.java"),
|
||||
"package pkg1;\n" +
|
||||
"public record Data(String name, int value) {}\n");
|
||||
|
||||
Files.writeString(pkg1.resolve("Type.java"),
|
||||
"package pkg1;\n" +
|
||||
"public enum Type {\n" +
|
||||
" A, B, C\n" +
|
||||
"}\n");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedModern.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.modern");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
String content = Files.readString(outputFile);
|
||||
assertTrue(content.contains("record Data"));
|
||||
assertTrue(content.contains("enum Type"));
|
||||
assertFalse(content.contains("public record Data"));
|
||||
assertFalse(content.contains("public enum Type"));
|
||||
|
||||
// Verify compilation
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertEquals(0, compilationResult, "Combined file with records and enums should compile successfully");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMetadataPreservation() throws Exception {
|
||||
Path pkg1 = tempDir.resolve("pkg1");
|
||||
Files.createDirectories(pkg1);
|
||||
Files.writeString(pkg1.resolve("Annotated.java"),
|
||||
"package pkg1;\n" +
|
||||
"/**\n" +
|
||||
" * Javadoc comment\n" +
|
||||
" */\n" +
|
||||
"@Deprecated\n" +
|
||||
"public class Annotated {\n" +
|
||||
" // Line comment\n" +
|
||||
" /* Block comment */\n" +
|
||||
" @SuppressWarnings(\"unchecked\")\n" +
|
||||
" public void method() {}\n" +
|
||||
"}");
|
||||
|
||||
Path outputFile = tempDir.resolve("CombinedMetadata.java");
|
||||
|
||||
CommandLineRunner runner = new CommandLineRunner();
|
||||
int exitCode = runner.run(tempDir.toString(), "-o", outputFile.toString(), "-p", "combined.metadata");
|
||||
|
||||
assertEquals(0, exitCode);
|
||||
|
||||
String content = Files.readString(outputFile);
|
||||
assertTrue(content.contains("Javadoc comment"));
|
||||
assertTrue(content.contains("@Deprecated"));
|
||||
assertTrue(content.contains("// Line comment"));
|
||||
assertTrue(content.contains("/* Block comment */"));
|
||||
assertTrue(content.contains("@SuppressWarnings(\"unchecked\")"));
|
||||
|
||||
// Verify compilation
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
int compilationResult = compiler.run(null, null, null, outputFile.toString());
|
||||
assertEquals(0, compilationResult, "Combined file with comments and annotations should compile successfully");
|
||||
}
|
||||
|
||||
private static class CommandLineRunner {
|
||||
int run(String... args) {
|
||||
return new picocli.CommandLine(new JavaConcatenator()).execute(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user