package org.jetbrains.jps.incremental; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.util.containers.SLRUCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.Module; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.Project; import org.jetbrains.jps.incremental.messages.BuildMessage; import org.jetbrains.jps.incremental.storage.BuildDataManager; import java.io.File; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * @author Eugene Zhuravlev * Date: 9/17/11 */ public class CompileContext extends UserDataHolderBase implements MessageHandler{ private final CompileScope myScope; private final boolean myIsMake; private final MessageHandler myDelegateMessageHandler; private volatile boolean myCompilingTests = false; private final BuildDataManager myDataManager; private SLRUCache<Module, FSSnapshot> myFilesCache = new SLRUCache<Module, FSSnapshot>(10, 10) { @NotNull public FSSnapshot createValue(Module key) { return buildSnapshot(key); } }; public CompileContext(CompileScope scope, String projectName, boolean isMake, MessageHandler delegateMessageHandler) { myScope = scope; myIsMake = isMake; myDelegateMessageHandler = delegateMessageHandler; final File buildDataRoot = new File(System.getProperty("user.home"), ".jps" + File.separator + projectName + File.separator + "build_data"); myDataManager = new BuildDataManager(buildDataRoot); } public Project getProject() { return myScope.getProject(); } public boolean isMake() { return myIsMake; } public boolean isCompilingTests() { return myCompilingTests; } public void setCompilingTests(boolean compilingTests) { myCompilingTests = compilingTests; clearFileCache(); } public void clearFileCache() { myFilesCache.clear(); } public CompileScope getScope() { return myScope; } public BuildDataManager getBuildDataManager() { return myDataManager; } public void processMessage(BuildMessage msg) { myDelegateMessageHandler.processMessage(msg); } public void processFiles(ModuleChunk chunk, FileProcessor processor) throws Exception { for (Module module : chunk.getModules()) { final FSSnapshot snapshot = myFilesCache.get(module); if (!snapshot.processFiles(processor)) { return; } } } /** @noinspection unchecked*/ //private boolean processModule(Module module, FileProcessor processor) throws Exception { // final Set<File> excludes = new HashSet<File>(); // for (String excludePath : (Collection<String>)module.getExcludes()) { // excludes.add(new File(excludePath)); // } // // final Collection<String> roots = myCompilingTests? (Collection<String>)module.getTestRoots() : (Collection<String>)module.getSourceRoots(); // for (String root : roots) { // final File rootFile = new File(root); // if (!processRootRecursively(module, rootFile, root, processor, excludes)) { // return false; // } // } // return true; //} private FSSnapshot buildSnapshot(Module module) { final Set<File> excludes = new HashSet<File>(); for (String excludePath : (Collection<String>)module.getExcludes()) { excludes.add(new File(excludePath)); } final FSSnapshot snapshot = new FSSnapshot(module); final Collection<String> roots = myCompilingTests? (Collection<String>)module.getTestRoots() : (Collection<String>)module.getSourceRoots(); for (String srcRoot : roots) { final FSSnapshot.Root root = snapshot.addRoot(new File(srcRoot), srcRoot); buildStructure(root.getNode(), excludes); } return snapshot; } //private static boolean processRootRecursively(final Module module, final File fromFile, final String sourceRoot, FileProcessor processor, final Set<File> excluded) throws Exception { // if (fromFile.isDirectory()) { // if (isExcluded(excluded, fromFile)) { // return true; // } // final File[] children = fromFile.listFiles(); // if (children != null) { // for (File child : children) { // final boolean shouldContinue = processRootRecursively(module, child, sourceRoot, processor, excluded); // if (!shouldContinue) { // return false; // } // } // } // return true; // } // return processor.apply(module, fromFile, sourceRoot); //} private static void buildStructure(final FSSnapshot.Node from, final Set<File> excluded) { final File nodeFile = from.getFile(); if (nodeFile.isDirectory()) { if (isExcluded(excluded, nodeFile)) { return; } final File[] children = nodeFile.listFiles(); if (children != null) { for (File child : children) { buildStructure(from.addChild(child), excluded); } } } } private static boolean isExcluded(final Set<File> excludedRoots, File file) { while (file != null) { if (excludedRoots.contains(file)) { return true; } file = file.getParentFile(); } return false; } }