annotation processing "proc:only" mode support (IDEA-253719)

GitOrigin-RevId: 24a2dc446de47bf223b83329a0bc1a87992306e7
This commit is contained in:
Eugene Zhuravlev
2020-12-02 13:51:32 +01:00
committed by intellij-monorepo-bot
parent 3338b2394e
commit 809200f825
16 changed files with 347 additions and 185 deletions

View File

@@ -56,6 +56,7 @@ public class ProcessorProfilePanel extends JPanel {
private final JLabel myTestLabel; private final JLabel myTestLabel;
private final JPanel myProcessorTablePanel; private final JPanel myProcessorTablePanel;
private final JPanel myOptionsTablePanel; private final JPanel myOptionsTablePanel;
private final JCheckBox myCbProcOnly;
public ProcessorProfilePanel(Project project) { public ProcessorProfilePanel(Project project) {
@@ -63,7 +64,7 @@ public class ProcessorProfilePanel extends JPanel {
myProject = project; myProject = project;
myCbEnableProcessing = new JCheckBox(JavaCompilerBundle.message("settings.enable.annotation.processing")); myCbEnableProcessing = new JCheckBox(JavaCompilerBundle.message("settings.enable.annotation.processing"));
myCbProcOnly = new JCheckBox(JavaCompilerBundle.message("settings.annotation.processing.proc.only"));
{ {
myRbClasspath = new JRadioButton(JavaCompilerBundle.message("settings.obtain.processors.from.project.classpath")); myRbClasspath = new JRadioButton(JavaCompilerBundle.message("settings.obtain.processors.from.project.classpath"));
myRbProcessorsPath = new JRadioButton(JavaCompilerBundle.message("settings.processor.path")); myRbProcessorsPath = new JRadioButton(JavaCompilerBundle.message("settings.processor.path"));
@@ -163,6 +164,9 @@ public class ProcessorProfilePanel extends JPanel {
add(myGeneratedTestsDirField, add(myGeneratedTestsDirField,
new GridBagConstraints(1, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.insets(10, 5, 0, 0), 0, 0)); new GridBagConstraints(1, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.insets(10, 5, 0, 0), 0, 0));
add(myCbProcOnly,
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.insets(10, 5, 0, 0), 0, 0));
add(myProcessorTablePanel, add(myProcessorTablePanel,
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0)); new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0));
add(myOptionsTablePanel, add(myOptionsTablePanel,
@@ -185,6 +189,8 @@ public class ProcessorProfilePanel extends JPanel {
public void setProfile(ProcessorConfigProfile config) { public void setProfile(ProcessorConfigProfile config) {
myCbEnableProcessing.setSelected(config.isEnabled()); myCbEnableProcessing.setSelected(config.isEnabled());
myCbProcOnly.setSelected(config.isProcOnly());
(config.isObtainProcessorsFromClasspath()? myRbClasspath : myRbProcessorsPath).setSelected(true); (config.isObtainProcessorsFromClasspath()? myRbClasspath : myRbProcessorsPath).setSelected(true);
myCbProcessorModulePath.setSelected(config.isUseProcessorModulePath()); myCbProcessorModulePath.setSelected(config.isUseProcessorModulePath());
myProcessorPathField.setText(FileUtil.toSystemDependentName(config.getProcessorPath())); myProcessorPathField.setText(FileUtil.toSystemDependentName(config.getProcessorPath()));
@@ -210,6 +216,7 @@ public class ProcessorProfilePanel extends JPanel {
profile.setObtainProcessorsFromClasspath(myRbClasspath.isSelected()); profile.setObtainProcessorsFromClasspath(myRbClasspath.isSelected());
profile.setProcessorPath(myProcessorPathField.getText().trim()); profile.setProcessorPath(myProcessorPathField.getText().trim());
profile.setUseProcessorModulePath(myCbProcessorModulePath.isSelected()); profile.setUseProcessorModulePath(myCbProcessorModulePath.isSelected());
profile.setProcOnly(myCbProcOnly.isSelected());
final String productionDir = myGeneratedProductionDirField.getText().trim(); final String productionDir = myGeneratedProductionDirField.getText().trim();
profile.setGeneratedSourcesDirectoryName(StringUtil.isEmpty(productionDir)? null : productionDir, false); profile.setGeneratedSourcesDirectoryName(StringUtil.isEmpty(productionDir)? null : productionDir, false);
@@ -263,6 +270,7 @@ public class ProcessorProfilePanel extends JPanel {
myStoreGenSourcesLabel.setEnabled(enabled); myStoreGenSourcesLabel.setEnabled(enabled);
myProductionLabel.setEnabled(enabled); myProductionLabel.setEnabled(enabled);
myTestLabel.setEnabled(enabled); myTestLabel.setEnabled(enabled);
myCbProcOnly.setEnabled(enabled);
myProcessorTablePanel.setEnabled(enabled); myProcessorTablePanel.setEnabled(enabled);
myOptionsTablePanel.setEnabled(enabled); myOptionsTablePanel.setEnabled(enabled);
} }

View File

@@ -146,6 +146,7 @@ settings.override.module.column=Module
settings.override.compilation.options.column=Compilation options settings.override.compilation.options.column=Compilation options
settings.additional.compilation.options=Additional compilation options will be the same for all modules settings.additional.compilation.options=Additional compilation options will be the same for all modules
settings.enable.annotation.processing=Enable annotation processing settings.enable.annotation.processing=Enable annotation processing
settings.annotation.processing.proc.only=Run processors in a separate step before compiling java (-proc:only mode)
settings.obtain.processors.from.project.classpath=Obtain processors from project classpath settings.obtain.processors.from.project.classpath=Obtain processors from project classpath
settings.processor.path=Processor path: settings.processor.path=Processor path:
settings.use.processor.module.path.compiler.option.for.java.9.and.later=Use --processor-module-path compiler option (for Java 9 and later) settings.use.processor.module.path.compiler.option.for.java.9.and.later=Use --processor-module-path compiler option (for Java 9 and later)

View File

@@ -7,13 +7,12 @@ import org.jetbrains.jps.javac.ast.JavacReferenceCollector;
import org.jetbrains.jps.javac.ast.api.JavacFileData; import org.jetbrains.jps.javac.ast.api.JavacFileData;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
import java.util.Collection;
public abstract class AbstractRefCollectorCompilerToolExtension extends JavaCompilerToolExtension { public abstract class AbstractRefCollectorCompilerToolExtension extends JavaCompilerToolExtension {
@Override @Override
public final void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool, public final void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool,
@NotNull JavaCompiler.CompilationTask task, @NotNull JavaCompiler.CompilationTask task,
@NotNull Collection<String> options, @NotNull Iterable<String> options,
@NotNull final DiagnosticOutputConsumer diagnosticConsumer) { @NotNull final DiagnosticOutputConsumer diagnosticConsumer) {
if (compilingTool.isCompilerTreeAPISupported() && isEnabled()) { if (compilingTool.isCompilerTreeAPISupported() && isEnabled()) {
JavacReferenceCollector.installOn(task, new JavacReferenceCollector.Consumer<JavacFileData>() { JavacReferenceCollector.installOn(task, new JavacReferenceCollector.Consumer<JavacFileData>() {

View File

@@ -18,8 +18,32 @@ public class Iterators {
} }
}; };
public static <T> boolean isEmpty(Iterable<T> iterable) { public static boolean isEmpty(Iterable<?> iterable) {
return iterable == null || (iterable instanceof Collection && ((Collection<?>)iterable).isEmpty()); if (iterable instanceof Collection) {
return ((Collection<?>)iterable).isEmpty();
}
return iterable == null || !iterable.iterator().hasNext();
}
public static <T> boolean contains(Iterable<? extends T> iterable, T obj) {
if (iterable instanceof Collection) {
return ((Collection<?>)iterable).contains(obj);
}
if (iterable != null) {
for (T o : iterable) {
if (obj.equals(o)) {
return true;
}
}
}
return false;
}
public static <C extends Collection<? super T>, T> C collect(Iterable<? extends T> iterable, C acc) {
for (T t : iterable) {
acc.add(t);
}
return acc;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.ExtensionsSupport; import org.jetbrains.jps.ExtensionsSupport;
import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.builders.java.JavaCompilingTool;
import javax.tools.*; import javax.tools.JavaCompiler;
import java.util.Collection; import java.util.Collection;
/** /**
@@ -29,13 +29,12 @@ public abstract class JavaCompilerToolExtension {
/** /**
* This method is called before compiler task execution. * This method is called before compiler task execution.
* The extension can install all necessary compiler listeners here. * The extension can install all necessary compiler listeners here.
* * @param compilingTool descriptor of compiler implementation that will perform compilation
* @param compilingTool descriptor of compiler implementation that will perform compilation
* @param task an instance of compiler task that is going to be executed * @param task an instance of compiler task that is going to be executed
* @param options compiler command line options for this compiler invocation * @param options compiler command line options for this compiler invocation
* @param diagnosticConsumer diagnostic data collector. Use this object to pass messages and collected data * @param diagnosticConsumer diagnostic data collector. Use this object to pass messages and collected data
*/ */
public void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool, @NotNull JavaCompiler.CompilationTask task, @NotNull Collection<String> options, @NotNull DiagnosticOutputConsumer diagnosticConsumer) { public void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool, @NotNull JavaCompiler.CompilationTask task, @NotNull Iterable<String> options, @NotNull DiagnosticOutputConsumer diagnosticConsumer) {
} }
private static final ExtensionsSupport<JavaCompilerToolExtension> ourExtSupport = new ExtensionsSupport<JavaCompilerToolExtension>(JavaCompilerToolExtension.class); private static final ExtensionsSupport<JavaCompilerToolExtension> ourExtSupport = new ExtensionsSupport<JavaCompilerToolExtension>(JavaCompilerToolExtension.class);

View File

@@ -30,7 +30,7 @@ public final class JavacMain {
"-d", "-classpath", "-cp", "--class-path", "-bootclasspath", "--boot-class-path" "-d", "-classpath", "-cp", "--class-path", "-bootclasspath", "--boot-class-path"
))); )));
private static final Set<String> FILTERED_SINGLE_OPTIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( private static final Set<String> FILTERED_SINGLE_OPTIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
/*javac options*/ "-verbose", "-proc:only", "-implicit:class", "-implicit:none", "-Xprefer:newer", "-Xprefer:source" /*javac options*/ "-verbose", "-implicit:class", "-implicit:none", "-Xprefer:newer", "-Xprefer:source"
))); )));
private static final Set<String> FILE_MANAGER_EARLY_INIT_OPTIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( private static final Set<String> FILE_MANAGER_EARLY_INIT_OPTIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
"-encoding", "-extdirs", "-endorseddirs", "-processorpath", "--processor-path", "--processor-module-path", "-s", "-d", "-h" "-encoding", "-extdirs", "-endorseddirs", "-processorpath", "--processor-path", "--processor-module-path", "-s", "-d", "-h"
@@ -41,13 +41,13 @@ public final class JavacMain {
public static final String TRACK_AP_GENERATED_DEPENDENCIES_PROPERTY = "jps.track.ap.dependencies"; public static final String TRACK_AP_GENERATED_DEPENDENCIES_PROPERTY = "jps.track.ap.dependencies";
public static final boolean TRACK_AP_GENERATED_DEPENDENCIES = Boolean.parseBoolean(System.getProperty(TRACK_AP_GENERATED_DEPENDENCIES_PROPERTY, "true")); public static final boolean TRACK_AP_GENERATED_DEPENDENCIES = Boolean.parseBoolean(System.getProperty(TRACK_AP_GENERATED_DEPENDENCIES_PROPERTY, "true"));
public static boolean compile(Collection<String> options, public static boolean compile(Iterable<? extends String> options,
final Collection<? extends File> sources, Iterable<? extends File> sources,
Collection<? extends File> classpath, Iterable<? extends File> classpath,
Collection<? extends File> platformClasspath, Iterable<? extends File> platformClasspath,
ModulePath modulePath, ModulePath modulePath,
Collection<? extends File> upgradeModulePath, Iterable<? extends File> upgradeModulePath,
Collection<? extends File> sourcePath, Iterable<? extends File> sourcePath,
final Map<File, Set<File>> outputDirToRoots, final Map<File, Set<File>> outputDirToRoots,
final DiagnosticOutputConsumer diagnosticConsumer, final DiagnosticOutputConsumer diagnosticConsumer,
final OutputFileConsumer outputSink, final OutputFileConsumer outputSink,
@@ -70,7 +70,7 @@ public final class JavacMain {
final JpsJavacFileManager fileManager = new JpsJavacFileManager( final JpsJavacFileManager fileManager = new JpsJavacFileManager(
new ContextImpl(compiler, diagnosticConsumer, outputSink, modulePath, canceledStatus), javacBefore9, JavaSourceTransformer.getTransformers() new ContextImpl(compiler, diagnosticConsumer, outputSink, modulePath, canceledStatus), javacBefore9, JavaSourceTransformer.getTransformers()
); );
if (javacBefore9 && !platformClasspath.isEmpty()) { if (javacBefore9 && !Iterators.isEmpty(platformClasspath)) {
// for javac6 this will prevent lazy initialization of Paths.bootClassPathRtJar // for javac6 this will prevent lazy initialization of Paths.bootClassPathRtJar
// and thus usage of symbol file for resolution, when this file is not expected to be used // and thus usage of symbol file for resolution, when this file is not expected to be used
fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator());
@@ -78,7 +78,7 @@ public final class JavacMain {
fileManager.handleOption("-endorseddirs", Collections.singleton("").iterator()); // this will clear cached stuff fileManager.handleOption("-endorseddirs", Collections.singleton("").iterator()); // this will clear cached stuff
} }
final Collection<String> _options = prepareOptions(options, compilingTool); final Iterable<String> _options = prepareOptions(options, compilingTool);
try { try {
// to be on the safe side, we'll have to apply all options _before_ calling any of manager's methods // to be on the safe side, we'll have to apply all options _before_ calling any of manager's methods
@@ -102,7 +102,7 @@ public final class JavacMain {
return false; return false;
} }
if (!platformClasspath.isEmpty()) { if (!Iterators.isEmpty(platformClasspath)) {
try { try {
fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, buildPlatformClasspath(platformClasspath, _options)); fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, buildPlatformClasspath(platformClasspath, _options));
@@ -113,7 +113,7 @@ public final class JavacMain {
} }
} }
if (!upgradeModulePath.isEmpty()) { if (!Iterators.isEmpty(upgradeModulePath)) {
try { try {
setLocation(fileManager, "UPGRADE_MODULE_PATH", upgradeModulePath); setLocation(fileManager, "UPGRADE_MODULE_PATH", upgradeModulePath);
} }
@@ -146,14 +146,13 @@ public final class JavacMain {
} }
} }
if (!classpath.isEmpty()) { if (!Iterators.isEmpty(classpath)) {
// because module path has priority if present, initialize classpath after the module path // because module path has priority if present, initialize classpath after the module path
try { try {
fileManager.setLocation(StandardLocation.CLASS_PATH, classpath); fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
if (!usingJavac && if (!usingJavac &&
isAnnotationProcessingEnabled && isAnnotationProcessingEnabled && !Iterators.contains(_options, "-processorpath") &&
!_options.contains("-processorpath") && (javacBefore9 || (!Iterators.contains(_options, "--processor-module-path") && getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null))) {
(javacBefore9 || (!_options.contains("--processor-module-path") && getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null))) {
// for non-javac file manager ensure annotation processor path defaults to classpath // for non-javac file manager ensure annotation processor path defaults to classpath
fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath); fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
} }
@@ -164,7 +163,7 @@ public final class JavacMain {
} }
} }
if (javacBefore9 || !sourcePath.isEmpty() || modulePath.isEmpty()) { if (javacBefore9 || !Iterators.isEmpty(sourcePath) || modulePath.isEmpty()) {
try { try {
// ensure the source path is set; // ensure the source path is set;
// otherwise, if not set, javac attempts to search both classes and sources in classpath; // otherwise, if not set, javac attempts to search both classes and sources in classpath;
@@ -506,11 +505,11 @@ public final class JavacMain {
return compilingTool instanceof JavacCompilerTool && (JAVA_RUNTIME_VERSION.startsWith("1.8.") || JAVA_RUNTIME_VERSION.startsWith("1.7.") || JAVA_RUNTIME_VERSION.startsWith("1.6.")); return compilingTool instanceof JavacCompilerTool && (JAVA_RUNTIME_VERSION.startsWith("1.8.") || JAVA_RUNTIME_VERSION.startsWith("1.7.") || JAVA_RUNTIME_VERSION.startsWith("1.6."));
} }
private static boolean isAnnotationProcessingEnabled(final Collection<String> options) { private static boolean isAnnotationProcessingEnabled(final Iterable<String> options) {
return !options.contains("-proc:none"); return !Iterators.contains(options, "-proc:none");
} }
private static Collection<String> prepareOptions(final Collection<String> options, @NotNull JavaCompilingTool compilingTool) { private static Iterable<String> prepareOptions(final Iterable<? extends String> options, @NotNull JavaCompilingTool compilingTool) {
final List<String> result = new ArrayList<String>(compilingTool.getDefaultCompilerOptions()); final List<String> result = new ArrayList<String>(compilingTool.getDefaultCompilerOptions());
boolean skip = false; boolean skip = false;
for (String option : options) { for (String option : options) {
@@ -529,7 +528,7 @@ public final class JavacMain {
return result; return result;
} }
private static Collection<? extends File> buildPlatformClasspath(Collection<? extends File> platformClasspath, Collection<String> options) { private static Iterable<? extends File> buildPlatformClasspath(Iterable<? extends File> platformClasspath, Iterable<String> options) {
final Map<PathOption, String> argsMap = new HashMap<PathOption, String>(); final Map<PathOption, String> argsMap = new HashMap<PathOption, String>();
for (Iterator<String> iterator = options.iterator(); iterator.hasNext(); ) { for (Iterator<String> iterator = options.iterator(); iterator.hasNext(); ) {
final String arg = iterator.next(); final String arg = iterator.next();
@@ -547,7 +546,7 @@ public final class JavacMain {
appendFiles(argsMap, PathOption.PREPEND_CP, result, false); appendFiles(argsMap, PathOption.PREPEND_CP, result, false);
appendFiles(argsMap, PathOption.ENDORSED, result, true); appendFiles(argsMap, PathOption.ENDORSED, result, true);
appendFiles(argsMap, PathOption.D_ENDORSED, result, true); appendFiles(argsMap, PathOption.D_ENDORSED, result, true);
result.addAll(platformClasspath); Iterators.collect(platformClasspath, result);
appendFiles(argsMap, PathOption.APPEND_CP, result, false); appendFiles(argsMap, PathOption.APPEND_CP, result, false);
appendFiles(argsMap, PathOption.EXTDIRS, result, true); appendFiles(argsMap, PathOption.EXTDIRS, result, true);
appendFiles(argsMap, PathOption.D_EXTDIRS, result, true); appendFiles(argsMap, PathOption.D_EXTDIRS, result, true);

View File

@@ -27,13 +27,13 @@ public final class JavacProtoUtil {
return JavacRemoteProto.Message.Request.newBuilder().setRequestType(JavacRemoteProto.Message.Request.Type.SHUTDOWN).build(); return JavacRemoteProto.Message.Request.newBuilder().setRequestType(JavacRemoteProto.Message.Request.Type.SHUTDOWN).build();
} }
public static JavacRemoteProto.Message.Request createCompilationRequest(List<String> options, public static JavacRemoteProto.Message.Request createCompilationRequest(Iterable<String> options,
Collection<? extends File> files, Iterable<? extends File> files,
Collection<? extends File> classpath, Iterable<? extends File> classpath,
Collection<? extends File> platformCp, Iterable<? extends File> platformCp,
ModulePath modulePath, ModulePath modulePath,
Collection<? extends File> upgradeModulePath, Iterable<? extends File> upgradeModulePath,
Collection<? extends File> sourcePath, Iterable<? extends File> sourcePath,
Map<File, Set<File>> outs) { Map<File, Set<File>> outs) {
final JavacRemoteProto.Message.Request.Builder builder = JavacRemoteProto.Message.Request.newBuilder(); final JavacRemoteProto.Message.Request.Builder builder = JavacRemoteProto.Message.Request.newBuilder();
builder.setRequestType(JavacRemoteProto.Message.Request.Type.COMPILE); builder.setRequestType(JavacRemoteProto.Message.Request.Type.COMPILE);

View File

@@ -10,15 +10,13 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.JavaSourceTransformer; import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import javax.tools.*; import javax.tools.*;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*; import java.util.*;
/** /**
@@ -72,6 +70,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
private Iterable<? extends JavaFileObject> myInputSources = Collections.emptyList(); private Iterable<? extends JavaFileObject> myInputSources = Collections.emptyList();
private final Map<String, JavaFileObject> myInputSourcesIndex = new HashMap<String, JavaFileObject>(); private final Map<String, JavaFileObject> myInputSourcesIndex = new HashMap<String, JavaFileObject>();
private final List<Closeable> myCloseables = new ArrayList<Closeable>();
public JpsJavacFileManager(final Context context, boolean javacBefore9, Collection<? extends JavaSourceTransformer> transformers) { public JpsJavacFileManager(final Context context, boolean javacBefore9, Collection<? extends JavaSourceTransformer> transformers) {
super(context.getStandardFileManager()); super(context.getStandardFileManager());
@@ -157,7 +156,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
@Override @Override
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
final String fileName = packageName.isEmpty()? relativeName : externalizeFileName(packageName, File.separator, relativeName); final String fileName = packageName.isEmpty()? relativeName : externalizeFileName(packageName, "/", relativeName);
return getFileForOutput(location, JpsFileObject.findKind(fileName), fileName, null, sibling); return getFileForOutput(location, JpsFileObject.findKind(fileName), fileName, null, sibling);
} }
@@ -251,21 +250,12 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
@Override @Override
public ClassLoader getClassLoader(Location location) { public ClassLoader getClassLoader(Location location) {
final Iterable<? extends File> path = getLocation(location);
if (path == null) {
return null;
}
final List<URL> urls = new ArrayList<URL>();
for (File f: path) {
try {
urls.add(f.toURI().toURL());
}
catch (MalformedURLException e) {
throw new AssertionError(e);
}
}
// ensure processor's loader will not resolve against JPS classes and libraries used in JPS // ensure processor's loader will not resolve against JPS classes and libraries used in JPS
return new URLClassLoader(urls.toArray(new URL[0]), myContext.getStandardFileManager().getClass().getClassLoader()); final ClassLoader loader = LazyInitClassLoader.createFrom(getLocation(location), myContext.getStandardFileManager().getClass().getClassLoader());
if (loader instanceof Closeable) {
myCloseables.add((Closeable)loader);
}
return loader;
} }
private File getSingleOutputDirectory(final Location loc, final URI sourceUri) { private File getSingleOutputDirectory(final Location loc, final URI sourceUri) {
@@ -314,7 +304,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
for (int i = 0, len = classOrPackageName.length(); i < len; i++) { for (int i = 0, len = classOrPackageName.length(); i < len; i++) {
char ch = classOrPackageName.charAt(i); char ch = classOrPackageName.charAt(i);
buf.append(ch == '.'? File.separatorChar : ch); buf.append(ch == '.'? '/' : ch);
} }
for (CharSequence s : suffix) { for (CharSequence s : suffix) {
buf.append(s); buf.append(s);
@@ -474,7 +464,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
if (isFileSystemLocation(location)) { if (isFileSystemLocation(location)) {
// we consider here only locations that are known to be file-based // we consider here only locations that are known to be file-based
final Iterable<? extends File> locationRoots = getLocation(location); final Iterable<? extends File> locationRoots = getLocation(location);
if (locationRoots == null) { if (Iterators.isEmpty(locationRoots)) {
return Collections.emptyList(); return Collections.emptyList();
} }
result = Iterators.flat(Iterators.map(locationRoots, new Function<File, Iterable<JavaFileObject>>() { result = Iterators.flat(Iterators.map(locationRoots, new Function<File, Iterable<JavaFileObject>>() {
@@ -583,6 +573,14 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
myInputSources = Collections.emptyList(); myInputSources = Collections.emptyList();
myInputSourcesIndex.clear(); myInputSourcesIndex.clear();
myFileOperations.clearCaches(null); myFileOperations.clearCaches(null);
for (Closeable closeable : myCloseables) {
try {
closeable.close();
}
catch (IOException ignored) {
}
}
myCloseables.clear();
} }
} }

View File

@@ -0,0 +1,73 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.jps.javac;
import com.intellij.util.Function;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicBoolean;
class LazyInitClassLoader extends URLClassLoader {
private static final URL[] EMPTY_URL_ARRAY = new URL[0];
private static final AtomicBoolean myInitialized = new AtomicBoolean(false);
private final Iterable<URL> myUrls;
LazyInitClassLoader(Iterable<URL> urls, ClassLoader parent) {
super(EMPTY_URL_ARRAY, parent);
myUrls = urls;
}
@Nullable
static LazyInitClassLoader createFrom(@Nullable Iterable<? extends File> files, ClassLoader parent) {
return files == null? null : new LazyInitClassLoader(Iterators.map(files, new Function<File, URL>() {
@Override
public URL fun(File f) {
try {
return f.toURI().toURL();
}
catch (MalformedURLException e) {
throw new AssertionError(e);
}
}
}), parent);
}
private void init() {
if (!myInitialized.getAndSet(true)) {
for (URL url : myUrls) {
addURL(url);
}
}
}
@Override
public URL[] getURLs() {
init();
return super.getURLs();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
init();
return super.findClass(name);
}
@Override
public URL findResource(String name) {
init();
return super.findResource(name);
}
@Override
public Enumeration<URL> findResources(String name) throws IOException {
init();
return super.findResources(name);
}
}

View File

@@ -14,7 +14,6 @@ import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.concurrency.SequentialTaskExecutor;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FileCollectionFactory; import com.intellij.util.containers.FileCollectionFactory;
import com.intellij.util.containers.JBIterable;
import com.intellij.util.containers.SmartHashSet; import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.execution.ParametersListUtil; import com.intellij.util.execution.ParametersListUtil;
import com.intellij.util.io.BaseOutputReader; import com.intellij.util.io.BaseOutputReader;
@@ -72,9 +71,6 @@ import java.util.stream.Collectors;
import static com.intellij.openapi.util.Pair.pair; import static com.intellij.openapi.util.Pair.pair;
/**
* @author Eugene Zhuravlev
*/
public final class JavaBuilder extends ModuleLevelBuilder { public final class JavaBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance(JavaBuilder.class); private static final Logger LOG = Logger.getInstance(JavaBuilder.class);
private static final String JAVA_EXTENSION = "java"; private static final String JAVA_EXTENSION = "java";
@@ -92,17 +88,23 @@ public final class JavaBuilder extends ModuleLevelBuilder {
private static final Key<ModulePathSplitter> MODULE_PATH_SPLITTER = GlobalContextKey.create("_module_path_splitter_"); private static final Key<ModulePathSplitter> MODULE_PATH_SPLITTER = GlobalContextKey.create("_module_path_splitter_");
private static final List<String> COMPILABLE_EXTENSIONS = Collections.singletonList(JAVA_EXTENSION); private static final List<String> COMPILABLE_EXTENSIONS = Collections.singletonList(JAVA_EXTENSION);
private static final String PROC_ONLY_OPTION = "-proc:only";
private static final String RELEASE_OPTION = "--release";
private static final String TARGET_OPTION = "-target";
private static final String PROC_NONE_OPTION = "-proc:none";
private static final String PROCESSORPATH_OPTION = "-processorpath";
private static final String ENCODING_OPTION = "-encoding";
private static final String ENABLE_PREVIEW_OPTION = "--enable-preview";
private static final String PROCESSOR_MODULE_PATH_OPTION = "--processor-module-path";
private static final String SOURCE_OPTION = "-source";
private static final Set<String> FILTERED_OPTIONS = ContainerUtil.newHashSet( private static final Set<String> FILTERED_OPTIONS = ContainerUtil.newHashSet(
"-target", "--release", "-d" TARGET_OPTION, RELEASE_OPTION, "-d"
); );
private static final Set<String> FILTERED_SINGLE_OPTIONS = ContainerUtil.newHashSet( private static final Set<String> FILTERED_SINGLE_OPTIONS = ContainerUtil.newHashSet(
"-g", "-deprecation", "-nowarn", "-verbose", "-proc:none", "-proc:only", "-proceedOnError" "-g", "-deprecation", "-nowarn", "-verbose", PROC_NONE_OPTION, PROC_ONLY_OPTION, "-proceedOnError"
); );
private static final Set<String> POSSIBLY_CONFLICTING_OPTIONS = ContainerUtil.newHashSet( private static final Set<String> POSSIBLY_CONFLICTING_OPTIONS = ContainerUtil.newHashSet(
"--boot-class-path", "-bootclasspath", "--boot-class-path", "-bootclasspath", "--class-path", "-classpath", "-cp", PROCESSORPATH_OPTION, "-sourcepath", "--module-path", "-p", "--module-source-path"
"--class-path", "-classpath", "-cp",
"-processorpath", "-sourcepath",
"--module-path", "-p", "--module-source-path"
); );
private static final List<ClassPostProcessor> ourClassProcessors = new ArrayList<>(); private static final List<ClassPostProcessor> ourClassProcessors = new ArrayList<>();
@@ -398,7 +400,6 @@ public final class JavaBuilder extends ModuleLevelBuilder {
final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getCompilerConfiguration( final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getCompilerConfiguration(
context.getProjectDescriptor().getProject() context.getProjectDescriptor().getProject()
); );
assert compilerConfig != null;
if (modules.size() == 1) { if (modules.size() == 1) {
profile = compilerConfig.getAnnotationProcessingProfile(modules.iterator().next()); profile = compilerConfig.getAnnotationProcessingProfile(modules.iterator().next());
@@ -414,43 +415,39 @@ public final class JavaBuilder extends ModuleLevelBuilder {
final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk); final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk);
try { try {
final int targetLanguageLevel = getTargetPlatformLanguageVersion(chunk.representativeTarget().getModule()); final int targetLanguageLevel = getTargetPlatformLanguageVersion(chunk.representativeTarget().getModule());
final boolean shouldForkJavac = shouldForkCompilerProcess(context, chunk, targetLanguageLevel);
// when forking external javac, compilers from SDK 1.6 and higher are supported // when forking external javac, compilers from SDK 1.6 and higher are supported
Pair<String, Integer> forkSdk = null; final Pair<String, Integer> forkSdk;
if (shouldForkJavac) { if (shouldForkCompilerProcess(context, chunk, targetLanguageLevel)) {
forkSdk = getForkedJavacSdk(chunk, targetLanguageLevel); forkSdk = getForkedJavacSdk(chunk, targetLanguageLevel);
if (forkSdk == null) { if (forkSdk == null) {
diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, JpsBuildBundle.message("build.message.cannot.start.javac.process.for.0.unknown.jdk.home", chunk.getName()))); diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, JpsBuildBundle.message("build.message.cannot.start.javac.process.for.0.unknown.jdk.home", chunk.getName())));
return false; return false;
} }
} }
else {
forkSdk = null;
}
final int compilerSdkVersion = forkSdk == null ? JavaVersion.current().feature : forkSdk.getSecond(); final int compilerSdkVersion = forkSdk == null ? JavaVersion.current().feature : forkSdk.getSecond();
final Pair<List<String>, List<String>> vm_compilerOptions = getCompilationOptions( final Pair<Iterable<String>, Iterable<String>> vm_compilerOptions = getCompilationOptions(compilerSdkVersion, context, chunk, profile, compilingTool);
compilerSdkVersion, context, chunk, profile, compilingTool final Iterable<String> vmOptions = vm_compilerOptions.first;
); final Iterable<String> options = vm_compilerOptions.second;
final List<String> vmOptions = vm_compilerOptions.first;
final List<String> options = vm_compilerOptions.second;
if (LOG.isDebugEnabled()) { Iterable<? extends File> effectivePlatformCp = calcEffectivePlatformCp(originalPlatformCp, options, compilingTool);
String mode = shouldForkJavac ? "fork" : "in-process"; if (effectivePlatformCp == null) {
LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\", mode=" + mode); String text = JpsBuildBundle.message(
} "build.message.unsupported.compact.compilation.profile.was.requested", chunk.getName(), System.getProperty("java.version")
);
Collection<? extends File> platformCp = calcEffectivePlatformCp(originalPlatformCp, options, compilingTool);
if (platformCp == null) {
String text = JpsBuildBundle.message("build.message.unsupported.compact.compilation.profile.was.requested", chunk.getName(),
System.getProperty("java.version"));
context.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.ERROR, text)); context.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.ERROR, text));
return false; return false;
} }
Collection<? extends File> classPath = originalClassPath; final Iterable<? extends File> platformCp;
ModulePath modulePath = ModulePath.EMPTY; final Iterable<? extends File> classPath;
Collection<? extends File> upgradeModulePath = Collections.emptyList(); final ModulePath modulePath;
final Iterable<? extends File> upgradeModulePath;
if (moduleInfoFile != null) { // has modules if (moduleInfoFile != null) { // has modules
final ModulePathSplitter splitter = MODULE_PATH_SPLITTER.get(context); final ModulePathSplitter splitter = MODULE_PATH_SPLITTER.get(context);
final Pair<ModulePath, Collection<File>> pair = splitter.splitPath( final Pair<ModulePath, Collection<File>> pair = splitter.splitPath(
@@ -473,44 +470,93 @@ public final class JavaBuilder extends ModuleLevelBuilder {
classPath = pair.second; classPath = pair.second;
} }
// modules above the JDK in the order entry list make a module upgrade path // modules above the JDK in the order entry list make a module upgrade path
upgradeModulePath = platformCp; upgradeModulePath = effectivePlatformCp;
platformCp = Collections.emptyList(); platformCp = Collections.emptyList();
} }
else {
if (!platformCp.isEmpty() && (getChunkSdkVersion(chunk)) >= 9) { modulePath = ModulePath.EMPTY;
// if chunk's SDK is 9 or higher, there is no way to specify full platform classpath upgradeModulePath = Collections.emptyList();
// because platform classes are stored in jimage binary files with unknown format. if (!Iterators.isEmpty(effectivePlatformCp) && (getChunkSdkVersion(chunk)) >= 9) {
// Because of this we are clearing platform classpath so that javac will resolve against its own boot classpath // if chunk's SDK is 9 or higher, there is no way to specify full platform classpath
// and prepending additional jars from the JDK configuration to compilation classpath // because platform classes are stored in jimage binary files with unknown format.
classPath = JBIterable.<File>from(platformCp).append(classPath).toList(); // Because of this we are clearing platform classpath so that javac will resolve against its own boot classpath
platformCp = Collections.emptyList(); // and prepending additional jars from the JDK configuration to compilation classpath
platformCp = Collections.emptyList();
classPath = Iterators.flat(effectivePlatformCp, originalClassPath);
}
else {
platformCp = effectivePlatformCp;
classPath = originalClassPath;
}
} }
final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink); final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink);
final boolean rc;
if (!shouldForkJavac) { if (forkSdk != null) {
updateCompilerUsageStatistics(context, compilingTool.getDescription(), chunk);
rc = JavacMain.compile(
options, files, classPath, platformCp, modulePath, upgradeModulePath, sourcePath, outs, diagnosticSink, classesConsumer,
context.getCancelStatus(), compilingTool
);
}
else {
updateCompilerUsageStatistics(context, "javac " + forkSdk.getSecond(), chunk); updateCompilerUsageStatistics(context, "javac " + forkSdk.getSecond(), chunk);
final ExternalJavacManager server = ensureJavacServerStarted(context); final ExternalJavacManager server = ensureJavacServerStarted(context);
final CompilationPaths paths = CompilationPaths.create(platformCp, classPath, upgradeModulePath, modulePath, sourcePath); final CompilationPaths paths = CompilationPaths.create(platformCp, classPath, upgradeModulePath, modulePath, sourcePath);
rc = server.forkJavac( final int heapSize = Utils.suggestForkedCompilerHeapSize();
forkSdk.getFirst(), Utils.suggestForkedCompilerHeapSize(), return invokeJavac(compilerSdkVersion, context, chunk, compilingTool, options, files, classesConsumer, (_options, _files, _outSink) -> {
vmOptions, options, paths, files, outs, diagnosticSink, classesConsumer, compilingTool, context.getCancelStatus(), true logJavacCall(chunk, _options, "fork");
).get(); return server.forkJavac(
forkSdk.getFirst(), heapSize, vmOptions, _options, paths, _files, outs, diagnosticSink, _outSink, compilingTool, context.getCancelStatus(), true
).get();
});
} }
return rc;
updateCompilerUsageStatistics(context, compilingTool.getDescription(), chunk);
return invokeJavac(compilerSdkVersion, context, chunk, compilingTool, options, files, classesConsumer, (_options, _files, _outSink) -> {
logJavacCall(chunk, _options, "in-process");
return JavacMain.compile(
_options, _files, classPath, platformCp, modulePath, upgradeModulePath, sourcePath, outs, diagnosticSink, _outSink, context.getCancelStatus(), compilingTool
);
});
} }
finally { finally {
counter.waitFor(); counter.waitFor();
} }
} }
private static void logJavacCall(ModuleChunk chunk, Iterable<? extends String> options, final String mode) {
if (LOG.isDebugEnabled()) {
LOG.debug((Iterators.contains(options, PROC_ONLY_OPTION)? "Running processors for chunk" : "Compiling chunk") + " [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\", mode=" + mode);
}
}
private interface JavacCaller {
boolean invoke(Iterable<String> options, Iterable<? extends File> files, OutputFileConsumer outSink);
}
private static boolean invokeJavac(
int compilerSdkVersion,
CompileContext context,
ModuleChunk chunk,
@NotNull JavaCompilingTool compilingTool,
Iterable<String> options,
Iterable<? extends File> files,
OutputFileConsumer outSink,
JavacCaller javacCall
) {
if (Iterators.contains(options, PROC_ONLY_OPTION)) {
// make a dedicated javac call for annotation processing only
final Collection<File> generated = new ArrayList<>();
final boolean processingSuccess = javacCall.invoke(options, files, fileObject -> {
if (fileObject.getKind() == JavaFileObject.Kind.SOURCE) {
generated.add(fileObject.getFile());
}
outSink.save(fileObject);
});
if (!processingSuccess) {
return false;
}
// now call javac with processor-generated sources and without processing-related options
final Iterable<String> compileOnlyOptions = getCompilationOptions(compilerSdkVersion, context, chunk, null, compilingTool).second;
return javacCall.invoke(compileOnlyOptions, Iterators.flat(files, generated), outSink);
}
return javacCall.invoke(options, files, outSink);
}
private static void updateCompilerUsageStatistics(CompileContext context, String compilerName, ModuleChunk chunk) { private static void updateCompilerUsageStatistics(CompileContext context, String compilerName, ModuleChunk chunk) {
final ConcurrentMap<String, Collection<String>> map = COMPILER_USAGE_STATISTICS.get(context); final ConcurrentMap<String, Collection<String>> map = COMPILER_USAGE_STATISTICS.get(context);
Collection<String> names = map.get(compilerName); Collection<String> names = map.get(compilerName);
@@ -530,7 +576,6 @@ public final class JavaBuilder extends ModuleLevelBuilder {
public static @Nls String validateCycle(CompileContext context, ModuleChunk chunk) { public static @Nls String validateCycle(CompileContext context, ModuleChunk chunk) {
final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance(); final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance();
final JpsJavaCompilerConfiguration compilerConfig = javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject()); final JpsJavaCompilerConfiguration compilerConfig = javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject());
assert compilerConfig != null;
final Set<JpsModule> modules = chunk.getModules(); final Set<JpsModule> modules = chunk.getModules();
Pair<String, LanguageLevel> pair = null; Pair<String, LanguageLevel> pair = null;
for (JpsModule module : modules) { for (JpsModule module : modules) {
@@ -564,8 +609,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
else { else {
context.processMessage(new CompilerMessage( context.processMessage(new CompilerMessage(
getBuilderName(), BuildMessage.Kind.WARNING, getBuilderName(), BuildMessage.Kind.WARNING,
JpsBuildBundle.message("build.message.some.modules.with.cyclic.dependencies.0.have.additional.command.line.parameters", JpsBuildBundle.message("build.message.some.modules.with.cyclic.dependencies.0.have.additional.command.line.parameters", chunk.getName())
chunk.getName())
)); ));
} }
} }
@@ -653,11 +697,9 @@ public final class JavaBuilder extends ModuleLevelBuilder {
private static boolean preferTargetJdkCompiler(CompileContext context) { private static boolean preferTargetJdkCompiler(CompileContext context) {
Boolean val = PREFER_TARGET_JDK_COMPILER.get(context); Boolean val = PREFER_TARGET_JDK_COMPILER.get(context);
if (val == null) { if (val == null) {
final JpsProject project = context.getProjectDescriptor().getProject(); JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(context.getProjectDescriptor().getProject());
final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
// default // default
val = config != null? config.getCompilerOptions(JavaCompilers.JAVAC_ID).PREFER_TARGET_JDK_COMPILER : Boolean.TRUE; PREFER_TARGET_JDK_COMPILER.set(context, val = config.getCompilerOptions(JavaCompilers.JAVAC_ID).PREFER_TARGET_JDK_COMPILER);
PREFER_TARGET_JDK_COMPILER.set(context, val);
} }
return val; return val;
} }
@@ -665,7 +707,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
// If platformCp of the build process is the same as the target platform, do not specify platformCp explicitly // If platformCp of the build process is the same as the target platform, do not specify platformCp explicitly
// this will allow javac to resolve against ct.sym file, which is required for the "compilation profiles" feature // this will allow javac to resolve against ct.sym file, which is required for the "compilation profiles" feature
@Nullable @Nullable
private static Collection<? extends File> calcEffectivePlatformCp(Collection<? extends File> platformCp, List<String> options, JavaCompilingTool compilingTool) { private static Iterable<? extends File> calcEffectivePlatformCp(Collection<? extends File> platformCp, Iterable<String> options, JavaCompilingTool compilingTool) {
if (ourDefaultRtJar == null || !isJavac(compilingTool)) { if (ourDefaultRtJar == null || !isJavac(compilingTool)) {
return platformCp; return platformCp;
} }
@@ -772,7 +814,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
private static final Key<String> USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_"); private static final Key<String> USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_");
private static Pair<List<String>, List<String>> getCompilationOptions(int compilerSdkVersion, private static Pair<Iterable<String>, Iterable<String>> getCompilationOptions(int compilerSdkVersion,
CompileContext context, CompileContext context,
ModuleChunk chunk, ModuleChunk chunk,
@Nullable ProcessorConfigProfile profile, @Nullable ProcessorConfigProfile profile,
@@ -830,7 +872,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
for (final String userOption : ParametersListUtil.parse(customArgs)) { for (final String userOption : ParametersListUtil.parse(customArgs)) {
if (FILTERED_OPTIONS.contains(userOption)) { if (FILTERED_OPTIONS.contains(userOption)) {
skip = true; skip = true;
targetOptionFound = "-target".equals(userOption); targetOptionFound = TARGET_OPTION.equals(userOption);
notifyOptionIgnored(context, userOption, chunk); notifyOptionIgnored(context, userOption, chunk);
continue; continue;
} }
@@ -864,7 +906,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
vmOptions.addAll(extension.getOptions(compilingTool)); vmOptions.addAll(extension.getOptions(compilingTool));
} }
addCompilationOptions(compilerSdkVersion, compilationOptions, context, chunk, profile); addCompilationOptions(compilerSdkVersion, compilationOptions, context, chunk, profile, true);
return pair(vmOptions, compilationOptions); return pair(vmOptions, compilationOptions);
} }
@@ -887,14 +929,14 @@ public final class JavaBuilder extends ModuleLevelBuilder {
CompileContext context, CompileContext context,
ModuleChunk chunk, ModuleChunk chunk,
@Nullable ProcessorConfigProfile profile) { @Nullable ProcessorConfigProfile profile) {
addCompilationOptions(JavaVersion.current().feature, options, context, chunk, profile); addCompilationOptions(JavaVersion.current().feature, options, context, chunk, profile, false);
} }
private static void addCompilationOptions(int compilerSdkVersion, private static void addCompilationOptions(int compilerSdkVersion,
List<? super String> options, List<? super String> options,
CompileContext context, ModuleChunk chunk, CompileContext context, ModuleChunk chunk,
@Nullable ProcessorConfigProfile profile) { @Nullable ProcessorConfigProfile profile, boolean procOnlySupported) {
if (!options.contains("-encoding")) { if (!options.contains(ENCODING_OPTION)) {
final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration(); final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration();
final String encoding = config.getPreferredModuleChunkEncoding(chunk); final String encoding = config.getPreferredModuleChunkEncoding(chunk);
if (config.getAllModuleChunkEncodings(chunk).size() > 1) { if (config.getAllModuleChunkEncodings(chunk).size() > 1) {
@@ -902,21 +944,27 @@ public final class JavaBuilder extends ModuleLevelBuilder {
context.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.INFO, message)); context.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.INFO, message));
} }
if (!StringUtil.isEmpty(encoding)) { if (!StringUtil.isEmpty(encoding)) {
options.add("-encoding"); options.add(ENCODING_OPTION);
options.add(encoding); options.add(encoding);
} }
} }
addCrossCompilationOptions(compilerSdkVersion, options, context, chunk); addCrossCompilationOptions(compilerSdkVersion, options, context, chunk);
if (!options.contains("--enable-preview")) { if (!options.contains(ENABLE_PREVIEW_OPTION)) {
LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(chunk.representativeTarget().getModule()); LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(chunk.representativeTarget().getModule());
if (level != null && level.isPreview()) { if (level != null && level.isPreview()) {
options.add("--enable-preview"); options.add(ENABLE_PREVIEW_OPTION);
} }
} }
if (addAnnotationProcessingOptions(options, profile)) { if (addAnnotationProcessingOptions(options, profile)) {
assert profile != null;
if (procOnlySupported && profile.isProcOnly()) {
options.add(PROC_ONLY_OPTION);
}
final File srcOutput = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir( final File srcOutput = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir(
chunk.getModules().iterator().next(), chunk.containsTests(), profile chunk.getModules().iterator().next(), chunk.containsTests(), profile
); );
@@ -933,14 +981,14 @@ public final class JavaBuilder extends ModuleLevelBuilder {
*/ */
public static boolean addAnnotationProcessingOptions(List<? super String> options, @Nullable AnnotationProcessingConfiguration profile) { public static boolean addAnnotationProcessingOptions(List<? super String> options, @Nullable AnnotationProcessingConfiguration profile) {
if (profile == null || !profile.isEnabled()) { if (profile == null || !profile.isEnabled()) {
options.add("-proc:none"); options.add(PROC_NONE_OPTION);
return false; return false;
} }
// configuring annotation processing // configuring annotation processing
if (!profile.isObtainProcessorsFromClasspath()) { if (!profile.isObtainProcessorsFromClasspath()) {
final String processorsPath = profile.getProcessorPath(); final String processorsPath = profile.getProcessorPath();
options.add(profile.isUseProcessorModulePath() ? "--processor-module-path" : "-processorpath"); options.add(profile.isUseProcessorModulePath() ? PROCESSOR_MODULE_PATH_OPTION : PROCESSORPATH_OPTION);
options.add(FileUtil.toSystemDependentName(processorsPath.trim())); options.add(FileUtil.toSystemDependentName(processorsPath.trim()));
} }
@@ -973,14 +1021,14 @@ public final class JavaBuilder extends ModuleLevelBuilder {
int bytecodeTarget = getModuleBytecodeTarget(context, chunk, compilerConfiguration, languageLevel); int bytecodeTarget = getModuleBytecodeTarget(context, chunk, compilerConfiguration, languageLevel);
if (shouldUseReleaseOption(compilerConfiguration, compilerSdkVersion, chunkSdkVersion, bytecodeTarget)) { if (shouldUseReleaseOption(compilerConfiguration, compilerSdkVersion, chunkSdkVersion, bytecodeTarget)) {
options.add("--release"); options.add(RELEASE_OPTION);
options.add(complianceOption(bytecodeTarget)); options.add(complianceOption(bytecodeTarget));
return; return;
} }
// using older -source, -target and -bootclasspath options // using older -source, -target and -bootclasspath options
if (languageLevel > 0) { if (languageLevel > 0) {
options.add("-source"); options.add(SOURCE_OPTION);
options.add(complianceOption(languageLevel)); options.add(complianceOption(languageLevel));
} }
@@ -1006,7 +1054,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
} }
if (bytecodeTarget > 0) { if (bytecodeTarget > 0) {
options.add("-target"); options.add(TARGET_OPTION);
options.add(complianceOption(bytecodeTarget)); options.add(complianceOption(bytecodeTarget));
} }
} }
@@ -1329,8 +1377,9 @@ public final class JavaBuilder extends ModuleLevelBuilder {
content.saveToFile(file); content.saveToFile(file);
} }
else { else {
myContext.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.WARNING, myContext.processMessage(new CompilerMessage(
JpsBuildBundle.message("build.message.missing.content.for.file.0", file.getPath()))); getBuilderName(), BuildMessage.Kind.WARNING, JpsBuildBundle.message("build.message.missing.content.for.file.0", file.getPath()))
);
} }
} }
catch (IOException e) { catch (IOException e) {

View File

@@ -5,48 +5,38 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.util.Collection;
import java.util.Collections;
/**
* @author Eugene Zhuravlev
* Date: 14-Nov-18
*/
public class CompilationPaths { public class CompilationPaths {
private final Collection<File> myPlatformClasspath; private final Iterable<? extends File> myPlatformClasspath;
private final Collection<File> myClasspath; private final Iterable<? extends File> myClasspath;
private final Collection<File> myUpgradeModulePath; private final Iterable<? extends File> myUpgradeModulePath;
private final ModulePath myModulePath; private final ModulePath myModulePath;
private final Collection<File> mySourcePath; private final Iterable<? extends File> mySourcePath;
public CompilationPaths(Collection<? extends File> platformClasspath, public CompilationPaths(Iterable<? extends File> platformClasspath,
Collection<? extends File> classpath, Iterable<? extends File> classpath,
Collection<? extends File> upgradeModulePath, Iterable<? extends File> upgradeModulePath,
ModulePath modulePath, ModulePath modulePath,
Collection<? extends File> sourcePath) { Iterable<? extends File> sourcePath) {
myPlatformClasspath = constCollection(platformClasspath); myPlatformClasspath = platformClasspath;
myClasspath = constCollection(classpath); myClasspath = classpath;
myUpgradeModulePath = constCollection(upgradeModulePath); myUpgradeModulePath = upgradeModulePath;
myModulePath = modulePath; myModulePath = modulePath;
mySourcePath = constCollection(sourcePath); mySourcePath = sourcePath;
}
private static <T> Collection<T> constCollection(Collection<? extends T> col) {
return col == null || col.isEmpty()? Collections.emptyList() : Collections.unmodifiableCollection(col);
} }
@NotNull @NotNull
public Collection<File> getPlatformClasspath() { public Iterable<? extends File> getPlatformClasspath() {
return myPlatformClasspath; return myPlatformClasspath;
} }
@NotNull @NotNull
public Collection<File> getClasspath() { public Iterable<? extends File> getClasspath() {
return myClasspath; return myClasspath;
} }
@NotNull @NotNull
public Collection<File> getUpgradeModulePath() { public Iterable<? extends File> getUpgradeModulePath() {
return myUpgradeModulePath; return myUpgradeModulePath;
} }
@@ -56,15 +46,15 @@ public class CompilationPaths {
} }
@NotNull @NotNull
public Collection<File> getSourcePath() { public Iterable<? extends File> getSourcePath() {
return mySourcePath; return mySourcePath;
} }
public static CompilationPaths create(@Nullable Collection<? extends File> platformCp, public static CompilationPaths create(@Nullable Iterable<? extends File> platformCp,
@Nullable Collection<? extends File> cp, @Nullable Iterable<? extends File> cp,
@Nullable Collection<? extends File> upgradeModCp, @Nullable Iterable<? extends File> upgradeModCp,
@NotNull ModulePath modulePath, @NotNull ModulePath modulePath,
@Nullable Collection<? extends File> sourcePath) { @Nullable Iterable<? extends File> sourcePath) {
return new CompilationPaths(platformCp, cp, upgradeModCp, modulePath, sourcePath); return new CompilationPaths(platformCp, cp, upgradeModCp, modulePath, sourcePath);
} }

View File

@@ -114,7 +114,7 @@ public class ExternalJavacManager extends ProcessAdapter {
} }
/** /**
* @deprecated Use {@link #forkJavac(String, int, List, List, CompilationPaths, Collection, Map, DiagnosticOutputConsumer, OutputFileConsumer, JavaCompilingTool, CanceledStatus, boolean)} instead * @deprecated Use {@link #forkJavac(String, int, Iterable, Iterable, CompilationPaths, Iterable, Map, DiagnosticOutputConsumer, OutputFileConsumer, JavaCompilingTool, CanceledStatus, boolean)} instead
*/ */
@Deprecated @Deprecated
public boolean forkJavac(String javaHome, public boolean forkJavac(String javaHome,
@@ -142,10 +142,10 @@ public class ExternalJavacManager extends ProcessAdapter {
public ExternalJavacRunResult forkJavac(String javaHome, public ExternalJavacRunResult forkJavac(String javaHome,
int heapSize, int heapSize,
List<String> vmOptions, Iterable<String> vmOptions,
List<String> options, Iterable<String> options,
CompilationPaths paths, CompilationPaths paths,
Collection<? extends File> files, Iterable<? extends File> files,
Map<File, Set<File>> outs, Map<File, Set<File>> outs,
DiagnosticOutputConsumer diagnosticSink, DiagnosticOutputConsumer diagnosticSink,
OutputFileConsumer outputSink, OutputFileConsumer outputSink,
@@ -256,14 +256,20 @@ public class ExternalJavacManager extends ProcessAdapter {
} }
} }
private static int processHash(String sdkHomePath, List<String> vmOptions, JavaCompilingTool tool) { private static int processHash(String sdkHomePath, Iterable<String> vmOptions, JavaCompilingTool tool) {
return Objects.hash(sdkHomePath.replace(File.separatorChar, '/'), vmOptions, tool.getId()); Collection<? extends String> opts = vmOptions instanceof Collection<?>? (Collection<String>)vmOptions : Iterators.collect(vmOptions, new ArrayList<>());
return Objects.hash(sdkHomePath.replace(File.separatorChar, '/'), opts, tool.getId());
} }
@Nullable @Nullable
private static String getEncodingName(List<String> options) { private static String getEncodingName(Iterable<String> options) {
int p = options.indexOf("-encoding"); for (Iterator<String> it = options.iterator(); it.hasNext(); ) {
return p >= 0 && p < options.size() - 1 ? options.get(p + 1) : null; final String option = it.next();
if ("-encoding".equals(option)) {
return it.hasNext()? it.next() : null;
}
}
return null;
} }
public boolean isRunning() { public boolean isRunning() {
@@ -324,7 +330,7 @@ public class ExternalJavacManager extends ProcessAdapter {
int heapSize, int heapSize,
int port, int port,
File workingDir, File workingDir,
List<String> vmOptions, Iterable<String> vmOptions,
JavaCompilingTool compilingTool, JavaCompilingTool compilingTool,
final boolean keepProcessAlive) throws Exception { final boolean keepProcessAlive) throws Exception {
final UUID processId = UUID.randomUUID(); final UUID processId = UUID.randomUUID();

View File

@@ -20,9 +20,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
/**
* @author Eugene Zhuravlev
*/
public interface AnnotationProcessingConfiguration { public interface AnnotationProcessingConfiguration {
boolean isEnabled(); boolean isEnabled();
@@ -43,4 +40,6 @@ public interface AnnotationProcessingConfiguration {
Map<String, String> getProcessorOptions(); Map<String, String> getProcessorOptions();
boolean isObtainProcessorsFromClasspath(); boolean isObtainProcessorsFromClasspath();
boolean isProcOnly();
} }

View File

@@ -42,6 +42,8 @@ public interface ProcessorConfigProfile extends AnnotationProcessingConfiguratio
void setGeneratedSourcesDirectoryName(@Nullable String generatedSourcesDirectoryName, boolean forTests); void setGeneratedSourcesDirectoryName(@Nullable String generatedSourcesDirectoryName, boolean forTests);
void setProcOnly(boolean value);
@NotNull @NotNull
Set<String> getModuleNames(); Set<String> getModuleNames();

View File

@@ -7,9 +7,6 @@ import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
import java.util.*; import java.util.*;
/**
* @author Eugene Zhuravlev
*/
public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile { public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile {
private String myName = ""; private String myName = "";
private boolean myEnabled = false; private boolean myEnabled = false;
@@ -21,6 +18,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile
private String myGeneratedProductionDirectoryName = DEFAULT_PRODUCTION_DIR_NAME; private String myGeneratedProductionDirectoryName = DEFAULT_PRODUCTION_DIR_NAME;
private String myGeneratedTestsDirectoryName = DEFAULT_TESTS_DIR_NAME; private String myGeneratedTestsDirectoryName = DEFAULT_TESTS_DIR_NAME;
private boolean myOutputRelativeToContentRoot = false; private boolean myOutputRelativeToContentRoot = false;
private boolean myIsProcOnly = false;
private final Set<String> myModuleNames = new HashSet<>(1); private final Set<String> myModuleNames = new HashSet<>(1);
@@ -36,6 +34,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile
public final void initFrom(ProcessorConfigProfile other) { public final void initFrom(ProcessorConfigProfile other) {
myName = other.getName(); myName = other.getName();
myEnabled = other.isEnabled(); myEnabled = other.isEnabled();
myIsProcOnly = other.isProcOnly();
myObtainProcessorsFromClasspath = other.isObtainProcessorsFromClasspath(); myObtainProcessorsFromClasspath = other.isObtainProcessorsFromClasspath();
myProcessorPath = other.getProcessorPath(); myProcessorPath = other.getProcessorPath();
myUseProcessorModulePath = other.isUseProcessorModulePath(); myUseProcessorModulePath = other.isUseProcessorModulePath();
@@ -127,6 +126,16 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile
myOutputRelativeToContentRoot = relativeToContent; myOutputRelativeToContentRoot = relativeToContent;
} }
@Override
public boolean isProcOnly() {
return myIsProcOnly;
}
@Override
public void setProcOnly(boolean value) {
myIsProcOnly = value;
}
@Override @Override
@NotNull @NotNull
public Set<String> getModuleNames() { public Set<String> getModuleNames() {
@@ -209,6 +218,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile
ProcessorConfigProfileImpl profile = (ProcessorConfigProfileImpl)o; ProcessorConfigProfileImpl profile = (ProcessorConfigProfileImpl)o;
if (myEnabled != profile.myEnabled) return false; if (myEnabled != profile.myEnabled) return false;
if (myIsProcOnly != profile.myIsProcOnly) return false;
if (myObtainProcessorsFromClasspath != profile.myObtainProcessorsFromClasspath) return false; if (myObtainProcessorsFromClasspath != profile.myObtainProcessorsFromClasspath) return false;
if (myGeneratedProductionDirectoryName != null if (myGeneratedProductionDirectoryName != null
? !myGeneratedProductionDirectoryName.equals(profile.myGeneratedProductionDirectoryName) ? !myGeneratedProductionDirectoryName.equals(profile.myGeneratedProductionDirectoryName)
@@ -235,6 +245,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile
public int hashCode() { public int hashCode() {
int result = myName.hashCode(); int result = myName.hashCode();
result = 31 * result + (myEnabled ? 1 : 0); result = 31 * result + (myEnabled ? 1 : 0);
result = 31 * result + (myIsProcOnly ? 1 : 0);
result = 31 * result + (myObtainProcessorsFromClasspath ? 1 : 0); result = 31 * result + (myObtainProcessorsFromClasspath ? 1 : 0);
result = 31 * result + (myProcessorPath != null ? myProcessorPath.hashCode() : 0); result = 31 * result + (myProcessorPath != null ? myProcessorPath.hashCode() : 0);
result = 31 * result + myProcessors.hashCode(); result = 31 * result + myProcessors.hashCode();

View File

@@ -16,6 +16,7 @@ public final class AnnotationProcessorProfileSerializer {
private static final String NAME = "name"; private static final String NAME = "name";
private static final String VALUE = "value"; private static final String VALUE = "value";
private static final String ENABLED = "enabled"; private static final String ENABLED = "enabled";
private static final String PROC_ONLY = "procOnly";
private static final String OPTION = "option"; private static final String OPTION = "option";
private static final String MODULE = "module"; private static final String MODULE = "module";
private static final String USE_CLASSPATH = "useClasspath"; private static final String USE_CLASSPATH = "useClasspath";
@@ -24,6 +25,7 @@ public final class AnnotationProcessorProfileSerializer {
public static void readExternal(ProcessorConfigProfile profile, Element element) { public static void readExternal(ProcessorConfigProfile profile, Element element) {
profile.setName(element.getAttributeValue(NAME, "")); profile.setName(element.getAttributeValue(NAME, ""));
profile.setEnabled(Boolean.valueOf(element.getAttributeValue(ENABLED, "false"))); profile.setEnabled(Boolean.valueOf(element.getAttributeValue(ENABLED, "false")));
profile.setProcOnly(Boolean.valueOf(element.getAttributeValue(PROC_ONLY, "false")));
final Element srcOutput = element.getChild("sourceOutputDir"); final Element srcOutput = element.getChild("sourceOutputDir");
final String out = srcOutput != null ? srcOutput.getAttributeValue(NAME) : null; final String out = srcOutput != null ? srcOutput.getAttributeValue(NAME) : null;
@@ -87,7 +89,9 @@ public final class AnnotationProcessorProfileSerializer {
if (profile.isEnabled()) { if (profile.isEnabled()) {
element.setAttribute(ENABLED, Boolean.toString(profile.isEnabled())); element.setAttribute(ENABLED, Boolean.toString(profile.isEnabled()));
} }
if (profile.isProcOnly()) {
element.setAttribute(PROC_ONLY, Boolean.toString(profile.isProcOnly()));
}
final String srcDirName = profile.getGeneratedSourcesDirectoryName(false); final String srcDirName = profile.getGeneratedSourcesDirectoryName(false);
if (!StringUtil.equals(ProcessorConfigProfile.DEFAULT_PRODUCTION_DIR_NAME, srcDirName)) { if (!StringUtil.equals(ProcessorConfigProfile.DEFAULT_PRODUCTION_DIR_NAME, srcDirName)) {
addChild(element, "sourceOutputDir").setAttribute(NAME, FileUtil.toSystemIndependentName(srcDirName)); addChild(element, "sourceOutputDir").setAttribute(NAME, FileUtil.toSystemIndependentName(srcDirName));