mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
supporting for multiple source files association with a single class name (needed for Kotlin)
This commit is contained in:
@@ -29,6 +29,7 @@ public class Callbacks {
|
||||
|
||||
public interface Backend {
|
||||
void associate(String classFileName, String sourceFileName, ClassReader cr);
|
||||
void associate(String classFileName, Collection<String> sources, ClassReader cr);
|
||||
void registerImports(String className, Collection<String> imports, Collection<String> staticImports);
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -28,7 +28,7 @@ import java.util.List;
|
||||
* @author: db
|
||||
* Date: 03.11.11
|
||||
*/
|
||||
abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable {
|
||||
abstract class IntObjectMultiMaplet<V> implements Streamable {
|
||||
abstract boolean containsKey(final int key);
|
||||
|
||||
abstract Collection<V> get(final int key);
|
||||
@@ -78,12 +78,17 @@ abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable
|
||||
final List<String> list = new LinkedList<String>();
|
||||
|
||||
for (final V value : b) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final PrintStream s = new PrintStream(baos);
|
||||
if (value instanceof Streamable) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
final PrintStream s = new PrintStream(baos);
|
||||
|
||||
value.toStream(context, s);
|
||||
((Streamable)value).toStream(context, s);
|
||||
|
||||
list.add(baos.toString());
|
||||
list.add(baos.toString());
|
||||
}
|
||||
else {
|
||||
list.add(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(list);
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import java.util.Collections;
|
||||
* @author: db
|
||||
* Date: 08.03.11
|
||||
*/
|
||||
class IntObjectPersistentMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
|
||||
class IntObjectPersistentMultiMaplet<V> extends IntObjectMultiMaplet<V> {
|
||||
private static final Collection NULL_COLLECTION = Collections.emptySet();
|
||||
private static final int CACHE_SIZE = 128;
|
||||
private final PersistentHashMap<Integer, Collection<V>> myMap;
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import java.util.Collection;
|
||||
* @author: db
|
||||
* Date: 08.03.11
|
||||
*/
|
||||
class IntObjectTransientMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
|
||||
class IntObjectTransientMultiMaplet<V> extends IntObjectMultiMaplet<V> {
|
||||
|
||||
private final TIntObjectHashMap<Collection<V>> myMap = new TIntObjectHashMap<Collection<V>>();
|
||||
private final CollectionFactory<V> myCollectionFactory;
|
||||
|
||||
+159
-109
@@ -85,7 +85,7 @@ public class Mappings {
|
||||
*/
|
||||
private IntIntMultiMaplet myClassToClassDependency;
|
||||
private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
|
||||
private IntObjectMaplet<File> myClassToSourceFile;
|
||||
private IntObjectMultiMaplet<File> myClassToSourceFile;
|
||||
/**
|
||||
* [short className] -> list of FQ names
|
||||
*/
|
||||
@@ -138,12 +138,17 @@ public class Mappings {
|
||||
myRemovedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
|
||||
myAddedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
|
||||
|
||||
final CollectionFactory<File> fileCollectionFactory = new CollectionFactory<File>() {
|
||||
public Collection<File> create() {
|
||||
return new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); // todo: do we really need set and not a list here?
|
||||
}
|
||||
};
|
||||
if (myIsDelta && myDeltaIsTransient) {
|
||||
myClassToSubclasses = new IntIntTransientMultiMaplet();
|
||||
myClassToClassDependency = new IntIntTransientMultiMaplet();
|
||||
myShortClassNameIndex = null;
|
||||
mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
|
||||
myClassToSourceFile = new IntObjectTransientMaplet<File>();
|
||||
myClassToSourceFile = new IntObjectTransientMultiMaplet<File>(fileCollectionFactory);
|
||||
}
|
||||
else {
|
||||
if (myIsDelta) {
|
||||
@@ -156,7 +161,7 @@ public class Mappings {
|
||||
DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
|
||||
ourClassSetConstructor
|
||||
);
|
||||
myClassToSourceFile = new IntObjectPersistentMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), new FileKeyDescriptor());
|
||||
myClassToSourceFile = new IntObjectPersistentMultiMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR, new FileKeyDescriptor(), fileCollectionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,17 +195,17 @@ public class Mappings {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassRepr getReprByName(@Nullable File source, final int name) {
|
||||
if (source == null) {
|
||||
source = myClassToSourceFile.get(name);
|
||||
}
|
||||
if (source != null) {
|
||||
final Collection<ClassRepr> reprs = mySourceFileToClasses.get(source);
|
||||
private ClassRepr getReprByName(final @Nullable File source, final int qName) {
|
||||
final Collection<File> sources = source != null? Collections.singleton(source) : myClassToSourceFile.get(qName);
|
||||
if (sources != null) {
|
||||
for (File src : sources) {
|
||||
final Collection<ClassRepr> reprs = mySourceFileToClasses.get(src);
|
||||
|
||||
if (reprs != null) {
|
||||
for (ClassRepr repr : reprs) {
|
||||
if (repr.name == name) {
|
||||
return repr;
|
||||
if (reprs != null) {
|
||||
for (ClassRepr repr : reprs) {
|
||||
if (repr.name == qName) {
|
||||
return repr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,14 +561,19 @@ public class Mappings {
|
||||
void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages, final Collection<File> alreadyCompiledFiles) {
|
||||
debug("Affecting subclasses of class: ", className);
|
||||
|
||||
final File fileName = myClassToSourceFile.get(className);
|
||||
if (fileName == null) {
|
||||
final Collection<File> allSources = myClassToSourceFile.get(className);
|
||||
if (allSources == null || allSources.isEmpty()) {
|
||||
debug("No source file detected for class ", className);
|
||||
debug("End of affectSubclasses");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Source file name: ", fileName);
|
||||
for (File fName : allSources) {
|
||||
debug("Source file name: ", fName);
|
||||
if (!alreadyCompiledFiles.contains(fName)) {
|
||||
affectedFiles.add(fName);
|
||||
}
|
||||
}
|
||||
|
||||
if (usages) {
|
||||
debug("Class usages affection requested");
|
||||
@@ -579,9 +589,6 @@ public class Mappings {
|
||||
if (depClasses != null) {
|
||||
addAll(dependants, depClasses);
|
||||
}
|
||||
if (!alreadyCompiledFiles.contains(fileName)) {
|
||||
affectedFiles.add(fileName);
|
||||
}
|
||||
|
||||
final TIntHashSet directSubclasses = myClassToSubclasses.get(className);
|
||||
if (directSubclasses != null) {
|
||||
@@ -701,10 +708,14 @@ public class Mappings {
|
||||
dependants.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int depClass) {
|
||||
final File depFile = myClassToSourceFile.get(depClass);
|
||||
if (depFile != null && !FileUtil.filesEqual(depFile, sourceFile)) {
|
||||
if (filter == null || filter.accept(depFile)) {
|
||||
affectedFiles.add(depFile);
|
||||
final Collection<File> allSources = myClassToSourceFile.get(depClass);
|
||||
if (allSources != null) {
|
||||
for (File depFile : allSources) {
|
||||
if (!FileUtil.filesEqual(depFile, sourceFile)) {
|
||||
if (filter == null || filter.accept(depFile)) {
|
||||
affectedFiles.add(depFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -768,10 +779,12 @@ public class Mappings {
|
||||
propagated.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int className) {
|
||||
final File fileName = myClassToSourceFile.get(className);
|
||||
if (fileName != null) {
|
||||
debug("Adding ", fileName);
|
||||
toRecompile.add(fileName);
|
||||
final Collection<File> fileNames = myClassToSourceFile.get(className);
|
||||
if (fileNames != null) {
|
||||
for (File fileName : fileNames) {
|
||||
debug("Adding ", fileName);
|
||||
}
|
||||
toRecompile.addAll(fileNames);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -784,13 +797,15 @@ public class Mappings {
|
||||
debug("Package name: ", packageName);
|
||||
|
||||
// Package-local branch
|
||||
myClassToSourceFile.forEachEntry(new TIntObjectProcedure<File>() {
|
||||
myClassToSourceFile.forEachEntry(new TIntObjectProcedure<Collection<File>>() {
|
||||
@Override
|
||||
public boolean execute(int className, File fileName) {
|
||||
public boolean execute(int className, Collection<File> fileNames) {
|
||||
if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
|
||||
if (filter == null || filter.accept(fileName)) {
|
||||
debug("Adding: ", fileName);
|
||||
toRecompile.add(fileName);
|
||||
for (File fileName : fileNames) {
|
||||
if (filter == null || filter.accept(fileName)) {
|
||||
debug("Adding: ", fileName);
|
||||
toRecompile.add(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1107,12 +1122,14 @@ public class Mappings {
|
||||
if (overrides.satisfy(method) && isInheritor) {
|
||||
debug("Current method overrides that found");
|
||||
|
||||
final File file = myClassToSourceFile.get(methodClass.name);
|
||||
|
||||
if (file != null) {
|
||||
myAffectedFiles.add(file);
|
||||
debug("Affecting file ", file);
|
||||
final Collection<File> files = myClassToSourceFile.get(methodClass.name);
|
||||
if (files != null) {
|
||||
myAffectedFiles.addAll(files);
|
||||
for (File file : files) {
|
||||
debug("Affecting file ", file);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
debug("Current method does not override that found");
|
||||
@@ -1141,12 +1158,15 @@ public class Mappings {
|
||||
@Override
|
||||
public boolean execute(int subClass) {
|
||||
final ClassRepr r = myFuture.reprByName(subClass);
|
||||
if (r != null) {
|
||||
final File sourceFileName = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
|
||||
myAffectedFiles.add(sourceFileName);
|
||||
if (r == null) {
|
||||
return true;
|
||||
}
|
||||
final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting file due to local overriding: ", sourceFileName);
|
||||
}
|
||||
}
|
||||
@@ -1199,10 +1219,12 @@ public class Mappings {
|
||||
myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);
|
||||
|
||||
for (final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
|
||||
final File fName = myClassToSourceFile.get(p.second.name);
|
||||
if (fName != null) {
|
||||
myAffectedFiles.add(fName);
|
||||
debug("Affecting file by overriding: ", fName);
|
||||
final Collection<File> fNames = myClassToSourceFile.get(p.second.name);
|
||||
if (fNames != null) {
|
||||
myAffectedFiles.addAll(fNames);
|
||||
for (File fName : fNames) {
|
||||
debug("Affecting file by overriding: ", fName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1242,12 +1264,14 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if (allAbstract && visited) {
|
||||
final File source = myClassToSourceFile.get(p);
|
||||
final Collection<File> sources = myClassToSourceFile.get(p);
|
||||
|
||||
if (source != null && !myCompiledFiles.contains(source)) {
|
||||
myAffectedFiles.add(source);
|
||||
if (sources != null && !myCompiledFiles.containsAll(sources)) {
|
||||
myAffectedFiles.addAll(sources);
|
||||
debug("Removed method is not abstract & overrides some abstract method which is not then over-overridden in subclass ", p);
|
||||
debug("Affecting subclass source file ", source);
|
||||
for (File source : sources) {
|
||||
debug("Affecting subclass source file ", source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1317,9 +1341,9 @@ public class Mappings {
|
||||
final ClassRepr aClass = p.getSecond();
|
||||
|
||||
if (aClass != MOCK_CLASS) {
|
||||
final File fileName = myClassToSourceFile.get(aClass.name);
|
||||
if (fileName != null) {
|
||||
myAffectedFiles.add(fileName);
|
||||
final Collection<File> fileNames = myClassToSourceFile.get(aClass.name);
|
||||
if (fileNames != null) {
|
||||
myAffectedFiles.addAll(fileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1387,17 +1411,21 @@ public class Mappings {
|
||||
public boolean execute(int subClass) {
|
||||
final ClassRepr r = myFuture.reprByName(subClass);
|
||||
if (r != null) {
|
||||
final File sourceFileName = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
|
||||
final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
if (r.isLocal()) {
|
||||
debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
|
||||
myAffectedFiles.add(sourceFileName);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
|
||||
}
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
}
|
||||
else {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, f)) {
|
||||
debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
|
||||
myAffectedFiles.add(sourceFileName);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
|
||||
}
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1796,7 +1824,9 @@ public class Mappings {
|
||||
// checking if this newly added class duplicates already existing one
|
||||
for (ClassRepr c : addedClasses) {
|
||||
if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
|
||||
final File currentlyMappedTo = myClassToSourceFile.get(c.name);
|
||||
final Collection<File> currentSources = myClassToSourceFile.get(c.name);
|
||||
final File currentlyMappedTo = currentSources != null && currentSources.size() == 1? currentSources.iterator().next() : null;
|
||||
// only check, if exactly one file is mapped
|
||||
if (currentlyMappedTo != null && !FileUtil.filesEqual(currentlyMappedTo, srcFile) && currentlyMappedTo.exists() && myFilter.belongsToCurrentTargetChunk(currentlyMappedTo)) {
|
||||
// Same classes from different source files.
|
||||
// Schedule for recompilation both to make possible 'duplicate sources' error evident
|
||||
@@ -1845,11 +1875,13 @@ public class Mappings {
|
||||
toAffect.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int depClass) {
|
||||
final File fName = myClassToSourceFile.get(depClass);
|
||||
if (fName != null) {
|
||||
if (myFilter == null || myFilter.accept(fName)) {
|
||||
debug("Adding dependent file ", fName);
|
||||
myAffectedFiles.add(fName);
|
||||
final Collection<File> fNames = myClassToSourceFile.get(depClass);
|
||||
if (fNames != null) {
|
||||
for (File fName : fNames) {
|
||||
if (myFilter == null || myFilter.accept(fName)) {
|
||||
debug("Adding dependent file ", fName);
|
||||
myAffectedFiles.add(fName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1863,24 +1895,30 @@ public class Mappings {
|
||||
state.myDependants.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(final int depClass) {
|
||||
final File depFile = myClassToSourceFile.get(depClass);
|
||||
final Collection<File> depFiles = myClassToSourceFile.get(depClass);
|
||||
if (depFiles != null) {
|
||||
for (File depFile : depFiles) {
|
||||
processDependentFile(depClass, depFile);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (depFile == null || myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
|
||||
return true;
|
||||
private void processDependentFile(int depClass, @NotNull File depFile) {
|
||||
if (myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Dependent class: ", depClass);
|
||||
|
||||
final ClassRepr classRepr = getReprByName(depFile, depClass);
|
||||
|
||||
if (classRepr == null) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
|
||||
|
||||
if (depUsages == null || depUsages.isEmpty()) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (UsageRepr.Usage usage : depUsages) {
|
||||
@@ -1889,32 +1927,24 @@ public class Mappings {
|
||||
if (query.satisfies(usage)) {
|
||||
debug("Added file due to annotation query");
|
||||
myAffectedFiles.add(depFile);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state.myAffectedUsages.contains(usage)) {
|
||||
final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
|
||||
|
||||
if (constraint == null) {
|
||||
debug("Added file with no constraints");
|
||||
myAffectedFiles.add(depFile);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (constraint.checkResidence(depClass)) {
|
||||
debug("Added file with satisfied constraint");
|
||||
myAffectedFiles.add(depFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (constraint.checkResidence(depClass)) {
|
||||
debug("Added file with satisfied constraint");
|
||||
myAffectedFiles.add(depFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2020,11 +2050,27 @@ public class Mappings {
|
||||
|
||||
private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
|
||||
final int className = cr.name;
|
||||
if (!FileUtil.filesEqual(sourceFile, myClassToSourceFile.get(className))) {
|
||||
// if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
|
||||
// we cannot destroy all these links
|
||||
|
||||
// it is safe to cleanup class information if it is mapped to non-existing files only
|
||||
final Collection<File> currentlyMapped = myClassToSourceFile.get(className);
|
||||
if (currentlyMapped == null || currentlyMapped.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (currentlyMapped.size() == 1) {
|
||||
if (!FileUtil.filesEqual(sourceFile, currentlyMapped.iterator().next())) {
|
||||
// if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
|
||||
// we cannot destroy all these links
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// many files
|
||||
for (File file : currentlyMapped) {
|
||||
if (!FileUtil.filesEqual(sourceFile, file) && file.exists()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final int superSomething : cr.getSupers()) {
|
||||
delta.registerRemovedSuperClass(className, superSomething);
|
||||
@@ -2126,13 +2172,8 @@ public class Mappings {
|
||||
delta.getChangedClasses().forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(final int className) {
|
||||
final File sourceFile = delta.myClassToSourceFile.get(className);
|
||||
if (sourceFile != null) {
|
||||
myClassToSourceFile.put(className, sourceFile);
|
||||
}
|
||||
else {
|
||||
myClassToSourceFile.remove(className);
|
||||
}
|
||||
final Collection<File> sourceFiles = delta.myClassToSourceFile.get(className);
|
||||
myClassToSourceFile.replace(className, sourceFiles);
|
||||
|
||||
cleanupBackDependency(className, null, dependenciesTrashBin);
|
||||
|
||||
@@ -2151,7 +2192,7 @@ public class Mappings {
|
||||
}
|
||||
else {
|
||||
myClassToSubclasses.putAll(delta.myClassToSubclasses);
|
||||
myClassToSourceFile.putAll(delta.myClassToSourceFile);
|
||||
myClassToSourceFile.replaceAll(delta.myClassToSourceFile);
|
||||
mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
public boolean execute(File src, Collection<ClassRepr> classes) {
|
||||
@@ -2216,18 +2257,21 @@ public class Mappings {
|
||||
|
||||
public Callbacks.Backend getCallback() {
|
||||
return new Callbacks.Backend() {
|
||||
public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
|
||||
|
||||
public void associate(String classFileName, Collection<String> sources, ClassReader cr) {
|
||||
synchronized (myLock) {
|
||||
final int classFileNameS = myContext.get(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 File sourceFile = new File(sourceFileName);
|
||||
final int className = repr.name;
|
||||
|
||||
myClassToSourceFile.put(className, sourceFile);
|
||||
mySourceFileToClasses.put(sourceFile, repr);
|
||||
for (String sourceFileName : sources) {
|
||||
final File sourceFile = new File(sourceFileName);
|
||||
myClassToSourceFile.put(className, sourceFile);
|
||||
mySourceFileToClasses.put(sourceFile, repr);
|
||||
}
|
||||
|
||||
for (final int s : repr.getSupers()) {
|
||||
myClassToSubclasses.put(s, className);
|
||||
@@ -2244,6 +2288,10 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
|
||||
associate(classFileName, Collections.singleton(sourceFileName), cr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerImports(final String className, final Collection<String> imports, Collection<String> staticImports) {
|
||||
final List<String> allImports = new ArrayList<String>();
|
||||
@@ -2265,14 +2313,16 @@ public class Mappings {
|
||||
myPostPasses.offer(new Runnable() {
|
||||
public void run() {
|
||||
final int rootClassName = myContext.get(className.replace(".", "/"));
|
||||
final File fileName = myClassToSourceFile.get(rootClassName);
|
||||
final ClassRepr repr = fileName != null? getReprByName(fileName, rootClassName) : null;
|
||||
final Collection<File> fileNames = myClassToSourceFile.get(rootClassName);
|
||||
final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getReprByName(fileNames.iterator().next(), rootClassName) : null;
|
||||
|
||||
for (final String i : allImports) {
|
||||
final int iname = myContext.get(i.replace(".", "/"));
|
||||
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 (File fileName : fileNames) {
|
||||
mySourceFileToClasses.put(fileName, repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2399,10 +2449,10 @@ public class Mappings {
|
||||
assert (myChangedClasses != null && myChangedFiles != null);
|
||||
myChangedClasses.add(it);
|
||||
|
||||
final File file = myClassToSourceFile.get(it);
|
||||
final Collection<File> files = myClassToSourceFile.get(it);
|
||||
|
||||
if (file != null) {
|
||||
myChangedFiles.add(file);
|
||||
if (files != null) {
|
||||
myChangedFiles.addAll(files);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* Date: 10/7/11
|
||||
*/
|
||||
public class BuildDataManager implements StorageOwner {
|
||||
private static final int VERSION = 24;
|
||||
private static final int VERSION = 25;
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
|
||||
private static final String SRC_TO_FORM_STORAGE = "src-form";
|
||||
private static final String OUT_TARGET_STORAGE = "out-target";
|
||||
|
||||
Reference in New Issue
Block a user