diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java b/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java index ed580e8d1272..0a8f41e27766 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/ClassRepr.java @@ -2,6 +2,8 @@ package org.jetbrains.ether.dependencyView; import com.intellij.util.io.DataExternalizer; import groovyjarjarasm.asm.Opcodes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.ether.RW; import java.io.*; @@ -165,6 +167,7 @@ public class ClassRepr extends Proto { }; } + @NotNull public int[] getSupers() { final int[] result = new int[myInterfaces.size() + 1]; @@ -297,6 +300,7 @@ public class ClassRepr extends Proto { return getPackageName(myContext.getValue(s)); } + @NotNull public static String getPackageName(final String raw) { final int index = raw.lastIndexOf('/'); @@ -307,6 +311,7 @@ public class ClassRepr extends Proto { return raw.substring(0, index); } + @Nullable public FieldRepr findField(final int name) { for (FieldRepr f : myFields) { if (f.name == name) { @@ -317,6 +322,7 @@ public class ClassRepr extends Proto { return null; } + @NotNull public Collection findMethods(final MethodRepr.Predicate p) { final Collection result = new LinkedList(); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 5fd6228acb02..5e81f8ef6538 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -335,128 +335,100 @@ public class Mappings { }; } - Collection> findOverridingMethods(final MethodRepr m, final ClassRepr c, final boolean bySpecificity) { - final Set> result = new HashSet>(); - final MethodRepr.Predicate predicate = bySpecificity ? lessSpecific(m) : MethodRepr.equalByJavaRules(m); + private void addOverridingMethods(final MethodRepr m, final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection> container) { + final TIntHashSet subClasses = myClassToSubclasses.get(fromClass.name); + if (subClasses == null) { + return; + } + subClasses.forEach(new TIntProcedure() { + @Override + public boolean execute(int subClassName) { + final ClassRepr r = reprByName(subClassName); - new Object() { - public void run(final ClassRepr c) { - final TIntHashSet subClasses = myClassToSubclasses.get(c.name); - - if (subClasses != null) { - subClasses.forEach(new TIntProcedure() { - @Override - public boolean execute(int subClassName) { - final ClassRepr r = reprByName(subClassName); - - if (r != null) { - boolean cont = true; - - final Collection methods = r.findMethods(predicate); - - for (MethodRepr mm : methods) { - if (isVisibleIn(c, m, r)) { - result.add(new Pair(mm, r)); - cont = false; - } - } - - if (cont) { - run(r); - } - } - return true; - } - }); - } - } - }.run(c); - - return result; - } - - Collection> findOverriddenMethods(final MethodRepr m, final ClassRepr c) { - return findOverridenMethods(m, c, false); - } - - Collection> findOverridenMethods(final MethodRepr m, final ClassRepr c, final boolean bySpecificity) { - final Set> result = new HashSet>(); - final MethodRepr.Predicate predicate = bySpecificity ? lessSpecific(m) : MethodRepr.equalByJavaRules(m); - - new Object() { - public void run(final ClassRepr c) { - final int[] supers = c.getSupers(); - - for (int succName : supers) { - final ClassRepr r = reprByName(succName); - - if (r != null) { - boolean cont = true; - - final Collection methods = r.findMethods(predicate); - - for (MethodRepr mm : methods) { - if (isVisibleIn(r, mm, c)) { - result.add(new Pair(mm, r)); - cont = false; - } - } - - if (cont) { - run(r); + if (r != null) { + boolean cont = true; + final Collection methods = r.findMethods(predicate); + for (MethodRepr mm : methods) { + if (isVisibleIn(fromClass, m, r)) { + container.add(new Pair(mm, r)); + cont = false; } } - else { - result.add(new Pair(MOCK_METHOD, MOCK_CLASS)); + if (cont) { + addOverridingMethods(m, r, predicate, container); } } + return true; } - }.run(c); + }); + } + private Collection> findAllMethodsBySpecificity(final MethodRepr m, final ClassRepr c) { + final MethodRepr.Predicate predicate = lessSpecific(m); + final Collection> result = new HashSet>(); + addOverridenMethods(c, predicate, result); + addOverridingMethods(m, c, predicate, result); return result; } - Collection> findAllMethodsBySpecificity(final MethodRepr m, final ClassRepr c) { - final Collection> result = findOverridenMethods(m, c, true); - - result.addAll(findOverridingMethods(m, c, true)); - + private Collection> findOverriddenMethods(final MethodRepr m, final ClassRepr c) { + final Collection> result = new HashSet>(); + addOverridenMethods(c, MethodRepr.equalByJavaRules(m), result); return result; } - Collection> findOverriddenFields(final FieldRepr f, final ClassRepr c) { - final Set> result = new HashSet>(); - - new Object() { - public void run(final ClassRepr c) { - final int[] supers = c.getSupers(); - - for (int succName : supers) { - final ClassRepr r = reprByName(succName); - - if (r != null) { - boolean cont = true; - - if (r.getFields().contains(f)) { - final FieldRepr ff = r.findField(f.name); - - if (ff != null) { - if (isVisibleIn(r, ff, c)) { - result.add(new Pair(ff, r)); - cont = false; - } - } - } - - if (cont) { - run(r); - } + private void addOverridenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate, final Collection> container) { + for (int superName : fromClass.getSupers()) { + final ClassRepr superClass = reprByName(superName); + if (superClass != null) { + boolean cont = true; + final Collection methods = superClass.findMethods(predicate); + for (MethodRepr mm : methods) { + if (isVisibleIn(superClass, mm, fromClass)) { + container.add(new Pair(mm, superClass)); + cont = false; } } + if (cont) { + addOverridenMethods(superClass, predicate, container); + } } - }.run(c); + else { + container.add(new Pair(MOCK_METHOD, MOCK_CLASS)); + } + } + } - return result; + private void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection> container) { + for (int supername : fromClass.getSupers()) { + final ClassRepr superClass = reprByName(supername); + if (superClass != null) { + final FieldRepr ff = superClass.findField(f.name); + if (ff != null && isVisibleIn(superClass, ff, fromClass)) { + container.add(new Pair(ff, superClass)); + } + else{ + addOverriddenFields(f, superClass, container); + } + } + } + } + + private boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) { + for (int supername : fromClass.getSupers()) { + final ClassRepr superClass = reprByName(supername); + if (superClass != null) { + final FieldRepr ff = superClass.findField(f.name); + if (ff != null && isVisibleIn(superClass, ff, fromClass)) { + return true; + } + final boolean found = hasOverriddenFields(f, superClass); + if (found) { + return true; + } + } + } + return false; } @Nullable @@ -535,25 +507,15 @@ public class Mappings { return false; } - boolean fieldVisible(final int className, final FieldRepr field) { + private boolean fieldVisible(final int className, final FieldRepr field) { final ClassRepr r = reprByName(className); - - if (r != null) { - if (r.getFields().contains(field)) { - return true; - } - - return findOverriddenFields(field, r).size() > 0; + if (r == null || r.getFields().contains(field)) { + return true; } - - return true; + return hasOverriddenFields(field, r); } - void affectSubclasses(final int className, - final Collection affectedFiles, - final Collection affectedUsages, - final TIntHashSet dependants, - final boolean usages) { + private void affectSubclasses(final int className, final Collection affectedFiles, final Collection affectedUsages, final TIntHashSet dependants, final boolean usages) { debug("Affecting subclasses of class: ", className); final int fileName = myClassToSourceFile.get(className); @@ -598,11 +560,7 @@ public class Mappings { } } - void affectFieldUsages(final FieldRepr field, - final TIntHashSet classes, - final UsageRepr.Usage rootUsage, - final Set affectedUsages, - final TIntHashSet dependents) { + private void affectFieldUsages(final FieldRepr field, final TIntHashSet classes, final UsageRepr.Usage rootUsage, final Set affectedUsages, final TIntHashSet dependents) { affectedUsages.add(rootUsage); classes.forEach(new TIntProcedure() { @@ -621,13 +579,8 @@ public class Mappings { }); } - void affectMethodUsages(final MethodRepr method, - final TIntHashSet subclasses, - final UsageRepr.Usage rootUsage, - final Set affectedUsages, - final TIntHashSet dependents) { + private void affectMethodUsages(final MethodRepr method, final TIntHashSet subclasses, final UsageRepr.Usage rootUsage, final Set affectedUsages, final TIntHashSet dependents) { affectedUsages.add(rootUsage); - if (subclasses != null) { subclasses.forEach(new TIntProcedure() { @Override @@ -649,7 +602,7 @@ public class Mappings { } } - void affectAll(final int className, final Collection affectedFiles, @Nullable final DependentFilesFilter filter) { + private void affectAll(final int className, final Collection affectedFiles, @Nullable final DependentFilesFilter filter) { final int sourceFile = myClassToSourceFile.get(className); if (sourceFile > 0) { final TIntHashSet dependants = myClassToClassDependency.get(className); @@ -767,10 +720,7 @@ public class Mappings { return acc; } - private boolean incrementalDecision(final int owner, - final Proto member, - final Collection affectedFiles, - @Nullable final DependentFilesFilter filter) { + private boolean incrementalDecision(final int owner, final Proto member, final Collection affectedFiles, @Nullable final DependentFilesFilter filter) { final boolean isField = member instanceof FieldRepr; final Util self = new Util(this); @@ -852,7 +802,7 @@ public class Mappings { } private class Differential { - final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; + private static final int DESPERATE_MASK = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; final Mappings myDelta; final Collection myFilesToCompile; @@ -1207,9 +1157,11 @@ public class Mappings { } } - final Collection> overriding = myUpdated.findOverridingMethods(m, it, false); + final Collection> overridingMethods = new HashSet>(); - for (final Pair p : overriding) { + myUpdated.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods); + + for (final Pair p : overridingMethods) { final int fName = myClassToSourceFile.get(p.second.name); affectedFiles.add(fName); debug("Affecting file by overriding: ", fName); @@ -1415,9 +1367,10 @@ public class Mappings { }); } - final Collection> overridden = myUpdated.findOverriddenFields(f, classRepr); + final Collection> overriddenFields = new HashSet>(); + myUpdated.addOverriddenFields(f, classRepr, overriddenFields); - for (final Pair p : overridden) { + for (final Pair p : overriddenFields) { final FieldRepr ff = p.first; final ClassRepr cc = p.second;