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 f6254cdf50cb..33b6a9e071f5 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 @@ -52,9 +52,60 @@ import java.util.*; public class JavaBuilderUtil { private static final Key> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_"); private static final Key> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_"); + private static final Key> FILES_TO_COMPILE_KEY = Key.create("_files_to_compile_"); + private static final Key> SUCCESSFULLY_COMPILED_FILES_KEY = Key.create("_successfully_compiled_files_"); + private static final Key> MAPPINGS_DELTA_KEY = Key.create("_mappings_delta_"); public static final Key CONSTANT_SEARCH_SERVICE = Key.create("_constant_search_service_"); private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder"); + public static void registerFileToCompile(CompileContext context, File file) { + registerFilesToCompile(context, Collections.singleton(file)); + } + + public static void registerFilesToCompile(CompileContext context, Collection files) { + getFilesContainer(context, FILES_TO_COMPILE_KEY).addAll(files); + } + + public static void registerSuccessfullyCompiled(CompileContext context, File file) { + registerSuccessfullyCompiled(context, Collections.singleton(file)); + } + + public static void registerSuccessfullyCompiled(CompileContext context, Collection files) { + getFilesContainer(context, SUCCESSFULLY_COMPILED_FILES_KEY).addAll(files); + } + + @NotNull + public static Callbacks.Backend getDependenciesRegistrar(CompileContext context) { + Pair pair = MAPPINGS_DELTA_KEY.get(context); + if (pair == null) { + final Mappings delta = context.getProjectDescriptor().dataManager.getMappings().createDelta(); + pair = Pair.create(delta, delta.getCallback()); + MAPPINGS_DELTA_KEY.set(context, pair); + } + return pair.second; + } + + public static boolean updateMappingsOnRoundCompletion( + CompileContext context, DirtyFilesHolder dirtyFilesHolder, ModuleChunk chunk) throws IOException { + + Mappings delta = null; + + final Pair pair = MAPPINGS_DELTA_KEY.get(context); + if (pair != null) { + MAPPINGS_DELTA_KEY.set(context, null); + delta = pair.getFirst(); + } + + if (delta == null) { + return false; + } + final Set compiledFiles = getFilesContainer(context, FILES_TO_COMPILE_KEY); + FILES_TO_COMPILE_KEY.set(context, null); + final Set successfullyCompiled = getFilesContainer(context, SUCCESSFULLY_COMPILED_FILES_KEY); + SUCCESSFULLY_COMPILED_FILES_KEY.set(context, null); + return updateMappings(context, delta, dirtyFilesHolder, chunk, compiledFiles, successfullyCompiled); + } + /** * * @param context @@ -83,8 +134,8 @@ public class JavaBuilderUtil { if (!isForcedRecompilationAllJavaModules(context)) { if (context.shouldDifferentiate(chunk)) { context.processMessage(new ProgressMessage("Checking dependencies... [" + chunk.getPresentableShortName() + "]")); - final Set allCompiledFiles = getAllCompiledFilesContainer(context); - final Set allAffectedFiles = getAllAffectedFilesContainer(context); + final Set allCompiledFiles = getFilesContainer(context, ALL_COMPILED_FILES_KEY); + final Set allAffectedFiles = getFilesContainer(context, ALL_AFFECTED_FILES_KEY); // mark as affected all files that were dirty before compilation allAffectedFiles.addAll(filesToCompile); @@ -232,22 +283,14 @@ public class JavaBuilderUtil { return false; } - private static Set getAllAffectedFilesContainer(CompileContext context) { - Set allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context); - if (allAffectedFiles == null) { - allAffectedFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY); - ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles); + @NotNull + private static Set getFilesContainer(CompileContext context, final Key> dataKey) { + Set files = dataKey.get(context); + if (files == null) { + files = new THashSet(FileUtil.FILE_HASHING_STRATEGY); + dataKey.set(context, files); } - return allAffectedFiles; - } - - private static Set getAllCompiledFilesContainer(CompileContext context) { - Set allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context); - if (allCompiledFiles == null) { - allCompiledFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY); - ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles); - } - return allCompiledFiles; + return files; } private static Set getRemovedPaths(ModuleChunk chunk, DirtyFilesHolder dirtyFilesHolder) { 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 97f64858b535..df235ad31ec1 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -1135,55 +1135,63 @@ public class IncProjectBuilder { continue; } - for (ModuleLevelBuilder builder : builders) { - processDeletedPaths(context, chunk.getTargets()); - long start = System.nanoTime(); - final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk, dirtyFilesHolder, outputConsumer); - incBuilderElapsedTime(builder, System.nanoTime() - start); - - doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE); - - if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) { - throw new StopBuildException("Builder " + builder.getPresentableName() + " requested build stop"); - } - context.checkCanceled(); - if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) { - if (!nextPassRequired) { - // recalculate basis - myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount; - stageCount += myTotalModuleLevelBuilderCount; - myTargetsProcessed += (buildersPassed * modulesInChunk) / stageCount; + try { + for (ModuleLevelBuilder builder : builders) { + processDeletedPaths(context, chunk.getTargets()); + long start = System.nanoTime(); + final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk, dirtyFilesHolder, outputConsumer); + incBuilderElapsedTime(builder, System.nanoTime() - start); + + doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE); + + if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) { + throw new StopBuildException("Builder " + builder.getPresentableName() + " requested build stop"); } + context.checkCanceled(); + if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) { + nextPassRequired = true; + } + else if (buildResult == ModuleLevelBuilder.ExitCode.CHUNK_REBUILD_REQUIRED) { + if (!rebuildFromScratchRequested && !JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)) { + LOG.info("Builder " + builder.getPresentableName() + " requested rebuild of module chunk " + chunk.getName()); + // allow rebuild from scratch only once per chunk + rebuildFromScratchRequested = true; + try { + // forcibly mark all files in the chunk dirty + context.getProjectDescriptor().fsState.clearContextRoundData(context); + FSOperations.markDirty(context, CompilationRound.NEXT, chunk, null); + // reverting to the beginning + myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount; + stageCount = myTotalModuleLevelBuilderCount; + buildersPassed = 0; + nextPassRequired = true; + outputConsumer.clear(); + break BUILDER_CATEGORY_LOOP; + } + catch (Exception e) { + throw new ProjectBuildException(e); + } + } + else { + LOG.debug("Builder " + builder.getPresentableName() + " requested second chunk rebuild"); + } + } + + buildersPassed++; + updateDoneFraction(context, modulesInChunk / (stageCount)); + } + } + finally { + final boolean moreToCompile = JavaBuilderUtil.updateMappingsOnRoundCompletion(context, dirtyFilesHolder, chunk); + if (moreToCompile) { nextPassRequired = true; } - else if (buildResult == ModuleLevelBuilder.ExitCode.CHUNK_REBUILD_REQUIRED) { - if (!rebuildFromScratchRequested && !JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)) { - LOG.info("Builder " + builder.getPresentableName() + " requested rebuild of module chunk " + chunk.getName()); - // allow rebuild from scratch only once per chunk - rebuildFromScratchRequested = true; - try { - // forcibly mark all files in the chunk dirty - context.getProjectDescriptor().fsState.clearContextRoundData(context); - FSOperations.markDirty(context, CompilationRound.NEXT, chunk, null); - // reverting to the beginning - myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount; - stageCount = myTotalModuleLevelBuilderCount; - buildersPassed = 0; - nextPassRequired = true; - outputConsumer.clear(); - break BUILDER_CATEGORY_LOOP; - } - catch (Exception e) { - throw new ProjectBuildException(e); - } - } - else { - LOG.debug("Builder " + builder.getPresentableName() + " requested second chunk rebuild"); - } + if (nextPassRequired && !rebuildFromScratchRequested) { + // recalculate basis + myTargetsProcessed -= (buildersPassed * modulesInChunk) / stageCount; + stageCount += myTotalModuleLevelBuilderCount; + myTargetsProcessed += (buildersPassed * modulesInChunk) / stageCount; } - - buildersPassed++; - updateDoneFraction(context, modulesInChunk / (stageCount)); } } } 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 409adcdfe05d..afcbe30bafac 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 @@ -39,8 +39,6 @@ import org.jetbrains.jps.builders.java.JavaBuilderExtension; import org.jetbrains.jps.builders.java.JavaBuilderUtil; import org.jetbrains.jps.builders.java.JavaCompilingTool; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; -import org.jetbrains.jps.builders.java.dependencyView.Callbacks; -import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.builders.logging.ProjectBuilderLogger; import org.jetbrains.jps.builders.storage.BuildDataCorruptedException; import org.jetbrains.jps.cmdline.ProjectDescriptor; @@ -252,9 +250,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final Collection platformCp = ProjectPaths.getPlatformCompilationClasspath(chunk, false/*context.isProjectRebuild()*/); // begin compilation round - final Mappings delta = pd.dataManager.getMappings().createDelta(); - final Callbacks.Backend mappingsCallback = delta.getCallback(); - final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getPresentableShortName()); + final OutputFilesSink outputSink = new OutputFilesSink(context, outputConsumer, JavaBuilderUtil.getDependenciesRegistrar(context), chunk.getPresentableShortName()); try { if (hasSourcesToCompile) { final AtomicReference ref = COMPILER_VERSION_INFO.get(context); @@ -323,9 +319,8 @@ public class JavaBuilder extends ModuleLevelBuilder { } } finally { - if (JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, files, outputSink.getSuccessfullyCompiled())) { - exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED; - } + JavaBuilderUtil.registerFilesToCompile(context, files); + JavaBuilderUtil.registerSuccessfullyCompiled(context, outputSink.getSuccessfullyCompiled()); } return exitCode; diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GreclipseBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GreclipseBuilder.java index 8dd5a78f0366..9be2af6d36be 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GreclipseBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GreclipseBuilder.java @@ -147,9 +147,7 @@ public class GreclipseBuilder extends ModuleLevelBuilder { context.processMessage(new CompilerMessage(getPresentableName(), BuildMessage.Kind.ERROR, "Compilation failed")); } - if (GroovyBuilder.updateDependencies(context, chunk, dirtyFilesHolder, toCompile, successfullyCompiled, outputConsumer, this)) { - return ExitCode.ADDITIONAL_PASS_REQUIRED; - } + GroovyBuilder.updateDependencies(context, toCompile, successfullyCompiled, outputConsumer, this); return ExitCode.OK; } 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 4d858953ed26..74f33582bed9 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 @@ -40,7 +40,6 @@ import org.jetbrains.jps.builders.FileProcessor; import org.jetbrains.jps.builders.java.JavaBuilderUtil; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; -import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.cmdline.ProjectDescriptor; @@ -162,8 +161,8 @@ public class GroovyBuilder extends ModuleLevelBuilder { context.processMessage(message); } - if (!myForStubs && updateDependencies(context, chunk, dirtyFilesHolder, toCompile, compiled, outputConsumer, this)) { - return ExitCode.ADDITIONAL_PASS_REQUIRED; + if (!myForStubs) { + updateDependencies(context, toCompile, compiled, outputConsumer, this); } return hasFilesToCompileForNextRound(context) ? ExitCode.ADDITIONAL_PASS_REQUIRED : ExitCode.OK; } @@ -443,17 +442,14 @@ public class GroovyBuilder extends ModuleLevelBuilder { return toCompile; } - public static boolean updateDependencies(CompileContext context, - ModuleChunk chunk, - DirtyFilesHolder dirtyFilesHolder, - List toCompile, - Map> successfullyCompiled, - OutputConsumer outputConsumer, Builder builder) throws IOException { - final Mappings delta = context.getProjectDescriptor().dataManager.getMappings().createDelta(); - final List successfullyCompiledFiles = new ArrayList(); + public static void updateDependencies(CompileContext context, + List toCompile, + Map> successfullyCompiled, + OutputConsumer outputConsumer, Builder builder) throws IOException { + JavaBuilderUtil.registerFilesToCompile(context, toCompile); if (!successfullyCompiled.isEmpty()) { - final Callbacks.Backend callback = delta.getCallback(); + final Callbacks.Backend callback = JavaBuilderUtil.getDependenciesRegistrar(context); for (Map.Entry> entry : successfullyCompiled.entrySet()) { final ModuleBuildTarget target = entry.getKey(); @@ -479,12 +475,10 @@ public class GroovyBuilder extends ModuleLevelBuilder { builder.getPresentableName(), BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath) ); } - successfullyCompiledFiles.add(srcFile); + JavaBuilderUtil.registerSuccessfullyCompiled(context, srcFile); } } } - - return JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, toCompile, successfullyCompiledFiles); } private static String readClassName(byte[] classBytes) throws IOException{