![JAR search and dependency download from the Maven repository](/logo.png)
io.github.oliviercailloux.javagrade.bytecode.NewCompiler Maven / Gradle / Ivy
The newest version!
package io.github.oliviercailloux.javagrade.bytecode;
import static com.google.common.base.Verify.verify;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NewCompiler {
@SuppressWarnings("unused")
private static final Logger LOGGER = LoggerFactory.getLogger(NewCompiler.class);
public static NewCompiler create() {
return new NewCompiler();
}
private boolean tolerateFailure;
private ImmutableList classPath;
private ImmutableSet sourcePaths;
private Path outputDirectory;
private DiagnosticCollector fileDiagnostics;
private DiagnosticCollector compilerDiagnostics;
private final JavaCompiler compiler;
private NewCompiler() {
this.classPath = ImmutableList.of();
this.outputDirectory = null;
this.tolerateFailure = true;
fileDiagnostics = null;
compilerDiagnostics = null;
compiler = new EclipseCompiler();
}
public ImmutableList getClassPath() {
return classPath;
}
public NewCompiler setClassPath(List classPath) {
this.classPath = ImmutableList.copyOf(classPath);
return this;
}
public ImmutableSet getSourcePaths() {
return sourcePaths;
}
public NewCompiler setSourcePaths(Iterable sourcePaths) {
this.sourcePaths = ImmutableSet.copyOf(sourcePaths);
return this;
}
public Optional getOutputDirectory() {
return Optional.ofNullable(outputDirectory);
}
public NewCompiler setOutputDirectory(Path directory) {
this.outputDirectory = directory;
return this;
}
public NewCompiler setIntolerant() {
tolerateFailure = false;
return this;
}
public ImmutableList> compile() throws IOException {
prepare();
final boolean compiled;
try (StandardJavaFileManager fileManager = getFileManager()) {
compiled = compile(fileManager);
}
final ImmutableList> diagnostics = getDiagnostics();
LOGGER.debug("Compiled and got: {}.", diagnostics);
verify(compiled == diagnostics.isEmpty());
if (!tolerateFailure) {
verify(diagnostics.isEmpty(), diagnostics.toString());
}
return diagnostics;
}
private void prepare() {
fileDiagnostics = new DiagnosticCollector<>();
compilerDiagnostics = new DiagnosticCollector<>();
}
private StandardJavaFileManager getFileManager() throws IOException {
final StandardJavaFileManager fileManager =
compiler.getStandardFileManager(fileDiagnostics, Locale.US, StandardCharsets.UTF_8);
/**
* Have to set explicitly the annotation processor path, otherwise, the initialization of
* annotation processing (involving #getClassLoader) uses the class path, which fails if the
* paths do not refer to File instances, because JavacFileManager#getClassLoader(Location
* location) calls getLocation, which tries to return File instances, instead of
* getLocationAsPaths(Location location). See CompilerTests#testBugJdk(). I got an email on the
* 10th of March, 2021, stating that the incident is fixed in https://jdk.java.net/16/. I have
* not checked.
* https://github.com/openjdk/jdk/blob/master/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java#L744
*/
fileManager.setLocationFromPaths(StandardLocation.ANNOTATION_PROCESSOR_PATH,
ImmutableList.of());
fileManager.setLocationFromPaths(StandardLocation.CLASS_PATH, classPath);
if (outputDirectory != null) {
fileManager.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
ImmutableSet.of(outputDirectory));
}
return fileManager;
}
private boolean compile(StandardJavaFileManager fileManager) {
final StringWriter compilationOutputReceiver = new StringWriter();
final boolean compiled =
compiler
.getTask(compilationOutputReceiver, fileManager, compilerDiagnostics,
ImmutableList.of(), null, fileManager.getJavaFileObjectsFromPaths(sourcePaths))
.call();
final String compilationOutput = compilationOutputReceiver.toString();
if (!compilationOutput.isEmpty()) {
throw new UnsupportedOperationException(
getDiagnostics().toString() + ";;" + compilationOutput);
}
return compiled;
}
private ImmutableList> getDiagnostics() {
final ImmutableSet> fD =
ImmutableSet.copyOf(fileDiagnostics.getDiagnostics());
final ImmutableSet> cD =
ImmutableSet.copyOf(compilerDiagnostics.getDiagnostics());
final ImmutableSet> inters =
Sets.intersection(fD, cD).immutableCopy();
if (!inters.isEmpty()) {
throw new UnsupportedOperationException();
}
final ImmutableList.Builder> builder =
ImmutableList.builderWithExpectedSize(fD.size() + cD.size());
builder.addAll(fD).addAll(cD);
return builder.build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy