compare file paths taking in account filesystem's case sensitivity (IDEA-91199 External compiler doesn't recompile class if only case of some letters in name was changed)

This commit is contained in:
Eugene Zhuravlev
2012-09-08 13:50:35 +02:00
parent ae4d8f717b
commit 8a95d0d373
5 changed files with 60 additions and 44 deletions
@@ -1,11 +1,15 @@
package org.jetbrains.jps.builders.java.dependencyView;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.PersistentStringEnumerator;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
@@ -21,8 +25,9 @@ class DependencyContext {
private final Map<TypeRepr.AbstractType, TypeRepr.AbstractType> myTypeMap = new HashMap<TypeRepr.AbstractType, TypeRepr.AbstractType>();
private final Map<UsageRepr.Usage, UsageRepr.Usage> myUsageMap = new HashMap<UsageRepr.Usage, UsageRepr.Usage>();
private final int myEmptyName;
UsageRepr.Usage getUsage(final UsageRepr.Usage u) {
UsageRepr.Usage getUsage(final UsageRepr.Usage u) {
final UsageRepr.Usage r = myUsageMap.get(u);
if (r == null) {
@@ -58,10 +63,11 @@ class DependencyContext {
DependencyContext(final File rootDir) throws IOException {
final File file = getTableFile(rootDir, STRING_TABLE_NAME);
myEnumerator = new PersistentStringEnumerator(file, true);
myEmptyName = myEnumerator.enumerate("");
}
@Nullable
public String getValue(final int s) {
try {
return myEnumerator.valueOf(s);
@@ -73,9 +79,20 @@ class DependencyContext {
public int get(final String s) {
try {
final int i = s == null ? myEnumerator.enumerate("") : myEnumerator.enumerate(s);
return StringUtil.isEmpty(s) ? myEmptyName : myEnumerator.enumerate(s);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
return i;
public int getFilePath(final String path) {
try {
if (StringUtil.isEmpty(path)) {
return myEmptyName;
}
final String _path = FileUtil.toSystemIndependentName(path);
return myEnumerator.enumerate(SystemInfo.isFileSystemCaseSensitive ? _path : _path.toLowerCase(Locale.US));
}
catch (IOException e) {
throw new RuntimeException(e);
@@ -146,7 +146,7 @@ public class Mappings {
private void compensateRemovedContent(final Collection<File> compiled) {
if (compiled != null) {
for (final File file : compiled) {
final int fileName = myContext.get(FileUtil.toSystemIndependentName(file.getAbsolutePath()));
final int fileName = myContext.getFilePath(file.getPath());
if (!mySourceFileToClasses.containsKey(fileName)) {
mySourceFileToClasses.put(fileName, new HashSet<ClassRepr>());
}
@@ -949,7 +949,7 @@ public class Mappings {
if (removed != null) {
for (final String file : removed) {
final Collection<ClassRepr> classes = mySourceFileToClasses.get(myContext.get(file));
final Collection<ClassRepr> classes = mySourceFileToClasses.get(myContext.getFilePath(file));
if (classes != null) {
for (ClassRepr c : classes) {
@@ -1965,7 +1965,7 @@ public class Mappings {
if (removed != null) {
for (final String file : removed) {
final int fileName = myContext.get(file);
final int fileName = myContext.getFilePath(file);
final Set<ClassRepr> fileClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
if (fileClasses != null) {
@@ -2101,12 +2101,12 @@ public class Mappings {
return new Callbacks.Backend() {
public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
synchronized (myLock) {
final int classFileNameS = myContext.get(classFileName);
final int classFileNameS = myContext.getFilePath(classFileName);
final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
final ClassRepr repr = result.first;
if (repr != null) {
final Set<UsageRepr.Usage> localUsages = result.second;
final int sourceFileNameS = myContext.get(sourceFileName);
final int sourceFileNameS = myContext.getFilePath(sourceFileName);
final int className = repr.name;
myClassToSourceFile.put(className, sourceFileNameS);
@@ -2146,20 +2146,20 @@ public class Mappings {
if (!allImports.isEmpty()) {
myPostPasses.offer(new Runnable() {
public void run() {
final int rootClassName = myContext.get(className.replace(".", "/"));
final int fileName = myClassToSourceFile.get(rootClassName);
final ClassRepr repr = fileName > 0? getReprByName(rootClassName) : null;
public void run() {
final int rootClassName = myContext.get(className.replace(".", "/"));
final int fileName = myClassToSourceFile.get(rootClassName);
final ClassRepr repr = fileName > 0? getReprByName(rootClassName) : null;
for (final String i : allImports) {
final int iname = myContext.get(i.replace(".", "/"));
myClassToClassDependency.put(iname, rootClassName);
if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
mySourceFileToClasses.put(fileName, repr);
}
}
}
});
for (final String i : allImports) {
final int iname = myContext.get(i.replace(".", "/"));
myClassToClassDependency.put(iname, rootClassName);
if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
mySourceFileToClasses.put(fileName, repr);
}
}
}
});
}
}
};
@@ -2168,7 +2168,7 @@ public class Mappings {
@Nullable
public Set<ClassRepr> getClasses(final String sourceFileName) {
synchronized (myLock) {
return (Set<ClassRepr>)mySourceFileToClasses.get(myContext.get(sourceFileName));
return (Set<ClassRepr>)mySourceFileToClasses.get(myContext.getFilePath(sourceFileName));
}
}
@@ -11,13 +11,17 @@ import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.MultiMapBasedOnSet;
import com.intellij.util.io.MappingFailedException;
import com.intellij.util.io.PersistentEnumerator;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.*;
import org.jetbrains.jps.JpsPathUtil;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.ProjectChunks;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.cmdline.BuildRunner;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.fs.BuildFSState;
@@ -946,7 +950,7 @@ public class IncProjectBuilder {
}
final Timestamps timestamps = pd.timestamps.getStorage();
final HashSet<File> currentFiles = new HashSet<File>();
final THashSet<File> currentFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
FSOperations.markDirtyFiles(context, target, timestamps, forceMarkDirty, target.isTests() ? FSOperations.DirtyMarkScope.TESTS : FSOperations.DirtyMarkScope.PRODUCTION, currentFiles);
// handle deleted paths
@@ -4,7 +4,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.IOUtil;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.Utils;
@@ -50,7 +49,7 @@ final class FilesDelta {
final File root = new File(IOUtil.readString(in));
Set<File> files = myFilesToRecompile.get(root);
if (files == null) {
files = createSetOfFiles();
files = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
myFilesToRecompile.put(root, files);
}
int filesCount = in.readInt();
@@ -69,20 +68,6 @@ final class FilesDelta {
}
private static Set<File> createSetOfFiles() {
return new THashSet<File>(new TObjectHashingStrategy<File>() {
@Override
public int computeHashCode(File file) {
return FileUtil.fileHashCode(file);
}
@Override
public boolean equals(File f1, File f2) {
return FileUtil.filesEqual(f1, f2);
}
});
}
public boolean markRecompile(File root, File file) {
final boolean added = _addToRecompiled(root, file);
if (added) {
@@ -115,7 +100,7 @@ final class FilesDelta {
synchronized (myFilesToRecompile) {
files = myFilesToRecompile.get(root);
if (files == null) {
files = createSetOfFiles();
files = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
myFilesToRecompile.put(root, files);
}
return files.add(file);
@@ -22,7 +22,17 @@ import java.util.List;
public final class SourceToOutputMapping extends AbstractStateStorage<String, Collection<String>> {
public SourceToOutputMapping(File storePath) throws IOException {
super(storePath, new EnumeratorStringDescriptor(), new StringCollectionExternalizer());
super(storePath, new EnumeratorStringDescriptor() {
@Override
public int getHashCode(String value) {
return FileUtil.pathHashCode(value);
}
@Override
public boolean isEqual(String val1, String val2) {
return FileUtil.pathsEqual(val1, val2);
}
}, new StringCollectionExternalizer());
}
@Override