【发布时间】:2021-01-11 23:17:47
【问题描述】:
鉴于源代码和 Java 版本,我需要能够验证代码是否可以编译。如果代码无法编译,我需要能够在源代码中返回错误。
以下解决方案有效,但仅适用于您机器上当前使用的 Java 版本。
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class Validator {
private final JavaCompiler COMPILER = ToolProvider.getSystemJavaCompiler();
//Assume srcFiles are java files that can be read
public final boolean compiles(Set<File> srcFiles) throws IOException {
//Convert files to JavaCompiler API compatible files
List<JavaFileObject> compilationUnits = new ArrayList<>();
for (File file : srcFiles) {
CompilableFile compilableFile = new CompilableFile(file.getName(), Files.readString(file.toPath()));
compilationUnits.add(compilableFile);
}
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
JavaCompiler.CompilationTask task = COMPILER.getTask(null, null, diagnosticCollector, null, null, compilationUnits);
boolean success = task.call();
//Displaying the info of each warning, error, etc
diagnosticCollector.getDiagnostics().forEach(Validator::printDiagnostic);
return success;
}
private static void printDiagnostic(Diagnostic<?> diagnostic) {
System.out.println(diagnostic.getCode());
System.out.println(diagnostic.getKind());
System.out.println(diagnostic.getPosition());
System.out.println(diagnostic.getStartPosition());
System.out.println(diagnostic.getEndPosition());
System.out.println(diagnostic.getSource());
System.out.println(diagnostic.getMessage(null));
}
/**
* Instances of this class can be compiled with the JavaCompiler API
*/
private static final class CompilableFile extends SimpleJavaFileObject {
final String code;
CompilableFile(String name, String code) {
super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.code = code;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return code;
}
}
}
有没有我可以实现以下功能?
public final boolean compiles(Set<File> srcFiles, SourceVersion version) {...}
【问题讨论】:
-
@Abra 我看不出这有什么关系。我只是想验证代码,我不一定需要编译它,理论上我可以使用 Java 9 实现一个 Java 10 编译器,然后用它来验证我的代码。即便如此,如果您有 tools.jar 文件,您也可以使用 Java 9 编译 Java 10 代码。见here。此外,如果我有一个 Java 15 编译器,那将无法验证它之前的所有 Java 代码,因为我可以给它一个在以前的版本中无法运行的有效 Java 15 程序。
-
@Progman 我的问题不是那种形式吗?那我该怎么改写呢?我没有看到任何其他方式来询问如何做某事
-
从未尝试实现我自己的,但您是否尝试设置
source选项?我看到您的编译器选项设置为空。也许有办法以这种方式设置source编译器选项? -
@IQbrod 谢谢!即使传递
-source选项不起作用,调查它让我尝试传递--release选项,它确实有效
标签: java java-compiler-api javacompiler