diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java b/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java index 404fb9ec87c0..d24f5105992f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/DirtyFilesHolder.java @@ -3,10 +3,16 @@ package org.jetbrains.jps.builders; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.util.Collection; /** * @author nik */ public interface DirtyFilesHolder> { void processDirtyFiles(@NotNull FileProcessor processor) throws IOException; + + boolean hasRemovedFiles(); + + @NotNull + Collection getRemovedFiles(@NotNull T target); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java new file mode 100644 index 000000000000..80e2fe0abef9 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/DirtyFilesHolderBase.java @@ -0,0 +1,42 @@ +package org.jetbrains.jps.builders.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.BuildRootDescriptor; +import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.DirtyFilesHolder; +import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.Utils; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +/** + * @author nik + */ +public abstract class DirtyFilesHolderBase> implements DirtyFilesHolder { + protected final CompileContext myContext; + + public DirtyFilesHolderBase(CompileContext context) { + myContext = context; + } + + @Override + public boolean hasRemovedFiles() { + Map, Collection> map = Utils.REMOVED_SOURCES_KEY.get(myContext); + return map != null && !map.isEmpty(); + } + + @NotNull + @Override + public Collection getRemovedFiles(@NotNull T target) { + Map, Collection> map = Utils.REMOVED_SOURCES_KEY.get(myContext); + if (map != null) { + Collection paths = map.get(target); + if (paths != null) { + return paths; + } + } + return Collections.emptyList(); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java index 5aed50c100fe..9fc1bb0dcddb 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderUtil.java @@ -7,7 +7,7 @@ import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashSet; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; -import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.incremental.CompileContext; @@ -31,24 +31,29 @@ public class JavaBuilderUtil { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder"); /** + * * @param context * @param delta + * @param dirtyFilesHolder * @param chunk * @param filesToCompile files compiled in this round * @param successfullyCompiled * @return true if additional compilation pass is required, false otherwise * @throws Exception */ - public static boolean updateMappings(CompileContext context, final Mappings delta, ModuleChunk chunk, - Collection filesToCompile, - Collection successfullyCompiled) throws IOException { + public static boolean updateMappings(CompileContext context, + final Mappings delta, + DirtyFilesHolder dirtyFilesHolder, + ModuleChunk chunk, + Collection filesToCompile, + Collection successfullyCompiled) throws IOException { if (Utils.errorsDetected(context)) { return false; } try { boolean additionalPassRequired = false; - final Set removedPaths = getRemovedPaths(context, chunk); + final Set removedPaths = getRemovedPaths(chunk, dirtyFilesHolder); final Mappings globalMappings = context.getProjectDescriptor().dataManager.getMappings(); @@ -204,17 +209,13 @@ public class JavaBuilderUtil { return allCompiledFiles; } - private static Set getRemovedPaths(CompileContext context, ModuleChunk chunk) { - final Map, Collection> map = Utils.REMOVED_SOURCES_KEY.get(context); - if (map == null) { + private static Set getRemovedPaths(ModuleChunk chunk, DirtyFilesHolder dirtyFilesHolder) { + if (!dirtyFilesHolder.hasRemovedFiles()) { return Collections.emptySet(); } final Set removed = new THashSet(FileUtil.PATH_HASHING_STRATEGY); for (ModuleBuildTarget target : chunk.getTargets()) { - final Collection modulePaths = map.get(target); - if (modulePaths != null) { - removed.addAll(modulePaths); - } + removed.addAll(dirtyFilesHolder.getRemovedFiles(target)); } return removed; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java index ad4c134ccc57..f04b3a93dc48 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuildOperations.java @@ -5,6 +5,7 @@ import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.impl.BuildTargetChunk; +import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase; import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.fs.BuildFSState; @@ -83,7 +84,7 @@ public class BuildOperations { void buildTarget(final T target, final CompileContext context, TargetBuilder builder) throws ProjectBuildException, IOException { if (builder.getTargetTypes().contains(target.getTargetType())) { - DirtyFilesHolder holder = new DirtyFilesHolder() { + DirtyFilesHolder holder = new DirtyFilesHolderBase(context) { @Override public void processDirtyFiles(@NotNull FileProcessor processor) throws IOException { context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 17a75a7357fe..9b10c58e6270 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -20,6 +20,7 @@ import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.impl.BuildTargetChunk; +import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase; import org.jetbrains.jps.builders.java.JavaBuilderUtil; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; @@ -730,7 +731,7 @@ public class IncProjectBuilder { myProjectDescriptor.fsState.beforeNextRoundStart(context, chunk); DirtyFilesHolder dirtyFilesHolder = - new DirtyFilesHolder() { + new DirtyFilesHolderBase(context) { @Override public void processDirtyFiles(@NotNull FileProcessor processor) throws IOException { 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 665f63f10794..a92b537c13ad 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 @@ -32,7 +32,6 @@ import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.api.GlobalOptions; import org.jetbrains.jps.api.RequestFuture; import org.jetbrains.jps.builders.BuildRootIndex; -import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.FileProcessor; import org.jetbrains.jps.builders.java.JavaBuilderUtil; @@ -173,11 +172,6 @@ public class JavaBuilder extends ModuleLevelBuilder { //add here class processors in the sequence they should be executed } - private static boolean hasRemovedSources(CompileContext context) { - final Map, Collection> removed = Utils.REMOVED_SOURCES_KEY.get(context); - return removed != null && !removed.isEmpty(); - } - @NotNull public String getPresentableName() { return BUILDER_NAME; @@ -260,7 +254,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - return compile(context, chunk, filesToCompile, formsToCompile); + return compile(context, chunk, dirtyFilesHolder, filesToCompile, formsToCompile); } catch (ProjectBuildException e) { throw e; @@ -302,13 +296,17 @@ public class JavaBuilder extends ModuleLevelBuilder { } } - private ExitCode compile(final CompileContext context, ModuleChunk chunk, Collection files, Collection forms) + private ExitCode compile(final CompileContext context, + ModuleChunk chunk, + DirtyFilesHolder dirtyFilesHolder, + Collection files, + Collection forms) throws Exception { ExitCode exitCode = ExitCode.NOTHING_DONE; final boolean hasSourcesToCompile = !files.isEmpty() || !forms.isEmpty(); - if (!hasSourcesToCompile && !hasRemovedSources(context)) { + if (!hasSourcesToCompile && !dirtyFilesHolder.hasRemovedFiles()) { return exitCode; } @@ -427,7 +425,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final Set successfullyCompiled = outputSink.getSuccessfullyCompiled(); DELTA_MAPPINGS_CALLBACK_KEY.set(context, null); - if (JavaBuilderUtil.updateMappings(context, delta, chunk, files, successfullyCompiled)) { + if (JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, files, successfullyCompiled)) { exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED; } } diff --git a/platform/util/src/com/intellij/util/containers/BidirectionalMultiMap.java b/platform/util/src/com/intellij/util/containers/BidirectionalMultiMap.java index ead4ca64c0db..1405fb1ed232 100644 --- a/platform/util/src/com/intellij/util/containers/BidirectionalMultiMap.java +++ b/platform/util/src/com/intellij/util/containers/BidirectionalMultiMap.java @@ -16,8 +16,9 @@ package com.intellij.util.containers; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.Map; import java.util.Set; @@ -29,16 +30,24 @@ public class BidirectionalMultiMap { private final Map> myValue2Keys; public BidirectionalMultiMap() { - myKey2Values = new HashMap>(); - myValue2Keys = new HashMap>(); + this(new HashMap>(), new HashMap>()); } - public @Nullable Set getValues(K key) { - return myKey2Values.get(key); + public BidirectionalMultiMap(final Map> key2Values, final Map> value2Keys) { + myKey2Values = key2Values; + myValue2Keys = value2Keys; } - public @Nullable Set getKeys(V value) { - return myValue2Keys.get(value); + @NotNull + public Set getValues(K key) { + Set set = myKey2Values.get(key); + return set != null ? set : Collections.emptySet(); + } + + @NotNull + public Set getKeys(V value) { + Set set = myValue2Keys.get(value); + return set != null ? set : Collections.emptySet(); } public boolean containsKey(K key) { diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 9e50d594a0b7..5e3fdce1e4b1 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -115,7 +115,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { context.processMessage(message); } - if (!myForStubs && updateDependencies(context, chunk, toCompile, generationOutputs, compiled)) { + if (!myForStubs && updateDependencies(context, chunk, dirtyFilesHolder, toCompile, generationOutputs, compiled)) { return ExitCode.ADDITIONAL_PASS_REQUIRED; } return ExitCode.OK; @@ -315,6 +315,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { private static boolean updateDependencies(CompileContext context, ModuleChunk chunk, + DirtyFilesHolder dirtyFilesHolder, List toCompile, Map generationOutputs, List successfullyCompiled) throws IOException { @@ -343,7 +344,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { } - return JavaBuilderUtil.updateMappings(context, delta, chunk, toCompile, successfullyCompiledFiles); + return JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, toCompile, successfullyCompiledFiles); } private static Collection generateClasspath(CompileContext context, ModuleChunk chunk) {