Integration of changes after switching to non-incremental mode may cause incorrect state of build storages (IDEA-154405 )

This commit is contained in:
Eugene Zhuravlev
2016-04-20 13:52:51 +02:00
parent 45aca913f2
commit 97353e5f34
10 changed files with 112 additions and 20 deletions
@@ -0,0 +1,24 @@
Cleaning output files:
out/production/IntegrateOnNonIncrementalMake/A.class
out/production/IntegrateOnNonIncrementalMake/B.class
out/production/IntegrateOnNonIncrementalMake/C.class
out/production/IntegrateOnNonIncrementalMake/D.class
End of files
Compiling files:
src/A.java
src/B.java
End of files
Cleaning output files:
out/production/IntegrateOnNonIncrementalMake/A.class
out/production/IntegrateOnNonIncrementalMake/B.class
out/production/IntegrateOnNonIncrementalMake/Bar.class
out/production/IntegrateOnNonIncrementalMake/C.class
out/production/IntegrateOnNonIncrementalMake/D.class
out/production/IntegrateOnNonIncrementalMake/Foo.class
End of files
Compiling files:
src/A.java
src/B.java
src/Bar.java
src/Foo.java
End of files
@@ -0,0 +1,9 @@
public class A {
public final Foo foo = new Foo();
public final int a = 1;
}
class C {
public final Foo foo = new Foo();
public final int a = 1;
}
@@ -0,0 +1,5 @@
public class A {
}
class C {
}
@@ -0,0 +1,9 @@
public class B {
public final int a = 1;
public final Bar bar = new Bar();
}
class D {
public final int a = 1;
public final Bar bar = new Bar();
}
@@ -0,0 +1,7 @@
public class B {
public final Foo bar = null;
}
class D {
public final Foo bar = null;
}
@@ -150,6 +150,7 @@ public class JavaBuilderUtil {
Collection<File> successfullyCompiled,
@Nullable FileFilter skipMarkingDirtyFilter) throws IOException {
try {
boolean performIntegrate = true;
boolean additionalPassRequired = false;
final Set<String> removedPaths = getRemovedPaths(chunk, dirtyFilesHolder);
@@ -226,11 +227,22 @@ public class JavaBuilderUtil {
}
}
else {
// non-incremental mode
final String messageText = "Marking " + chunk.getPresentableShortName() + " and direct dependants for recompilation";
LOG.info("Non-incremental mode: " + messageText);
context.processMessage(new ProgressMessage(messageText));
additionalPassRequired = isCompileJavaIncrementally(context);
final boolean alreadyMarkedDirty = FSOperations.isMarkedDirty(context, chunk);
additionalPassRequired = isCompileJavaIncrementally(context) && !alreadyMarkedDirty;
if (alreadyMarkedDirty) {
// need this to make sure changes data stored in Delta is complete
globalMappings.differentiateOnNonIncrementalMake(delta, removedPaths, filesToCompile);
}
else {
performIntegrate = false;
}
FileFilter toBeMarkedFilter = skipMarkingDirtyFilter == null ? null : new NegationFileFilter(skipMarkingDirtyFilter);
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, toBeMarkedFilter);
}
@@ -255,9 +267,10 @@ public class JavaBuilderUtil {
return false;
}
context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getPresentableShortName() + "]"));
globalMappings.integrate(delta);
if (performIntegrate) {
context.processMessage(new ProgressMessage("Updating dependency information... [" + chunk.getPresentableShortName() + "]"));
globalMappings.integrate(delta);
}
return additionalPassRequired;
}
@@ -39,7 +39,6 @@ import org.jetbrains.jps.model.module.JpsModule;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -165,6 +164,17 @@ public class FSOperations {
}
}
if (JavaBuilderUtil.isCompileJavaIncrementally(context)) {
// mark as non-incremental only the module that triggered non-incremental change
for (ModuleBuildTarget target : targets) {
if (!isMarkedDirty(context, target)) {
// if the target was marked dirty already, all its files were compiled, so
// it makes no sense to mark it non-incremental
context.markNonIncremental(target);
}
}
}
removeTargetsAlreadyMarkedDirty(context, dirtyTargets);
final Timestamps timestamps = context.getProjectDescriptor().timestamps.getStorage();
@@ -172,12 +182,6 @@ public class FSOperations {
markDirtyFiles(context, target, round, timestamps, true, null, filter);
}
if (JavaBuilderUtil.isCompileJavaIncrementally(context)) {
// mark as non-incremental only the module that triggered non-incremental change
for (ModuleBuildTarget target : targets) {
context.markNonIncremental(target);
}
}
}
private static Set<JpsModule> getDependentModulesRecursively(final JpsModule module, final JpsJavaClasspathKind kind) {
@@ -287,22 +291,36 @@ public class FSOperations {
}
}
public static boolean isMarkedDirty(CompileContext context, ModuleChunk chunk) {
synchronized (TARGETS_COMPLETELY_MARKED_DIRTY) {
Set<BuildTarget<?>> marked = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
return marked != null && marked.containsAll(chunk.getTargets());
}
}
public static boolean isMarkedDirty(CompileContext context, BuildTarget<?> target) {
synchronized (TARGETS_COMPLETELY_MARKED_DIRTY) {
Set<BuildTarget<?>> marked = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
return marked != null && marked.contains(target);
}
}
private static void addCompletelyMarkedDirtyTarget(CompileContext context, BuildTarget<?> target) {
synchronized (TARGETS_COMPLETELY_MARKED_DIRTY) {
Set<BuildTarget<?>> targetsCompletelyMarkedDirty = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
if (targetsCompletelyMarkedDirty == null) {
targetsCompletelyMarkedDirty = Collections.synchronizedSet(new HashSet<BuildTarget<?>>());
TARGETS_COMPLETELY_MARKED_DIRTY.set(context, targetsCompletelyMarkedDirty);
Set<BuildTarget<?>> marked = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
if (marked == null) {
marked = new HashSet<BuildTarget<?>>();
TARGETS_COMPLETELY_MARKED_DIRTY.set(context, marked);
}
targetsCompletelyMarkedDirty.add(target);
marked.add(target);
}
}
private static void removeTargetsAlreadyMarkedDirty(CompileContext context, Set<ModuleBuildTarget> targetsSetToFilter) {
synchronized (TARGETS_COMPLETELY_MARKED_DIRTY) {
Set<BuildTarget<?>> targetsCompletelyMarkedDirty = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
if (targetsCompletelyMarkedDirty != null) {
targetsSetToFilter.removeAll(targetsCompletelyMarkedDirty);
Set<BuildTarget<?>> marked = TARGETS_COMPLETELY_MARKED_DIRTY.get(context);
if (marked != null) {
targetsSetToFilter.removeAll(marked);
}
}
}
@@ -157,5 +157,8 @@ public class CommonTest extends IncrementalTestCase {
public void testMoveClassToAnotherRoot() throws Exception {
doTest();
}
public void testIntegrateOnNonIncrementalMake() throws Exception {
doTest();
}
}