module-level builders output conflict detection

GitOrigin-RevId: 73f6c80539735dfb1d912dd47e3dfeffc6d68f00
This commit is contained in:
Eugene Zhuravlev
2022-02-09 08:32:54 +00:00
committed by intellij-monorepo-bot
parent 57b499abad
commit 5cf035c24d
3 changed files with 28 additions and 4 deletions
@@ -26,6 +26,7 @@ progress.message.dependency.analysis.found.0.affected.files=Dependency analysis
progress.message.finished.saving.caches=Finished, saving caches\u2026
progress.message.running.after.tasks=Running 'after' tasks
progress.message.running.before.tasks=Running 'before' tasks
build.message.conflicting.outputs.error=Output file "{0}" has already been registered by "{1}"
#java
build.message.0.was.used.to.compile.1={0} was used to compile [{1}]
@@ -1,28 +1,38 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.jps.incremental;
import com.intellij.openapi.util.io.FileUtil;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.JpsBuildBundle;
import org.jetbrains.jps.builders.impl.BuildOutputConsumerImpl;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene Zhuravlev
*/
final class ChunkBuildOutputConsumerImpl implements ModuleLevelBuilder.OutputConsumer {
private final CompileContext myContext;
private final Map<BuildTarget<?>, BuildOutputConsumerImpl> myTarget2Consumer = new HashMap<>();
private final Map<String, CompiledClass> myClasses = new HashMap<>();
private final Map<BuildTarget<?>, Collection<CompiledClass>> myTargetToClassesMap = new HashMap<>();
private final Int2ObjectMap<String> myOutputToBuilderNameMap = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
private volatile String myCurrentBuilderName;
ChunkBuildOutputConsumerImpl(CompileContext context) {
myContext = context;
}
public void setCurrentBuilderName(String builderName) {
myCurrentBuilderName = builderName;
}
@Override
public Collection<CompiledClass> getTargetCompiledClasses(@NotNull BuildTarget<?> target) {
final Collection<CompiledClass> classes = myTargetToClassesMap.get(target);
@@ -65,6 +75,16 @@ final class ChunkBuildOutputConsumerImpl implements ModuleLevelBuilder.OutputCon
@Override
public void registerOutputFile(@NotNull BuildTarget<?> target, File outputFile, Collection<String> sourcePaths) throws IOException {
final String currentBuilder = myCurrentBuilderName;
if (currentBuilder != null) {
final String previousBuilder = myOutputToBuilderNameMap.put(FileUtil.fileHashCode(outputFile), currentBuilder);
if (previousBuilder != null && !previousBuilder.equals(currentBuilder)) {
final String source = sourcePaths.isEmpty()? null : sourcePaths.iterator().next();
myContext.processMessage(new CompilerMessage(
currentBuilder, BuildMessage.Kind.ERROR, JpsBuildBundle.message("build.message.conflicting.outputs.error", outputFile.getAbsolutePath(), previousBuilder), source
));
}
}
BuildOutputConsumerImpl consumer = myTarget2Consumer.get(target);
if (consumer == null) {
consumer = new BuildOutputConsumerImpl(target, myContext);
@@ -91,5 +111,6 @@ final class ChunkBuildOutputConsumerImpl implements ModuleLevelBuilder.OutputCon
myTarget2Consumer.clear();
myClasses.clear();
myTargetToClassesMap.clear();
myOutputToBuilderNameMap.clear();
}
}
@@ -1509,6 +1509,7 @@ public final class IncProjectBuilder {
try {
for (ModuleLevelBuilder builder : builders) {
outputConsumer.setCurrentBuilderName(builder.getPresentableName());
processDeletedPaths(context, chunk.getTargets());
long start = System.nanoTime();
int processedSourcesBefore = outputConsumer.getNumberOfProcessedSources();
@@ -1556,6 +1557,7 @@ public final class IncProjectBuilder {
}
}
finally {
outputConsumer.setCurrentBuilderName(null);
final boolean moreToCompile = JavaBuilderUtil.updateMappingsOnRoundCompletion(context, dirtyFilesHolder, chunk);
if (moreToCompile) {
nextPassRequired = true;