out-of-process build: temp roots management

This commit is contained in:
Eugene Zhuravlev
2012-05-30 14:51:58 +02:00
parent 9bed8ccc3b
commit 0fe430f834
8 changed files with 76 additions and 45 deletions
@@ -416,6 +416,15 @@ public class IncProjectBuilder {
throw new ProjectBuildException(e);
}
finally {
final Collection<RootDescriptor> tempRoots = context.getRootsIndex().clearTempRoots();
if (!tempRoots.isEmpty()) {
final Set<File> rootFiles = new HashSet<File>();
for (RootDescriptor rd : tempRoots) {
rootFiles.add(rd.root);
context.getProjectDescriptor().fsState.clearRecompile(rd);
}
FileUtil.asyncDelete(rootFiles);
}
try {
// restore deleted paths that were not procesesd by 'integrate'
@@ -41,13 +41,13 @@ public class ModuleRootsIndex {
}
for (String r : module.getSourceRoots()) {
final File root = new File(FileUtil.toCanonicalPath(r));
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, false, generatedRoots.contains(r));
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, false, generatedRoots.contains(r), false);
myRootToModuleMap.put(root, descriptor);
moduleRoots.add(descriptor);
}
for (String r : module.getTestRoots()) {
final File root = new File(FileUtil.toCanonicalPath(r));
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, true, generatedRoots.contains(r));
final RootDescriptor descriptor = new RootDescriptor(moduleName, root, true, generatedRoots.contains(r), false);
myRootToModuleMap.put(root, descriptor);
moduleRoots.add(descriptor);
}
@@ -79,7 +79,7 @@ public class ModuleRootsIndex {
}
@NotNull
public RootDescriptor associateRoot(File root, Module module, boolean isTestRoot, final boolean isForGeneratedSources) {
public RootDescriptor associateRoot(File root, Module module, boolean isTestRoot, final boolean isForGeneratedSources, final boolean isTemp) {
final RootDescriptor d = myRootToModuleMap.get(root);
if (d != null) {
return d;
@@ -89,12 +89,29 @@ public class ModuleRootsIndex {
moduleRoots = new ArrayList<RootDescriptor>();
myModuleToRootsMap.put(module, moduleRoots);
}
final RootDescriptor descriptor = new RootDescriptor(module.getName(), root, isTestRoot, isForGeneratedSources);
final RootDescriptor descriptor = new RootDescriptor(module.getName(), root, isTestRoot, isForGeneratedSources, isTemp);
myRootToModuleMap.put(root, descriptor);
moduleRoots.add(descriptor);
return descriptor;
}
@NotNull
public Collection<RootDescriptor> clearTempRoots() {
final Set<RootDescriptor> toRemove = new HashSet<RootDescriptor>();
for (Iterator<Map.Entry<File, RootDescriptor>> iterator = myRootToModuleMap.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<File, RootDescriptor> entry = iterator.next();
final RootDescriptor rd = entry.getValue();
if (rd.isTemp) {
toRemove.add(rd);
iterator.remove();
}
}
for (Map.Entry<Module, List<RootDescriptor>> entry : myModuleToRootsMap.entrySet()) {
entry.getValue().removeAll(toRemove);
}
return toRemove;
}
@Nullable
public RootDescriptor getModuleAndRoot(File file) {
File current = file;
@@ -15,12 +15,14 @@ public final class RootDescriptor {
public final File root;
public final boolean isTestRoot;
public final boolean isGeneratedSources;
public final boolean isTemp;
public RootDescriptor(@NotNull final String moduleName, @NotNull File root, boolean isTestRoot, boolean isGenerated) {
public RootDescriptor(@NotNull final String moduleName, @NotNull File root, boolean isTestRoot, boolean isGenerated, boolean isTemp) {
this.module = moduleName;
this.root = root;
this.isTestRoot = isTestRoot;
this.isGeneratedSources = isGenerated;
this.isTemp = isTemp;
}
@Override
@@ -89,26 +89,32 @@ public class JavaBuilder extends ModuleLevelBuilder {
//add here class processors in the sequence they should be executed
myClassProcessors.add(new ClassPostProcessor() {
public void process(CompileContext context, OutputFileObject out) {
final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(context);
if (callback != null) {
final OutputFileObject.Content content = out.getContent();
final File srcFile = out.getSourceFile();
if (srcFile != null && content != null) {
final String outputPath = FileUtil.toSystemIndependentName(out.getFile().getPath());
final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(srcFile);
final BuildDataManager dataManager = context.getDataManager();
if (moduleAndRoot != null) {
final OutputFileObject.Content content = out.getContent();
final File srcFile = out.getSourceFile();
if (srcFile != null && content != null) {
final String outputPath = FileUtil.toSystemIndependentName(out.getFile().getPath());
final String sourcePath = FileUtil.toSystemIndependentName(srcFile.getPath());
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(srcFile);
final BuildDataManager dataManager = context.getDataManager();
boolean isTemp = false;
if (moduleAndRoot != null) {
isTemp = moduleAndRoot.isTemp;
if (!isTemp) {
try {
final String moduleName = moduleAndRoot.module;
dataManager.getSourceToOutputMap(moduleName, context.isCompilingTests()).appendData(sourcePath, outputPath);
dataManager.getSourceToOutputMap(moduleAndRoot.module, context.isCompilingTests()).appendData(sourcePath, outputPath);
}
catch (Exception e) {
context.processMessage(new CompilerMessage(BUILDER_NAME, e));
}
}
final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
callback.associate(outputPath, sourcePath, reader);
}
out.setTemp(isTemp);
if (!isTemp) {
final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(context);
if (callback != null) {
final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
callback.associate(outputPath, sourcePath, reader);
}
}
}
}
@@ -124,17 +130,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
return "Java Builder";
}
private static final Key<Set<File>> TEMPORARY_SOURCE_ROOTS_KEY = Key.create("_additional_source_roots_");
public static void addTempSourcePathRoot(CompileContext context, File root) {
Set<File> roots = TEMPORARY_SOURCE_ROOTS_KEY.get(context);
if (roots == null) {
roots = new HashSet<File>();
TEMPORARY_SOURCE_ROOTS_KEY.set(context, roots);
}
roots.add(root);
}
public ExitCode build(final CompileContext context, final ModuleChunk chunk) throws ProjectBuildException {
try {
final Set<File> filesToCompile = new HashSet<File>();
@@ -282,7 +277,15 @@ public class JavaBuilder extends ModuleLevelBuilder {
try {
if (hasSourcesToCompile) {
exitCode = ExitCode.OK;
final Set<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.<File>emptySet());
final Set<File> tempRootsSourcePath = new HashSet<File>();
final ModuleRootsIndex index = context.getRootsIndex();
for (Module module : chunk.getModules()) {
for (RootDescriptor rd : index.getModuleRoots(module)) {
if (rd.isTemp) {
tempRootsSourcePath.add(rd.root);
}
}
}
final String chunkName = getChunkPresentableName(chunk);
context.processMessage(new ProgressMessage("Compiling java [" + chunkName + "]"));
@@ -291,7 +294,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
boolean compiledOk = true;
if (filesCount > 0) {
LOG.info("Compiling " + filesCount + " java files; module: " + chunkName);
compiledOk = compileJava(chunk, files, classpath, platformCp, sourcePath, outs, context, diagnosticSink, outputSink);
compiledOk = compileJava(chunk, files, classpath, platformCp, tempRootsSourcePath, outs, context, diagnosticSink, outputSink);
}
context.checkCanceled();
@@ -362,13 +365,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
}
}
if (exitCode != ExitCode.ADDITIONAL_PASS_REQUIRED) {
final Set<File> tempRoots = TEMPORARY_SOURCE_ROOTS_KEY.get(context);
TEMPORARY_SOURCE_ROOTS_KEY.set(context, null);
if (tempRoots != null && tempRoots.size() > 0) {
FileUtil.asyncDelete(tempRoots);
}
}
return exitCode;
}
@@ -19,7 +19,7 @@ import java.util.*;
*/
class OutputFilesSink implements OutputFileConsumer {
private final CompileContext myContext;
private final Set<File> mySuccessfullyCompiled = new HashSet<File>();
private final Set<File> mySuccessfullyCompiled = new LinkedHashSet<File>();
private final Set<File> myProblematic = new HashSet<File>();
private final List<OutputFileObject> myFileObjects = new ArrayList<OutputFileObject>();
private final Map<String, OutputFileObject> myCompiledClasses = new HashMap<String, OutputFileObject>();
@@ -113,7 +113,7 @@ class OutputFilesSink implements OutputFileConsumer {
}
final File source = fileObject.getSourceFile();
if (source != null && !myProblematic.contains(source)) {
if (!fileObject.isTemp() && source != null && !myProblematic.contains(source)) {
mySuccessfullyCompiled.add(source);
final String className = fileObject.getClassName();
if (className != null) {
@@ -25,6 +25,7 @@ public final class OutputFileObject extends SimpleJavaFileObject {
@Nullable private final URI mySourceUri;
private volatile Content myContent;
private final File mySourceFile;
public boolean myIsTemp = false;
public OutputFileObject(@NotNull JavacFileManager.Context context, @Nullable File outputRoot, String relativePath, @NotNull File file, @NotNull Kind kind, @Nullable String className, @Nullable final URI sourceUri) {
this(context, outputRoot, relativePath, file, kind, className, sourceUri, null);
@@ -42,6 +43,14 @@ public final class OutputFileObject extends SimpleJavaFileObject {
mySourceFile = srcUri != null? Utils.convertToFile(srcUri) : null;
}
public boolean isTemp() {
return myIsTemp;
}
public void setTemp(boolean isTemp) {
myIsTemp = isTemp;
}
@Nullable
public File getOutputRoot() {
return myOutputRoot;
@@ -14,7 +14,6 @@ import org.jetbrains.groovy.compiler.rt.GroovyCompilerWrapper;
import org.jetbrains.jps.*;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.fs.RootDescriptor;
import org.jetbrains.jps.incremental.java.JavaBuilder;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.FileGeneratedEvent;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
@@ -100,8 +99,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
if (myForStubs) {
for (Module module : generationOutputs.keySet()) {
File root = new File(generationOutputs.get(module));
context.getRootsIndex().associateRoot(root, module, context.isCompilingTests(), true);
JavaBuilder.addTempSourcePathRoot(context, root);
context.getRootsIndex().associateRoot(root, module, context.isCompilingTests(), true, true);
}
}
@@ -640,7 +640,7 @@ public class Main {
CompileServerManager.instance.shutdownServer()
}
public void "_test make stub-level error and correct it"() {
public void "test make stub-level error and correct it"() {
def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo { }')
myFixture.addFileToProject('Bar.java', 'class Bar extends Foo {}')