external build: added api to get removed sources files, recompiled GWT modules if some files are removed

This commit is contained in:
nik
2012-11-02 13:20:12 +04:00
parent a4916e476d
commit f966483f58
8 changed files with 92 additions and 33 deletions
@@ -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<R extends BuildRootDescriptor, T extends BuildTarget<R>> {
void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException;
boolean hasRemovedFiles();
@NotNull
Collection<String> getRemovedFiles(@NotNull T target);
}
@@ -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<R extends BuildRootDescriptor, T extends BuildTarget<R>> implements DirtyFilesHolder<R, T> {
protected final CompileContext myContext;
public DirtyFilesHolderBase(CompileContext context) {
myContext = context;
}
@Override
public boolean hasRemovedFiles() {
Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(myContext);
return map != null && !map.isEmpty();
}
@NotNull
@Override
public Collection<String> getRemovedFiles(@NotNull T target) {
Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(myContext);
if (map != null) {
Collection<String> paths = map.get(target);
if (paths != null) {
return paths;
}
}
return Collections.emptyList();
}
}
@@ -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<File> filesToCompile,
Collection<File> successfullyCompiled) throws IOException {
public static boolean updateMappings(CompileContext context,
final Mappings delta,
DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
ModuleChunk chunk,
Collection<File> filesToCompile,
Collection<File> successfullyCompiled) throws IOException {
if (Utils.errorsDetected(context)) {
return false;
}
try {
boolean additionalPassRequired = false;
final Set<String> removedPaths = getRemovedPaths(context, chunk);
final Set<String> removedPaths = getRemovedPaths(chunk, dirtyFilesHolder);
final Mappings globalMappings = context.getProjectDescriptor().dataManager.getMappings();
@@ -204,17 +209,13 @@ public class JavaBuilderUtil {
return allCompiledFiles;
}
private static Set<String> getRemovedPaths(CompileContext context, ModuleChunk chunk) {
final Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(context);
if (map == null) {
private static Set<String> getRemovedPaths(ModuleChunk chunk, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder) {
if (!dirtyFilesHolder.hasRemovedFiles()) {
return Collections.emptySet();
}
final Set<String> removed = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
for (ModuleBuildTarget target : chunk.getTargets()) {
final Collection<String> modulePaths = map.get(target);
if (modulePaths != null) {
removed.addAll(modulePaths);
}
removed.addAll(dirtyFilesHolder.getRemovedFiles(target));
}
return removed;
}
@@ -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<R, T> holder = new DirtyFilesHolder<R, T>() {
DirtyFilesHolder<R, T> holder = new DirtyFilesHolderBase<R, T>(context) {
@Override
public void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException {
context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor);
@@ -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<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder =
new DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>() {
new DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) {
@Override
public void processDirtyFiles(@NotNull FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget> processor)
throws IOException {
@@ -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<BuildTarget<?>, Collection<String>> 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<File> files, Collection<File> forms)
private ExitCode compile(final CompileContext context,
ModuleChunk chunk,
DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
Collection<File> files,
Collection<File> 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<File> 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;
}
}
@@ -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<K, V> {
private final Map<V, Set<K>> myValue2Keys;
public BidirectionalMultiMap() {
myKey2Values = new HashMap<K, Set<V>>();
myValue2Keys = new HashMap<V, Set<K>>();
this(new HashMap<K, Set<V>>(), new HashMap<V, Set<K>>());
}
public @Nullable Set<V> getValues(K key) {
return myKey2Values.get(key);
public BidirectionalMultiMap(final Map<K, Set<V>> key2Values, final Map<V, Set<K>> value2Keys) {
myKey2Values = key2Values;
myValue2Keys = value2Keys;
}
public @Nullable Set<K> getKeys(V value) {
return myValue2Keys.get(value);
@NotNull
public Set<V> getValues(K key) {
Set<V> set = myKey2Values.get(key);
return set != null ? set : Collections.<V>emptySet();
}
@NotNull
public Set<K> getKeys(V value) {
Set<K> set = myValue2Keys.get(value);
return set != null ? set : Collections.<K>emptySet();
}
public boolean containsKey(K key) {
@@ -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<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
List<File> toCompile,
Map<ModuleBuildTarget, String> generationOutputs,
List<GroovycOSProcessHandler.OutputItem> 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<String> generateClasspath(CompileContext context, ModuleChunk chunk) {