mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
split FSState functionality
This commit is contained in:
@@ -21,6 +21,7 @@ import org.jetbrains.jps.artifacts.Artifact;
|
||||
import org.jetbrains.jps.idea.IdeaProjectLoader;
|
||||
import org.jetbrains.jps.idea.SystemOutErrorReporter;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.messages.*;
|
||||
import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
|
||||
@@ -145,7 +146,7 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
private void runBuild(String projectPath, BuildType buildType, Set<String> modules, Collection<String> artifacts, Map<String, String> builderParams, Collection<String> paths, final MessageHandler msgHandler, CanceledStatus cs) throws Throwable{
|
||||
ProjectDescriptor pd;
|
||||
final Project project = loadProject(projectPath);
|
||||
final FSState fsState = new FSState(false);
|
||||
final BuildFSState fsState = new BuildFSState(false);
|
||||
ProjectTimestamps timestamps = null;
|
||||
BuildDataManager dataManager = null;
|
||||
final File dataStorageRoot = Utils.getDataStorageRoot(project);
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
package org.jetbrains.jps.incremental;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.CompilerExcludes;
|
||||
import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.incremental.storage.TimestampStorage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 12/16/11
|
||||
*/
|
||||
public class FSState {
|
||||
private final Map<Module, FilesDelta> myDeltas = Collections.synchronizedMap(new HashMap<Module, FilesDelta>());
|
||||
private final Set<Module> myInitialTestsScanPerformed = Collections.synchronizedSet(new HashSet<Module>());
|
||||
private final Set<Module> myInitialProductionScanPerformed = Collections.synchronizedSet(new HashSet<Module>());
|
||||
|
||||
private final Set<Module> myContextModules = new HashSet<Module>();
|
||||
private volatile FilesDelta myCurrentRoundDelta;
|
||||
private volatile FilesDelta myLastRoundDelta;
|
||||
|
||||
// when true, will always determine dirty files by scanning FS and comparing timestamps
|
||||
// alternatively, when false, after first scan will rely on extarnal notifications about changes
|
||||
private final boolean myAlwaysScanFS;
|
||||
|
||||
public FSState(boolean alwaysScanFS) {
|
||||
myAlwaysScanFS = alwaysScanFS;
|
||||
}
|
||||
|
||||
public void onRebuild() {
|
||||
clearContextRoundData();
|
||||
myInitialProductionScanPerformed.clear();
|
||||
myInitialTestsScanPerformed.clear();
|
||||
myDeltas.clear();
|
||||
}
|
||||
|
||||
public boolean markInitialScanPerformed(Module module, boolean forTests) {
|
||||
if (myAlwaysScanFS) {
|
||||
return true;
|
||||
}
|
||||
final Set<Module> map = forTests ? myInitialTestsScanPerformed : myInitialProductionScanPerformed;
|
||||
return map.add(module);
|
||||
}
|
||||
|
||||
public void setContextChunk(ModuleChunk chunk) {
|
||||
myContextModules.addAll(chunk.getModules());
|
||||
}
|
||||
|
||||
public void beforeNextRoundStart() {
|
||||
myLastRoundDelta = myCurrentRoundDelta;
|
||||
myCurrentRoundDelta = new FilesDelta();
|
||||
}
|
||||
|
||||
public void clearContextRoundData() {
|
||||
myCurrentRoundDelta = null;
|
||||
myLastRoundDelta = null;
|
||||
}
|
||||
|
||||
public void clearContextChunk() {
|
||||
myContextModules.clear();
|
||||
}
|
||||
|
||||
public void clearRecompile(RootDescriptor rd) {
|
||||
getDelta(rd.module).clearRecompile(rd.root, rd.isTestRoot);
|
||||
}
|
||||
|
||||
public void markDirty(final File file, final RootDescriptor rd, final @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final FilesDelta roundDelta = myCurrentRoundDelta;
|
||||
if (roundDelta != null) {
|
||||
if (myContextModules.contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
final FilesDelta mainDelta = getDelta(rd.module);
|
||||
final boolean marked = mainDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.markDirty(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void markDirtyIfNotDeleted(final File file, final RootDescriptor rd, final @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final FilesDelta mainDelta = getDelta(rd.module);
|
||||
final boolean marked = mainDelta.markRecompileIfNotDeleted(rd.root, rd.isTestRoot, file);
|
||||
if (marked) {
|
||||
if (tsStorage != null) {
|
||||
tsStorage.markDirty(file);
|
||||
}
|
||||
final FilesDelta roundDelta = myCurrentRoundDelta;
|
||||
if (roundDelta != null) {
|
||||
if (myContextModules.contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if marked something, false otherwise
|
||||
*/
|
||||
public boolean markAllUpToDate(CompileScope scope, final RootDescriptor rd, final TimestampStorage tsStorage, final long compilationStartStamp) throws IOException {
|
||||
boolean marked = false;
|
||||
final FilesDelta delta = getDelta(rd.module);
|
||||
final Set<File> files = delta.clearRecompile(rd.root, rd.isTestRoot);
|
||||
if (files != null) {
|
||||
final CompilerExcludes excludes = rd.module.getProject().getCompilerConfiguration().getExcludes();
|
||||
for (File file : files) {
|
||||
if (!excludes.isExcluded(file)) {
|
||||
if (scope.isAffected(rd.module, file)) {
|
||||
final long stamp = file.lastModified();
|
||||
if (!rd.isGeneratedSources && stamp > compilationStartStamp) {
|
||||
// if the file was modified after the compilation had started,
|
||||
// do not save the stamp considering file dirty
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
else {
|
||||
marked = true;
|
||||
tsStorage.saveStamp(file, stamp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tsStorage.remove(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public boolean processFilesToRecompile(CompileContext context, final Module module, final FileProcessor processor) throws IOException {
|
||||
final FilesDelta lastRoundDelta = myLastRoundDelta;
|
||||
final FilesDelta delta = lastRoundDelta != null? lastRoundDelta : getDelta(module);
|
||||
final Map<File, Set<File>> data = delta.getSourcesToRecompile(context.isCompilingTests());
|
||||
final CompilerExcludes excludes = module.getProject().getCompilerConfiguration().getExcludes();
|
||||
final CompileScope scope = context.getScope();
|
||||
synchronized (data) {
|
||||
for (Map.Entry<File, Set<File>> entry : data.entrySet()) {
|
||||
final String root = FileUtil.toSystemIndependentName(entry.getKey().getPath());
|
||||
for (File file : entry.getValue()) {
|
||||
if (!scope.isAffected(module, file)) {
|
||||
continue;
|
||||
}
|
||||
if (excludes.isExcluded(file)) {
|
||||
continue;
|
||||
}
|
||||
if (!processor.apply(module, file, root)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void registerDeleted(final Module module, final File file, final boolean isTest, @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
getDelta(module).addDeleted(file, isTest);
|
||||
if (tsStorage != null) {
|
||||
tsStorage.remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getDeletedPaths(final Module module, final boolean isTest) {
|
||||
final FilesDelta delta = myDeltas.get(module);
|
||||
if (delta == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return delta.getDeletedPaths(isTest);
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(final Module module, final boolean isTest) {
|
||||
final FilesDelta delta = myDeltas.get(module);
|
||||
if (delta != null) {
|
||||
delta.clearDeletedPaths(isTest);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private FilesDelta getDelta(Module module) {
|
||||
synchronized (myDeltas) {
|
||||
FilesDelta delta = myDeltas.get(module);
|
||||
if (delta == null) {
|
||||
delta = new FilesDelta();
|
||||
myDeltas.put(module, delta);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
||||
/** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/
|
||||
private static final class FilesDelta {
|
||||
private final Set<String> myDeletedProduction = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Set<String> myDeletedTests = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Map<File, Set<File>> mySourcesToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
private final Map<File, Set<File>> myTestsToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
|
||||
public boolean markRecompile(File root, boolean isTestRoot, File file) {
|
||||
final boolean added = _addToRecompiled(root, isTestRoot, file);
|
||||
if (added) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
if (!deleted.isEmpty()) { // optimization
|
||||
deleted.remove(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean markRecompileIfNotDeleted(File root, boolean isTestRoot, File file) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
final boolean isMarkedDeleted;
|
||||
synchronized (deleted) {
|
||||
isMarkedDeleted = !deleted.isEmpty() && deleted.contains(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
if (!isMarkedDeleted) {
|
||||
return _addToRecompiled(root, isTestRoot, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean _addToRecompiled(File root, boolean isTestRoot, File file) {
|
||||
final Map<File, Set<File>> toRecompile = isTestRoot ? myTestsToRecompile : mySourcesToRecompile;
|
||||
Set<File> files;
|
||||
synchronized (toRecompile) {
|
||||
files = toRecompile.get(root);
|
||||
if (files == null) {
|
||||
files = new HashSet<File>();
|
||||
toRecompile.put(root, files);
|
||||
}
|
||||
}
|
||||
return files.add(file);
|
||||
}
|
||||
|
||||
public void addDeleted(File file, boolean isTest) {
|
||||
// ensure the file is no more marked to recompilation
|
||||
final Map<File, Set<File>> toRecompile = isTest ? myTestsToRecompile : mySourcesToRecompile;
|
||||
synchronized (toRecompile) {
|
||||
for (Set<File> files : toRecompile.values()) {
|
||||
files.remove(file);
|
||||
}
|
||||
}
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
deleted.add(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
deleted.clear();
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(boolean forTests) {
|
||||
return forTests? myTestsToRecompile : mySourcesToRecompile;
|
||||
}
|
||||
|
||||
public Set<String> getDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest ? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
return deleted.isEmpty()? Collections.<String>emptySet() : new HashSet<String>(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<File> clearRecompile(File root, boolean isTestRoot) {
|
||||
return isTestRoot? myTestsToRecompile.remove(root) : mySourcesToRecompile.remove(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,7 +255,7 @@ public class IncProjectBuilder {
|
||||
catch (IOException e) {
|
||||
throw new ProjectBuildException("Error cleaning compiler storages", e);
|
||||
}
|
||||
myProjectDescriptor.fsState.onRebuild();
|
||||
myProjectDescriptor.fsState.clearAll();
|
||||
|
||||
final Collection<Module> modulesToClean = context.getProject().getModules().values();
|
||||
final Set<File> rootsToDelete = new HashSet<File>();
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.incremental.RootDescriptor;
|
||||
import org.jetbrains.jps.incremental.storage.TimestampStorage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 12/16/11
|
||||
*/
|
||||
public class BuildFSState extends FSState {
|
||||
private final Set<Module> myInitialTestsScanPerformed = Collections.synchronizedSet(new HashSet<Module>());
|
||||
private final Set<Module> myInitialProductionScanPerformed = Collections.synchronizedSet(new HashSet<Module>());
|
||||
|
||||
private final Set<Module> myContextModules = new HashSet<Module>();
|
||||
private volatile FilesDelta myCurrentRoundDelta;
|
||||
private volatile FilesDelta myLastRoundDelta;
|
||||
|
||||
// when true, will always determine dirty files by scanning FS and comparing timestamps
|
||||
// alternatively, when false, after first scan will rely on extarnal notifications about changes
|
||||
private final boolean myAlwaysScanFS;
|
||||
|
||||
public BuildFSState(boolean alwaysScanFS) {
|
||||
myAlwaysScanFS = alwaysScanFS;
|
||||
}
|
||||
|
||||
public boolean markInitialScanPerformed(Module module, boolean forTests) {
|
||||
if (myAlwaysScanFS) {
|
||||
return true;
|
||||
}
|
||||
final Set<Module> map = forTests ? myInitialTestsScanPerformed : myInitialProductionScanPerformed;
|
||||
return map.add(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<File, Set<File>> getSourcesToRecompile(Module module, boolean forTests) {
|
||||
final FilesDelta lastRoundDelta = myLastRoundDelta;
|
||||
if (lastRoundDelta != null) {
|
||||
return lastRoundDelta.getSourcesToRecompile(forTests);
|
||||
}
|
||||
return super.getSourcesToRecompile(module, forTests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markDirty(File file, RootDescriptor rd, @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final FilesDelta roundDelta = myCurrentRoundDelta;
|
||||
if (roundDelta != null) {
|
||||
if (myContextModules.contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
return super.markDirty(file, rd, tsStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markDirtyIfNotDeleted(File file, RootDescriptor rd, @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final boolean marked = super.markDirtyIfNotDeleted(file, rd, tsStorage);
|
||||
if (marked) {
|
||||
final FilesDelta roundDelta = myCurrentRoundDelta;
|
||||
if (roundDelta != null) {
|
||||
if (myContextModules.contains(rd.module)) {
|
||||
roundDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
clearContextRoundData();
|
||||
clearContextChunk();
|
||||
myInitialProductionScanPerformed.clear();
|
||||
myInitialTestsScanPerformed.clear();
|
||||
super.clearAll();
|
||||
}
|
||||
|
||||
public void clearContextRoundData() {
|
||||
myCurrentRoundDelta = null;
|
||||
myLastRoundDelta = null;
|
||||
}
|
||||
|
||||
public void clearContextChunk() {
|
||||
myContextModules.clear();
|
||||
}
|
||||
|
||||
public void setContextChunk(ModuleChunk chunk) {
|
||||
myContextModules.addAll(chunk.getModules());
|
||||
}
|
||||
|
||||
public void beforeNextRoundStart() {
|
||||
myLastRoundDelta = myCurrentRoundDelta;
|
||||
myCurrentRoundDelta = new FilesDelta();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.CompilerExcludes;
|
||||
import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.CompileScope;
|
||||
import org.jetbrains.jps.incremental.FileProcessor;
|
||||
import org.jetbrains.jps.incremental.RootDescriptor;
|
||||
import org.jetbrains.jps.incremental.storage.TimestampStorage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 4/20/12
|
||||
*/
|
||||
public class FSState {
|
||||
private final Map<Module, FilesDelta> myDeltas = Collections.synchronizedMap(new HashMap<Module, FilesDelta>());
|
||||
|
||||
public final void clearRecompile(RootDescriptor rd) {
|
||||
getDelta(rd.module).clearRecompile(rd.root, rd.isTestRoot);
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
myDeltas.clear();
|
||||
}
|
||||
|
||||
public boolean markDirty(final File file, final RootDescriptor rd, final @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final FilesDelta mainDelta = getDelta(rd.module);
|
||||
final boolean marked = mainDelta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.markDirty(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public boolean markDirtyIfNotDeleted(final File file, final RootDescriptor rd, final @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
final FilesDelta mainDelta = getDelta(rd.module);
|
||||
final boolean marked = mainDelta.markRecompileIfNotDeleted(rd.root, rd.isTestRoot, file);
|
||||
if (marked && tsStorage != null) {
|
||||
tsStorage.markDirty(file);
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if marked something, false otherwise
|
||||
*/
|
||||
public boolean markAllUpToDate(CompileScope scope, final RootDescriptor rd, final TimestampStorage tsStorage, final long compilationStartStamp) throws IOException {
|
||||
boolean marked = false;
|
||||
final FilesDelta delta = getDelta(rd.module);
|
||||
final Set<File> files = delta.clearRecompile(rd.root, rd.isTestRoot);
|
||||
if (files != null) {
|
||||
final CompilerExcludes excludes = rd.module.getProject().getCompilerConfiguration().getExcludes();
|
||||
for (File file : files) {
|
||||
if (!excludes.isExcluded(file)) {
|
||||
if (scope.isAffected(rd.module, file)) {
|
||||
final long stamp = file.lastModified();
|
||||
if (!rd.isGeneratedSources && stamp > compilationStartStamp) {
|
||||
// if the file was modified after the compilation had started,
|
||||
// do not save the stamp considering file dirty
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
else {
|
||||
marked = true;
|
||||
tsStorage.saveStamp(file, stamp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delta.markRecompile(rd.root, rd.isTestRoot, file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tsStorage.remove(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return marked;
|
||||
}
|
||||
|
||||
public boolean processFilesToRecompile(CompileContext context, final Module module, final FileProcessor processor) throws IOException {
|
||||
final Map<File, Set<File>> data = getSourcesToRecompile(module, context.isCompilingTests());
|
||||
final CompilerExcludes excludes = module.getProject().getCompilerConfiguration().getExcludes();
|
||||
final CompileScope scope = context.getScope();
|
||||
synchronized (data) {
|
||||
for (Map.Entry<File, Set<File>> entry : data.entrySet()) {
|
||||
final String root = FileUtil.toSystemIndependentName(entry.getKey().getPath());
|
||||
for (File file : entry.getValue()) {
|
||||
if (!scope.isAffected(module, file)) {
|
||||
continue;
|
||||
}
|
||||
if (excludes.isExcluded(file)) {
|
||||
continue;
|
||||
}
|
||||
if (!processor.apply(module, file, root)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void registerDeleted(final Module module, final File file, final boolean isTest, @Nullable TimestampStorage tsStorage) throws IOException {
|
||||
getDelta(module).addDeleted(file, isTest);
|
||||
if (tsStorage != null) {
|
||||
tsStorage.remove(file);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(Module module, boolean forTests) {
|
||||
return getDelta(module).getSourcesToRecompile(forTests);
|
||||
}
|
||||
|
||||
public Collection<String> getDeletedPaths(final Module module, final boolean isTest) {
|
||||
final FilesDelta delta = myDeltas.get(module);
|
||||
if (delta == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return delta.getDeletedPaths(isTest);
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(final Module module, final boolean isTest) {
|
||||
final FilesDelta delta = myDeltas.get(module);
|
||||
if (delta != null) {
|
||||
delta.clearDeletedPaths(isTest);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected final FilesDelta getDelta(Module module) {
|
||||
synchronized (myDeltas) {
|
||||
FilesDelta delta = myDeltas.get(module);
|
||||
if (delta == null) {
|
||||
delta = new FilesDelta();
|
||||
myDeltas.put(module, delta);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.jetbrains.jps.incremental.fs;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/
|
||||
final class FilesDelta {
|
||||
private final Set<String> myDeletedProduction = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Set<String> myDeletedTests = Collections.synchronizedSet(new HashSet<String>());
|
||||
private final Map<File, Set<File>> mySourcesToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
private final Map<File, Set<File>> myTestsToRecompile = Collections.synchronizedMap(new HashMap<File, Set<File>>()); // srcRoot -> set of sources
|
||||
|
||||
public boolean markRecompile(File root, boolean isTestRoot, File file) {
|
||||
final boolean added = _addToRecompiled(root, isTestRoot, file);
|
||||
if (added) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
if (!deleted.isEmpty()) { // optimization
|
||||
deleted.remove(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean markRecompileIfNotDeleted(File root, boolean isTestRoot, File file) {
|
||||
final Set<String> deleted = isTestRoot? myDeletedTests : myDeletedProduction;
|
||||
final boolean isMarkedDeleted;
|
||||
synchronized (deleted) {
|
||||
isMarkedDeleted = !deleted.isEmpty() && deleted.contains(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
if (!isMarkedDeleted) {
|
||||
return _addToRecompiled(root, isTestRoot, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean _addToRecompiled(File root, boolean isTestRoot, File file) {
|
||||
final Map<File, Set<File>> toRecompile = isTestRoot ? myTestsToRecompile : mySourcesToRecompile;
|
||||
Set<File> files;
|
||||
synchronized (toRecompile) {
|
||||
files = toRecompile.get(root);
|
||||
if (files == null) {
|
||||
files = new HashSet<File>();
|
||||
toRecompile.put(root, files);
|
||||
}
|
||||
}
|
||||
return files.add(file);
|
||||
}
|
||||
|
||||
public void addDeleted(File file, boolean isTest) {
|
||||
// ensure the file is no more marked to recompilation
|
||||
final Map<File, Set<File>> toRecompile = isTest ? myTestsToRecompile : mySourcesToRecompile;
|
||||
synchronized (toRecompile) {
|
||||
for (Set<File> files : toRecompile.values()) {
|
||||
files.remove(file);
|
||||
}
|
||||
}
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
deleted.add(FileUtil.toCanonicalPath(file.getPath()));
|
||||
}
|
||||
|
||||
public void clearDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest? myDeletedTests : myDeletedProduction;
|
||||
deleted.clear();
|
||||
}
|
||||
|
||||
public Map<File, Set<File>> getSourcesToRecompile(boolean forTests) {
|
||||
return forTests? myTestsToRecompile : mySourcesToRecompile;
|
||||
}
|
||||
|
||||
public Set<String> getDeletedPaths(boolean isTest) {
|
||||
final Set<String> deleted = isTest ? myDeletedTests : myDeletedProduction;
|
||||
synchronized (deleted) {
|
||||
return deleted.isEmpty()? Collections.<String>emptySet() : new HashSet<String>(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<File> clearRecompile(File root, boolean isTestRoot) {
|
||||
return isTestRoot? myTestsToRecompile.remove(root) : mySourcesToRecompile.remove(root);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.Project;
|
||||
import org.jetbrains.jps.Sdk;
|
||||
import org.jetbrains.jps.incremental.BuildLoggingManager;
|
||||
import org.jetbrains.jps.incremental.FSState;
|
||||
import org.jetbrains.jps.incremental.ModuleRootsIndex;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Set;
|
||||
*/
|
||||
public final class ProjectDescriptor {
|
||||
public final Project project;
|
||||
public final FSState fsState;
|
||||
public final BuildFSState fsState;
|
||||
public final ProjectTimestamps timestamps;
|
||||
public final BuildDataManager dataManager;
|
||||
private final BuildLoggingManager myLoggingManager;
|
||||
@@ -29,7 +29,7 @@ public final class ProjectDescriptor {
|
||||
private Set<JavaSdk> myProjectJavaSdks;
|
||||
|
||||
public ProjectDescriptor(Project project,
|
||||
FSState fsState,
|
||||
BuildFSState fsState,
|
||||
ProjectTimestamps timestamps,
|
||||
BuildDataManager dataManager,
|
||||
BuildLoggingManager loggingManager) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.jps.artifacts.Artifact;
|
||||
import org.jetbrains.jps.idea.IdeaProjectLoader;
|
||||
import org.jetbrains.jps.idea.SystemOutErrorReporter;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
@@ -134,7 +135,7 @@ class ServerState {
|
||||
pd = myProjects.get(projectPath);
|
||||
if (pd == null) {
|
||||
final Project project = loadProject(projectPath);
|
||||
final FSState fsState = new FSState(false);
|
||||
final BuildFSState fsState = new BuildFSState(false);
|
||||
ProjectTimestamps timestamps = null;
|
||||
BuildDataManager dataManager = null;
|
||||
final File dataStorageRoot = Utils.getDataStorageRoot(project);
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.jps.artifacts.Artifact;
|
||||
import org.jetbrains.jps.idea.IdeaProjectLoader;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLoggerImpl;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilderLogger;
|
||||
import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
|
||||
@@ -204,7 +205,7 @@ public abstract class IncrementalTestCase extends TestCase {
|
||||
final File dataStorageRoot = Utils.getDataStorageRoot(project);
|
||||
final TestJavaBuilderLogger javaBuilderLogger = new TestJavaBuilderLogger(FileUtil.toSystemIndependentName(getWorkDir() + File.separator));
|
||||
final ProjectDescriptor projectDescriptor =
|
||||
new ProjectDescriptor(project, new FSState(true), new ProjectTimestamps(dataStorageRoot),
|
||||
new ProjectDescriptor(project, new BuildFSState(true), new ProjectTimestamps(dataStorageRoot),
|
||||
new BuildDataManager(dataStorageRoot, true), new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), javaBuilderLogger));
|
||||
try {
|
||||
new IncProjectBuilder(
|
||||
|
||||
+2
-1
@@ -26,6 +26,7 @@ import org.jetbrains.jps.*;
|
||||
import org.jetbrains.jps.api.CanceledStatus;
|
||||
import org.jetbrains.jps.artifacts.Artifact;
|
||||
import org.jetbrains.jps.incremental.*;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
@@ -162,7 +163,7 @@ public abstract class ArtifactBuilderTestCase extends UsefulTestCase {
|
||||
final File dataStorageRoot = Utils.getDataStorageRoot(myProject);
|
||||
ProjectTimestamps timestamps = new ProjectTimestamps(dataStorageRoot);
|
||||
BuildDataManager dataManager = new BuildDataManager(dataStorageRoot, true);
|
||||
return new ProjectDescriptor(myProject, new FSState(true), timestamps, dataManager, new BuildLoggingManager(myArtifactBuilderLogger,
|
||||
return new ProjectDescriptor(myProject, new BuildFSState(true), timestamps, dataManager, new BuildLoggingManager(myArtifactBuilderLogger,
|
||||
new JavaBuilderLoggerImpl()));
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
||||
Reference in New Issue
Block a user