more accurate processing of class usages in generic bounds: process only those parent classes that really are missing from parents list recursively

This commit is contained in:
Eugene Zhuravlev
2012-11-06 16:53:19 +01:00
parent 657bbb1c74
commit 2bb8ca30bc
10 changed files with 71 additions and 31 deletions
@@ -0,0 +1,14 @@
Cleaning output files:
out/production/ArgumentContainment3/Sub2.class
End of files
Compiling files:
src/Sub2.java
End of files
Cleaning output files:
out/production/ArgumentContainment3/CaptureCreator2.class
out/production/ArgumentContainment3/GenericBound.class
End of files
Compiling files:
src/CaptureCreator2.java
src/GenericBound.java
End of files
@@ -0,0 +1,2 @@
public class Sub2 extends Parent {
}
@@ -0,0 +1,4 @@
public class CaptureCreator {
public void context(GenericBound<? extends Parent> p) {
}
}
@@ -0,0 +1,4 @@
public class CaptureCreator2 {
public void context(GenericBound<? extends Sub> p) {
}
}
@@ -0,0 +1,2 @@
public class GenericBound<T extends Sub2> {
}
@@ -0,0 +1,2 @@
public class Parent {
}
@@ -0,0 +1,2 @@
public class Sub extends Parent {
}
@@ -0,0 +1,2 @@
public class Sub2 extends Sub {
}
@@ -391,7 +391,7 @@ public class Mappings {
}
}
private void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
for (int supername : fromClass.getSupers()) {
final ClassRepr superClass = reprByName(supername);
if (superClass != null) {
@@ -406,7 +406,7 @@ public class Mappings {
}
}
private boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
for (int supername : fromClass.getSupers()) {
final ClassRepr superClass = reprByName(supername);
if (superClass != null) {
@@ -457,7 +457,7 @@ public class Mappings {
}
@Nullable
private Boolean isSubtypeOf(final TypeRepr.AbstractType who, final TypeRepr.AbstractType whom) {
Boolean isSubtypeOf(final TypeRepr.AbstractType who, final TypeRepr.AbstractType whom) {
if (who.equals(whom)) {
return Boolean.TRUE;
}
@@ -487,7 +487,7 @@ public class Mappings {
return Boolean.FALSE;
}
private boolean isMethodVisible(final int className, final MethodRepr m) {
boolean isMethodVisible(final int className, final MethodRepr m) {
final ClassRepr r = reprByName(className);
if (r != null) {
if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) {
@@ -498,7 +498,7 @@ public class Mappings {
return false;
}
private boolean isFieldVisible(final int className, final FieldRepr field) {
boolean isFieldVisible(final int className, final FieldRepr field) {
final ClassRepr r = reprByName(className);
if (r == null || r.getFields().contains(field)) {
return true;
@@ -506,27 +506,18 @@ public class Mappings {
return hasOverriddenFields(field, r);
}
private void affectUsagesInGenericBounds(final int className, final Collection<UsageRepr.Usage> affectedUsages, TIntHashSet dependants) {
if (className == myObjectClassName) {
return;
}
debug("Affecting usages in generic type parameter bounds of class: ", className);
affectedUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));
final TIntHashSet depClasses = myClassToClassDependency.get(className);
if (depClasses != null) {
addAll(dependants, depClasses);
}
void collectSupersRecursively(@NotNull final int className, @NotNull final TIntHashSet container) {
final ClassRepr classRepr = reprByName(className);
if (classRepr != null) {
for (int clsName : classRepr.getSupers()) {
affectUsagesInGenericBounds(clsName, affectedUsages, dependants);
final int[] supers = classRepr.getSupers();
container.addAll(supers);
for (int aSuper : supers) {
collectSupersRecursively(aSuper, container);
}
}
}
private void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages) {
void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages) {
debug("Affecting subclasses of class: ", className);
final File fileName = myClassToSourceFile.get(className);
@@ -566,7 +557,7 @@ public class Mappings {
}
}
private void affectFieldUsages(final FieldRepr field, final TIntHashSet classes, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
void affectFieldUsages(final FieldRepr field, final TIntHashSet classes, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
affectedUsages.add(rootUsage);
classes.forEach(new TIntProcedure() {
@@ -583,7 +574,7 @@ public class Mappings {
});
}
private void affectMethodUsages(final MethodRepr method, final TIntHashSet subclasses, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
void affectMethodUsages(final MethodRepr method, final TIntHashSet subclasses, final UsageRepr.Usage rootUsage, final Set<UsageRepr.Usage> affectedUsages, final TIntHashSet dependents) {
affectedUsages.add(rootUsage);
if (subclasses != null) {
subclasses.forEach(new TIntProcedure() {
@@ -666,7 +657,7 @@ public class Mappings {
}
}
private void affectAll(final int className, final Collection<File> affectedFiles, @Nullable final DependentFilesFilter filter) {
void affectAll(final int className, final Collection<File> affectedFiles, @Nullable final DependentFilesFilter filter) {
final File sourceFile = myClassToSourceFile.get(className);
if (sourceFile != null) {
final TIntHashSet dependants = myClassToClassDependency.get(className);
@@ -1606,14 +1597,26 @@ public class Mappings {
myFuture.affectSubclasses(changedClass.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, extendsChanged || interfacesRemoved || signatureChanged);
if (!changedClass.isAnonymous()) {
if (superClassChanged) {
myPresent.affectUsagesInGenericBounds(changedClass.getSuperClass().className, state.myAffectedUsages, state.myDependants);
}
if (interfacesChanged) {
for (final TypeRepr.AbstractType typ : diff.interfaces().removed()) {
final TypeRepr.ClassType removedIface = (TypeRepr.ClassType)typ;
myPresent.affectUsagesInGenericBounds(removedIface.className, state.myAffectedUsages, state.myDependants);
}
final TIntHashSet parents = new TIntHashSet();
myPresent.collectSupersRecursively(changedClass.name, parents);
final TIntHashSet futureParents = new TIntHashSet();
myFuture.collectSupersRecursively(changedClass.name, futureParents);
parents.removeAll(futureParents.toArray());
parents.remove(myObjectClassName);
if (!parents.isEmpty()) {
parents.forEach(new TIntProcedure() {
@Override
public boolean execute(int className) {
debug("Affecting usages in generic type parameter bounds of class: ", className);
state.myAffectedUsages.add(UsageRepr.createClassAsGenericBoundUsage(myContext, className));
final TIntHashSet depClasses = myClassToClassDependency.get(className);
if (depClasses != null) {
addAll(state.myDependants, depClasses);
}
return true;
}
});
}
}
}
@@ -130,7 +130,12 @@ public class GenericTest extends IncrementalTestCase {
public void testArgumentContainment() throws Exception {
doTest();
}
public void testArgumentContainment2() throws Exception {
doTest();
}
public void testArgumentContainment3() throws Exception {
doTest();
}
}