From 809200f825cbac373a51092f475378f0a960cb6c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 2 Dec 2020 13:51:32 +0100 Subject: [PATCH] annotation processing "proc:only" mode support (IDEA-253719) GitOrigin-RevId: 24a2dc446de47bf223b83329a0bc1a87992306e7 --- .../options/ProcessorProfilePanel.java | 10 +- .../messages/JavaCompilerBundle.properties | 1 + ...ractRefCollectorCompilerToolExtension.java | 3 +- .../org/jetbrains/jps/javac/Iterators.java | 28 ++- .../jps/javac/JavaCompilerToolExtension.java | 13 +- .../org/jetbrains/jps/javac/JavacMain.java | 41 ++-- .../jetbrains/jps/javac/JavacProtoUtil.java | 12 +- .../jps/javac/JpsJavacFileManager.java | 38 ++-- .../jps/javac/LazyInitClassLoader.java | 73 ++++++ .../jps/incremental/java/JavaBuilder.java | 207 +++++++++++------- .../jetbrains/jps/javac/CompilationPaths.java | 50 ++--- .../jps/javac/ExternalJavacManager.java | 26 ++- .../AnnotationProcessingConfiguration.java | 5 +- .../java/compiler/ProcessorConfigProfile.java | 2 + .../compiler/ProcessorConfigProfileImpl.java | 17 +- .../AnnotationProcessorProfileSerializer.java | 6 +- 16 files changed, 347 insertions(+), 185 deletions(-) create mode 100644 jps/jps-builders-6/src/org/jetbrains/jps/javac/LazyInitClassLoader.java diff --git a/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java b/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java index 465b3424fc03..c45fed5c5d60 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/ProcessorProfilePanel.java @@ -56,6 +56,7 @@ public class ProcessorProfilePanel extends JPanel { private final JLabel myTestLabel; private final JPanel myProcessorTablePanel; private final JPanel myOptionsTablePanel; + private final JCheckBox myCbProcOnly; public ProcessorProfilePanel(Project project) { @@ -63,7 +64,7 @@ public class ProcessorProfilePanel extends JPanel { myProject = project; 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")); myRbProcessorsPath = new JRadioButton(JavaCompilerBundle.message("settings.processor.path")); @@ -163,6 +164,9 @@ public class ProcessorProfilePanel extends JPanel { 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)); + 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, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0)); add(myOptionsTablePanel, @@ -185,6 +189,8 @@ public class ProcessorProfilePanel extends JPanel { public void setProfile(ProcessorConfigProfile config) { myCbEnableProcessing.setSelected(config.isEnabled()); + myCbProcOnly.setSelected(config.isProcOnly()); + (config.isObtainProcessorsFromClasspath()? myRbClasspath : myRbProcessorsPath).setSelected(true); myCbProcessorModulePath.setSelected(config.isUseProcessorModulePath()); myProcessorPathField.setText(FileUtil.toSystemDependentName(config.getProcessorPath())); @@ -210,6 +216,7 @@ public class ProcessorProfilePanel extends JPanel { profile.setObtainProcessorsFromClasspath(myRbClasspath.isSelected()); profile.setProcessorPath(myProcessorPathField.getText().trim()); profile.setUseProcessorModulePath(myCbProcessorModulePath.isSelected()); + profile.setProcOnly(myCbProcOnly.isSelected()); final String productionDir = myGeneratedProductionDirField.getText().trim(); profile.setGeneratedSourcesDirectoryName(StringUtil.isEmpty(productionDir)? null : productionDir, false); @@ -263,6 +270,7 @@ public class ProcessorProfilePanel extends JPanel { myStoreGenSourcesLabel.setEnabled(enabled); myProductionLabel.setEnabled(enabled); myTestLabel.setEnabled(enabled); + myCbProcOnly.setEnabled(enabled); myProcessorTablePanel.setEnabled(enabled); myOptionsTablePanel.setEnabled(enabled); } diff --git a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties index 72e4f657f0e6..6def9ed555c1 100644 --- a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties +++ b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties @@ -146,6 +146,7 @@ settings.override.module.column=Module settings.override.compilation.options.column=Compilation options settings.additional.compilation.options=Additional compilation options will be the same for all modules 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.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) diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/AbstractRefCollectorCompilerToolExtension.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/AbstractRefCollectorCompilerToolExtension.java index dc5851203def..077506b5d7ee 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/AbstractRefCollectorCompilerToolExtension.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/AbstractRefCollectorCompilerToolExtension.java @@ -7,13 +7,12 @@ import org.jetbrains.jps.javac.ast.JavacReferenceCollector; import org.jetbrains.jps.javac.ast.api.JavacFileData; import javax.tools.JavaCompiler; -import java.util.Collection; public abstract class AbstractRefCollectorCompilerToolExtension extends JavaCompilerToolExtension { @Override public final void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool, @NotNull JavaCompiler.CompilationTask task, - @NotNull Collection options, + @NotNull Iterable options, @NotNull final DiagnosticOutputConsumer diagnosticConsumer) { if (compilingTool.isCompilerTreeAPISupported() && isEnabled()) { JavacReferenceCollector.installOn(task, new JavacReferenceCollector.Consumer() { diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/Iterators.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/Iterators.java index a12ee19c4e9b..64c6a62e05ed 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/Iterators.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/Iterators.java @@ -18,8 +18,32 @@ public class Iterators { } }; - public static boolean isEmpty(Iterable iterable) { - return iterable == null || (iterable instanceof Collection && ((Collection)iterable).isEmpty()); + public static boolean isEmpty(Iterable iterable) { + if (iterable instanceof Collection) { + return ((Collection)iterable).isEmpty(); + } + return iterable == null || !iterable.iterator().hasNext(); + } + + public static boolean contains(Iterable 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 , T> C collect(Iterable iterable, C acc) { + for (T t : iterable) { + acc.add(t); + } + return acc; } @SuppressWarnings("unchecked") diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavaCompilerToolExtension.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavaCompilerToolExtension.java index bc8d30777452..cd099fbcafbe 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavaCompilerToolExtension.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavaCompilerToolExtension.java @@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.ExtensionsSupport; import org.jetbrains.jps.builders.java.JavaCompilingTool; -import javax.tools.*; +import javax.tools.JavaCompiler; import java.util.Collection; /** @@ -29,13 +29,12 @@ public abstract class JavaCompilerToolExtension { /** * This method is called before compiler task execution. * 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 options compiler command line options for this compiler invocation - * @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 options, @NotNull DiagnosticOutputConsumer diagnosticConsumer) { + * @param options compiler command line options for this compiler invocation + * @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 Iterable options, @NotNull DiagnosticOutputConsumer diagnosticConsumer) { } private static final ExtensionsSupport ourExtSupport = new ExtensionsSupport(JavaCompilerToolExtension.class); diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java index f48bacacaf4c..94f9995a18d3 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java @@ -30,7 +30,7 @@ public final class JavacMain { "-d", "-classpath", "-cp", "--class-path", "-bootclasspath", "--boot-class-path" ))); private static final Set FILTERED_SINGLE_OPTIONS = Collections.unmodifiableSet(new HashSet(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 FILE_MANAGER_EARLY_INIT_OPTIONS = Collections.unmodifiableSet(new HashSet(Arrays.asList( "-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 boolean TRACK_AP_GENERATED_DEPENDENCIES = Boolean.parseBoolean(System.getProperty(TRACK_AP_GENERATED_DEPENDENCIES_PROPERTY, "true")); - public static boolean compile(Collection options, - final Collection sources, - Collection classpath, - Collection platformClasspath, + public static boolean compile(Iterable options, + Iterable sources, + Iterable classpath, + Iterable platformClasspath, ModulePath modulePath, - Collection upgradeModulePath, - Collection sourcePath, + Iterable upgradeModulePath, + Iterable sourcePath, final Map> outputDirToRoots, final DiagnosticOutputConsumer diagnosticConsumer, final OutputFileConsumer outputSink, @@ -70,7 +70,7 @@ public final class JavacMain { final JpsJavacFileManager fileManager = new JpsJavacFileManager( 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 // and thus usage of symbol file for resolution, when this file is not expected to be used 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 } - final Collection _options = prepareOptions(options, compilingTool); + final Iterable _options = prepareOptions(options, compilingTool); try { // 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; } - if (!platformClasspath.isEmpty()) { + if (!Iterators.isEmpty(platformClasspath)) { try { fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff 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 { 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 try { fileManager.setLocation(StandardLocation.CLASS_PATH, classpath); if (!usingJavac && - isAnnotationProcessingEnabled && - !_options.contains("-processorpath") && - (javacBefore9 || (!_options.contains("--processor-module-path") && getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null))) { + isAnnotationProcessingEnabled && !Iterators.contains(_options, "-processorpath") && + (javacBefore9 || (!Iterators.contains(_options, "--processor-module-path") && getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null))) { // for non-javac file manager ensure annotation processor path defaults to 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 { // ensure the source path is set; // 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.")); } - private static boolean isAnnotationProcessingEnabled(final Collection options) { - return !options.contains("-proc:none"); + private static boolean isAnnotationProcessingEnabled(final Iterable options) { + return !Iterators.contains(options, "-proc:none"); } - private static Collection prepareOptions(final Collection options, @NotNull JavaCompilingTool compilingTool) { + private static Iterable prepareOptions(final Iterable options, @NotNull JavaCompilingTool compilingTool) { final List result = new ArrayList(compilingTool.getDefaultCompilerOptions()); boolean skip = false; for (String option : options) { @@ -529,7 +528,7 @@ public final class JavacMain { return result; } - private static Collection buildPlatformClasspath(Collection platformClasspath, Collection options) { + private static Iterable buildPlatformClasspath(Iterable platformClasspath, Iterable options) { final Map argsMap = new HashMap(); for (Iterator iterator = options.iterator(); iterator.hasNext(); ) { final String arg = iterator.next(); @@ -547,7 +546,7 @@ public final class JavacMain { appendFiles(argsMap, PathOption.PREPEND_CP, result, false); appendFiles(argsMap, PathOption.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.EXTDIRS, result, true); appendFiles(argsMap, PathOption.D_EXTDIRS, result, true); diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacProtoUtil.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacProtoUtil.java index 68a340e8273d..8ac7382b00a0 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacProtoUtil.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacProtoUtil.java @@ -27,13 +27,13 @@ public final class JavacProtoUtil { return JavacRemoteProto.Message.Request.newBuilder().setRequestType(JavacRemoteProto.Message.Request.Type.SHUTDOWN).build(); } - public static JavacRemoteProto.Message.Request createCompilationRequest(List options, - Collection files, - Collection classpath, - Collection platformCp, + public static JavacRemoteProto.Message.Request createCompilationRequest(Iterable options, + Iterable files, + Iterable classpath, + Iterable platformCp, ModulePath modulePath, - Collection upgradeModulePath, - Collection sourcePath, + Iterable upgradeModulePath, + Iterable sourcePath, Map> outs) { final JavacRemoteProto.Message.Request.Builder builder = JavacRemoteProto.Message.Request.newBuilder(); builder.setRequestType(JavacRemoteProto.Message.Request.Type.COMPILE); diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JpsJavacFileManager.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JpsJavacFileManager.java index d7dd4f4bc622..c163873e2521 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JpsJavacFileManager.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JpsJavacFileManager.java @@ -10,15 +10,13 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.java.JavaSourceTransformer; import javax.tools.*; +import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; import java.util.*; /** @@ -72,6 +70,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager myInputSources = Collections.emptyList(); private final Map myInputSourcesIndex = new HashMap(); + private final List myCloseables = new ArrayList(); public JpsJavacFileManager(final Context context, boolean javacBefore9, Collection transformers) { super(context.getStandardFileManager()); @@ -157,7 +156,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager path = getLocation(location); - if (path == null) { - return null; - } - final List urls = new ArrayList(); - 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 - 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) { @@ -314,7 +304,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager locationRoots = getLocation(location); - if (locationRoots == null) { + if (Iterators.isEmpty(locationRoots)) { return Collections.emptyList(); } result = Iterators.flat(Iterators.map(locationRoots, new Function>() { @@ -583,6 +573,14 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager myUrls; + + LazyInitClassLoader(Iterable urls, ClassLoader parent) { + super(EMPTY_URL_ARRAY, parent); + myUrls = urls; + } + + @Nullable + static LazyInitClassLoader createFrom(@Nullable Iterable files, ClassLoader parent) { + return files == null? null : new LazyInitClassLoader(Iterators.map(files, new Function() { + @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 findResources(String name) throws IOException { + init(); + return super.findResources(name); + } + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index e2615feda069..11410227eff5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -14,7 +14,6 @@ import com.intellij.util.concurrency.Semaphore; import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FileCollectionFactory; -import com.intellij.util.containers.JBIterable; import com.intellij.util.containers.SmartHashSet; import com.intellij.util.execution.ParametersListUtil; import com.intellij.util.io.BaseOutputReader; @@ -72,9 +71,6 @@ import java.util.stream.Collectors; import static com.intellij.openapi.util.Pair.pair; -/** - * @author Eugene Zhuravlev - */ public final class JavaBuilder extends ModuleLevelBuilder { private static final Logger LOG = Logger.getInstance(JavaBuilder.class); private static final String JAVA_EXTENSION = "java"; @@ -92,17 +88,23 @@ public final class JavaBuilder extends ModuleLevelBuilder { private static final Key MODULE_PATH_SPLITTER = GlobalContextKey.create("_module_path_splitter_"); private static final List 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 FILTERED_OPTIONS = ContainerUtil.newHashSet( - "-target", "--release", "-d" + TARGET_OPTION, RELEASE_OPTION, "-d" ); private static final Set 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 POSSIBLY_CONFLICTING_OPTIONS = ContainerUtil.newHashSet( - "--boot-class-path", "-bootclasspath", - "--class-path", "-classpath", "-cp", - "-processorpath", "-sourcepath", - "--module-path", "-p", "--module-source-path" + "--boot-class-path", "-bootclasspath", "--class-path", "-classpath", "-cp", PROCESSORPATH_OPTION, "-sourcepath", "--module-path", "-p", "--module-source-path" ); private static final List ourClassProcessors = new ArrayList<>(); @@ -398,7 +400,6 @@ public final class JavaBuilder extends ModuleLevelBuilder { final JpsJavaCompilerConfiguration compilerConfig = JpsJavaExtensionService.getInstance().getCompilerConfiguration( context.getProjectDescriptor().getProject() ); - assert compilerConfig != null; if (modules.size() == 1) { profile = compilerConfig.getAnnotationProcessingProfile(modules.iterator().next()); @@ -414,43 +415,39 @@ public final class JavaBuilder extends ModuleLevelBuilder { final Map> outs = buildOutputDirectoriesMap(context, chunk); try { 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 - Pair forkSdk = null; - if (shouldForkJavac) { + final Pair forkSdk; + if (shouldForkCompilerProcess(context, chunk, targetLanguageLevel)) { forkSdk = getForkedJavacSdk(chunk, targetLanguageLevel); 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()))); return false; } } + else { + forkSdk = null; + } final int compilerSdkVersion = forkSdk == null ? JavaVersion.current().feature : forkSdk.getSecond(); - final Pair, List> vm_compilerOptions = getCompilationOptions( - compilerSdkVersion, context, chunk, profile, compilingTool - ); - final List vmOptions = vm_compilerOptions.first; - final List options = vm_compilerOptions.second; + final Pair, Iterable> vm_compilerOptions = getCompilationOptions(compilerSdkVersion, context, chunk, profile, compilingTool); + final Iterable vmOptions = vm_compilerOptions.first; + final Iterable options = vm_compilerOptions.second; - if (LOG.isDebugEnabled()) { - String mode = shouldForkJavac ? "fork" : "in-process"; - LOG.debug("Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\", mode=" + mode); - } - - Collection 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")); + Iterable effectivePlatformCp = calcEffectivePlatformCp(originalPlatformCp, options, compilingTool); + if (effectivePlatformCp == 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)); return false; } - Collection classPath = originalClassPath; - ModulePath modulePath = ModulePath.EMPTY; - Collection upgradeModulePath = Collections.emptyList(); - + final Iterable platformCp; + final Iterable classPath; + final ModulePath modulePath; + final Iterable upgradeModulePath; if (moduleInfoFile != null) { // has modules final ModulePathSplitter splitter = MODULE_PATH_SPLITTER.get(context); final Pair> pair = splitter.splitPath( @@ -473,44 +470,93 @@ public final class JavaBuilder extends ModuleLevelBuilder { classPath = pair.second; } // modules above the JDK in the order entry list make a module upgrade path - upgradeModulePath = platformCp; + upgradeModulePath = effectivePlatformCp; platformCp = Collections.emptyList(); } - - if (!platformCp.isEmpty() && (getChunkSdkVersion(chunk)) >= 9) { - // if chunk's SDK is 9 or higher, there is no way to specify full platform classpath - // because platform classes are stored in jimage binary files with unknown format. - // Because of this we are clearing platform classpath so that javac will resolve against its own boot classpath - // and prepending additional jars from the JDK configuration to compilation classpath - classPath = JBIterable.from(platformCp).append(classPath).toList(); - platformCp = Collections.emptyList(); + else { + modulePath = ModulePath.EMPTY; + upgradeModulePath = Collections.emptyList(); + if (!Iterators.isEmpty(effectivePlatformCp) && (getChunkSdkVersion(chunk)) >= 9) { + // if chunk's SDK is 9 or higher, there is no way to specify full platform classpath + // because platform classes are stored in jimage binary files with unknown format. + // Because of this we are clearing platform classpath so that javac will resolve against its own boot classpath + // 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 boolean rc; - if (!shouldForkJavac) { - updateCompilerUsageStatistics(context, compilingTool.getDescription(), chunk); - rc = JavacMain.compile( - options, files, classPath, platformCp, modulePath, upgradeModulePath, sourcePath, outs, diagnosticSink, classesConsumer, - context.getCancelStatus(), compilingTool - ); - } - else { + + if (forkSdk != null) { updateCompilerUsageStatistics(context, "javac " + forkSdk.getSecond(), chunk); final ExternalJavacManager server = ensureJavacServerStarted(context); final CompilationPaths paths = CompilationPaths.create(platformCp, classPath, upgradeModulePath, modulePath, sourcePath); - rc = server.forkJavac( - forkSdk.getFirst(), Utils.suggestForkedCompilerHeapSize(), - vmOptions, options, paths, files, outs, diagnosticSink, classesConsumer, compilingTool, context.getCancelStatus(), true - ).get(); + final int heapSize = Utils.suggestForkedCompilerHeapSize(); + return invokeJavac(compilerSdkVersion, context, chunk, compilingTool, options, files, classesConsumer, (_options, _files, _outSink) -> { + logJavacCall(chunk, _options, "fork"); + 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 { counter.waitFor(); } } + private static void logJavacCall(ModuleChunk chunk, Iterable 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 options, Iterable files, OutputFileConsumer outSink); + } + private static boolean invokeJavac( + int compilerSdkVersion, + CompileContext context, + ModuleChunk chunk, + @NotNull JavaCompilingTool compilingTool, + Iterable options, + Iterable files, + OutputFileConsumer outSink, + JavacCaller javacCall + ) { + if (Iterators.contains(options, PROC_ONLY_OPTION)) { + // make a dedicated javac call for annotation processing only + final Collection 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 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) { final ConcurrentMap> map = COMPILER_USAGE_STATISTICS.get(context); Collection names = map.get(compilerName); @@ -530,7 +576,6 @@ public final class JavaBuilder extends ModuleLevelBuilder { public static @Nls String validateCycle(CompileContext context, ModuleChunk chunk) { final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance(); final JpsJavaCompilerConfiguration compilerConfig = javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject()); - assert compilerConfig != null; final Set modules = chunk.getModules(); Pair pair = null; for (JpsModule module : modules) { @@ -564,8 +609,7 @@ public final class JavaBuilder extends ModuleLevelBuilder { else { context.processMessage(new CompilerMessage( getBuilderName(), BuildMessage.Kind.WARNING, - JpsBuildBundle.message("build.message.some.modules.with.cyclic.dependencies.0.have.additional.command.line.parameters", - chunk.getName()) + JpsBuildBundle.message("build.message.some.modules.with.cyclic.dependencies.0.have.additional.command.line.parameters", chunk.getName()) )); } } @@ -653,11 +697,9 @@ public final class JavaBuilder extends ModuleLevelBuilder { private static boolean preferTargetJdkCompiler(CompileContext context) { Boolean val = PREFER_TARGET_JDK_COMPILER.get(context); if (val == null) { - final JpsProject project = context.getProjectDescriptor().getProject(); - final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project); + JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getCompilerConfiguration(context.getProjectDescriptor().getProject()); // default - val = config != null? config.getCompilerOptions(JavaCompilers.JAVAC_ID).PREFER_TARGET_JDK_COMPILER : Boolean.TRUE; - PREFER_TARGET_JDK_COMPILER.set(context, val); + PREFER_TARGET_JDK_COMPILER.set(context, val = config.getCompilerOptions(JavaCompilers.JAVAC_ID).PREFER_TARGET_JDK_COMPILER); } 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 // this will allow javac to resolve against ct.sym file, which is required for the "compilation profiles" feature @Nullable - private static Collection calcEffectivePlatformCp(Collection platformCp, List options, JavaCompilingTool compilingTool) { + private static Iterable calcEffectivePlatformCp(Collection platformCp, Iterable options, JavaCompilingTool compilingTool) { if (ourDefaultRtJar == null || !isJavac(compilingTool)) { return platformCp; } @@ -772,7 +814,7 @@ public final class JavaBuilder extends ModuleLevelBuilder { private static final Key USER_DEFINED_BYTECODE_TARGET = Key.create("_user_defined_bytecode_target_"); - private static Pair, List> getCompilationOptions(int compilerSdkVersion, + private static Pair, Iterable> getCompilationOptions(int compilerSdkVersion, CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile, @@ -830,7 +872,7 @@ public final class JavaBuilder extends ModuleLevelBuilder { for (final String userOption : ParametersListUtil.parse(customArgs)) { if (FILTERED_OPTIONS.contains(userOption)) { skip = true; - targetOptionFound = "-target".equals(userOption); + targetOptionFound = TARGET_OPTION.equals(userOption); notifyOptionIgnored(context, userOption, chunk); continue; } @@ -864,7 +906,7 @@ public final class JavaBuilder extends ModuleLevelBuilder { vmOptions.addAll(extension.getOptions(compilingTool)); } - addCompilationOptions(compilerSdkVersion, compilationOptions, context, chunk, profile); + addCompilationOptions(compilerSdkVersion, compilationOptions, context, chunk, profile, true); return pair(vmOptions, compilationOptions); } @@ -887,14 +929,14 @@ public final class JavaBuilder extends ModuleLevelBuilder { CompileContext context, ModuleChunk chunk, @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, List options, CompileContext context, ModuleChunk chunk, - @Nullable ProcessorConfigProfile profile) { - if (!options.contains("-encoding")) { + @Nullable ProcessorConfigProfile profile, boolean procOnlySupported) { + if (!options.contains(ENCODING_OPTION)) { final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration(); final String encoding = config.getPreferredModuleChunkEncoding(chunk); 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)); } if (!StringUtil.isEmpty(encoding)) { - options.add("-encoding"); + options.add(ENCODING_OPTION); options.add(encoding); } } addCrossCompilationOptions(compilerSdkVersion, options, context, chunk); - if (!options.contains("--enable-preview")) { + if (!options.contains(ENABLE_PREVIEW_OPTION)) { LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(chunk.representativeTarget().getModule()); if (level != null && level.isPreview()) { - options.add("--enable-preview"); + options.add(ENABLE_PREVIEW_OPTION); } } if (addAnnotationProcessingOptions(options, profile)) { + assert profile != null; + + if (procOnlySupported && profile.isProcOnly()) { + options.add(PROC_ONLY_OPTION); + } + final File srcOutput = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir( chunk.getModules().iterator().next(), chunk.containsTests(), profile ); @@ -933,14 +981,14 @@ public final class JavaBuilder extends ModuleLevelBuilder { */ public static boolean addAnnotationProcessingOptions(List options, @Nullable AnnotationProcessingConfiguration profile) { if (profile == null || !profile.isEnabled()) { - options.add("-proc:none"); + options.add(PROC_NONE_OPTION); return false; } // configuring annotation processing if (!profile.isObtainProcessorsFromClasspath()) { 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())); } @@ -973,14 +1021,14 @@ public final class JavaBuilder extends ModuleLevelBuilder { int bytecodeTarget = getModuleBytecodeTarget(context, chunk, compilerConfiguration, languageLevel); if (shouldUseReleaseOption(compilerConfiguration, compilerSdkVersion, chunkSdkVersion, bytecodeTarget)) { - options.add("--release"); + options.add(RELEASE_OPTION); options.add(complianceOption(bytecodeTarget)); return; } // using older -source, -target and -bootclasspath options if (languageLevel > 0) { - options.add("-source"); + options.add(SOURCE_OPTION); options.add(complianceOption(languageLevel)); } @@ -1006,7 +1054,7 @@ public final class JavaBuilder extends ModuleLevelBuilder { } if (bytecodeTarget > 0) { - options.add("-target"); + options.add(TARGET_OPTION); options.add(complianceOption(bytecodeTarget)); } } @@ -1329,8 +1377,9 @@ public final class JavaBuilder extends ModuleLevelBuilder { content.saveToFile(file); } else { - myContext.processMessage(new CompilerMessage(getBuilderName(), BuildMessage.Kind.WARNING, - JpsBuildBundle.message("build.message.missing.content.for.file.0", file.getPath()))); + myContext.processMessage(new CompilerMessage( + getBuilderName(), BuildMessage.Kind.WARNING, JpsBuildBundle.message("build.message.missing.content.for.file.0", file.getPath())) + ); } } catch (IOException e) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationPaths.java b/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationPaths.java index be396067026a..b23572833bd4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationPaths.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/CompilationPaths.java @@ -5,48 +5,38 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.Collection; -import java.util.Collections; -/** - * @author Eugene Zhuravlev - * Date: 14-Nov-18 - */ public class CompilationPaths { - private final Collection myPlatformClasspath; - private final Collection myClasspath; - private final Collection myUpgradeModulePath; + private final Iterable myPlatformClasspath; + private final Iterable myClasspath; + private final Iterable myUpgradeModulePath; private final ModulePath myModulePath; - private final Collection mySourcePath; + private final Iterable mySourcePath; - public CompilationPaths(Collection platformClasspath, - Collection classpath, - Collection upgradeModulePath, + public CompilationPaths(Iterable platformClasspath, + Iterable classpath, + Iterable upgradeModulePath, ModulePath modulePath, - Collection sourcePath) { - myPlatformClasspath = constCollection(platformClasspath); - myClasspath = constCollection(classpath); - myUpgradeModulePath = constCollection(upgradeModulePath); + Iterable sourcePath) { + myPlatformClasspath = platformClasspath; + myClasspath = classpath; + myUpgradeModulePath = upgradeModulePath; myModulePath = modulePath; - mySourcePath = constCollection(sourcePath); - } - - private static Collection constCollection(Collection col) { - return col == null || col.isEmpty()? Collections.emptyList() : Collections.unmodifiableCollection(col); + mySourcePath = sourcePath; } @NotNull - public Collection getPlatformClasspath() { + public Iterable getPlatformClasspath() { return myPlatformClasspath; } @NotNull - public Collection getClasspath() { + public Iterable getClasspath() { return myClasspath; } @NotNull - public Collection getUpgradeModulePath() { + public Iterable getUpgradeModulePath() { return myUpgradeModulePath; } @@ -56,15 +46,15 @@ public class CompilationPaths { } @NotNull - public Collection getSourcePath() { + public Iterable getSourcePath() { return mySourcePath; } - public static CompilationPaths create(@Nullable Collection platformCp, - @Nullable Collection cp, - @Nullable Collection upgradeModCp, + public static CompilationPaths create(@Nullable Iterable platformCp, + @Nullable Iterable cp, + @Nullable Iterable upgradeModCp, @NotNull ModulePath modulePath, - @Nullable Collection sourcePath) { + @Nullable Iterable sourcePath) { return new CompilationPaths(platformCp, cp, upgradeModCp, modulePath, sourcePath); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacManager.java index a31b4ff42452..3de5bab7fbe9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacManager.java @@ -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 public boolean forkJavac(String javaHome, @@ -142,10 +142,10 @@ public class ExternalJavacManager extends ProcessAdapter { public ExternalJavacRunResult forkJavac(String javaHome, int heapSize, - List vmOptions, - List options, + Iterable vmOptions, + Iterable options, CompilationPaths paths, - Collection files, + Iterable files, Map> outs, DiagnosticOutputConsumer diagnosticSink, OutputFileConsumer outputSink, @@ -256,14 +256,20 @@ public class ExternalJavacManager extends ProcessAdapter { } } - private static int processHash(String sdkHomePath, List vmOptions, JavaCompilingTool tool) { - return Objects.hash(sdkHomePath.replace(File.separatorChar, '/'), vmOptions, tool.getId()); + private static int processHash(String sdkHomePath, Iterable vmOptions, JavaCompilingTool tool) { + Collection opts = vmOptions instanceof Collection? (Collection)vmOptions : Iterators.collect(vmOptions, new ArrayList<>()); + return Objects.hash(sdkHomePath.replace(File.separatorChar, '/'), opts, tool.getId()); } @Nullable - private static String getEncodingName(List options) { - int p = options.indexOf("-encoding"); - return p >= 0 && p < options.size() - 1 ? options.get(p + 1) : null; + private static String getEncodingName(Iterable options) { + for (Iterator it = options.iterator(); it.hasNext(); ) { + final String option = it.next(); + if ("-encoding".equals(option)) { + return it.hasNext()? it.next() : null; + } + } + return null; } public boolean isRunning() { @@ -324,7 +330,7 @@ public class ExternalJavacManager extends ProcessAdapter { int heapSize, int port, File workingDir, - List vmOptions, + Iterable vmOptions, JavaCompilingTool compilingTool, final boolean keepProcessAlive) throws Exception { final UUID processId = UUID.randomUUID(); diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java index 27ca873a5409..b848ddf4e212 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/AnnotationProcessingConfiguration.java @@ -20,9 +20,6 @@ import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.Set; -/** - * @author Eugene Zhuravlev - */ public interface AnnotationProcessingConfiguration { boolean isEnabled(); @@ -43,4 +40,6 @@ public interface AnnotationProcessingConfiguration { Map getProcessorOptions(); boolean isObtainProcessorsFromClasspath(); + + boolean isProcOnly(); } diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java index dab08d251937..2bf18abdca64 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java +++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/ProcessorConfigProfile.java @@ -42,6 +42,8 @@ public interface ProcessorConfigProfile extends AnnotationProcessingConfiguratio void setGeneratedSourcesDirectoryName(@Nullable String generatedSourcesDirectoryName, boolean forTests); + void setProcOnly(boolean value); + @NotNull Set getModuleNames(); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java index 66eb8834d85f..2e487ad7abe9 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ProcessorConfigProfileImpl.java @@ -7,9 +7,6 @@ import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile; import java.util.*; -/** - * @author Eugene Zhuravlev - */ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile { private String myName = ""; private boolean myEnabled = false; @@ -21,6 +18,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile private String myGeneratedProductionDirectoryName = DEFAULT_PRODUCTION_DIR_NAME; private String myGeneratedTestsDirectoryName = DEFAULT_TESTS_DIR_NAME; private boolean myOutputRelativeToContentRoot = false; + private boolean myIsProcOnly = false; private final Set myModuleNames = new HashSet<>(1); @@ -36,6 +34,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile public final void initFrom(ProcessorConfigProfile other) { myName = other.getName(); myEnabled = other.isEnabled(); + myIsProcOnly = other.isProcOnly(); myObtainProcessorsFromClasspath = other.isObtainProcessorsFromClasspath(); myProcessorPath = other.getProcessorPath(); myUseProcessorModulePath = other.isUseProcessorModulePath(); @@ -127,6 +126,16 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile myOutputRelativeToContentRoot = relativeToContent; } + @Override + public boolean isProcOnly() { + return myIsProcOnly; + } + + @Override + public void setProcOnly(boolean value) { + myIsProcOnly = value; + } + @Override @NotNull public Set getModuleNames() { @@ -209,6 +218,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile ProcessorConfigProfileImpl profile = (ProcessorConfigProfileImpl)o; if (myEnabled != profile.myEnabled) return false; + if (myIsProcOnly != profile.myIsProcOnly) return false; if (myObtainProcessorsFromClasspath != profile.myObtainProcessorsFromClasspath) return false; if (myGeneratedProductionDirectoryName != null ? !myGeneratedProductionDirectoryName.equals(profile.myGeneratedProductionDirectoryName) @@ -235,6 +245,7 @@ public final class ProcessorConfigProfileImpl implements ProcessorConfigProfile public int hashCode() { int result = myName.hashCode(); result = 31 * result + (myEnabled ? 1 : 0); + result = 31 * result + (myIsProcOnly ? 1 : 0); result = 31 * result + (myObtainProcessorsFromClasspath ? 1 : 0); result = 31 * result + (myProcessorPath != null ? myProcessorPath.hashCode() : 0); result = 31 * result + myProcessors.hashCode(); diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java index a69199a97ba3..c78f8c37a45d 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/AnnotationProcessorProfileSerializer.java @@ -16,6 +16,7 @@ public final class AnnotationProcessorProfileSerializer { private static final String NAME = "name"; private static final String VALUE = "value"; private static final String ENABLED = "enabled"; + private static final String PROC_ONLY = "procOnly"; private static final String OPTION = "option"; private static final String MODULE = "module"; private static final String USE_CLASSPATH = "useClasspath"; @@ -24,6 +25,7 @@ public final class AnnotationProcessorProfileSerializer { public static void readExternal(ProcessorConfigProfile profile, Element element) { profile.setName(element.getAttributeValue(NAME, "")); profile.setEnabled(Boolean.valueOf(element.getAttributeValue(ENABLED, "false"))); + profile.setProcOnly(Boolean.valueOf(element.getAttributeValue(PROC_ONLY, "false"))); final Element srcOutput = element.getChild("sourceOutputDir"); final String out = srcOutput != null ? srcOutput.getAttributeValue(NAME) : null; @@ -87,7 +89,9 @@ public final class AnnotationProcessorProfileSerializer { if (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); if (!StringUtil.equals(ProcessorConfigProfile.DEFAULT_PRODUCTION_DIR_NAME, srcDirName)) { addChild(element, "sourceOutputDir").setAttribute(NAME, FileUtil.toSystemIndependentName(srcDirName));