mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Description
This commit is contained in:
@@ -172,32 +172,4 @@ public class GenericsUtil {
|
||||
return type.getInternalCanonicalText().equals(type.getCanonicalText());
|
||||
}
|
||||
|
||||
public static PsiClass[] getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(aClass, bClass, true)) {
|
||||
return new PsiClass[]{aClass};
|
||||
}
|
||||
|
||||
if (InheritanceUtil.isInheritorOrSelf(bClass, aClass, true)) {
|
||||
return new PsiClass[]{bClass};
|
||||
}
|
||||
|
||||
final Set<PsiClass> descendants = new LinkedHashSet<PsiClass>();
|
||||
|
||||
new Object() {
|
||||
public void getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass, final Set<PsiClass> descendants) {
|
||||
if (aClass.isInheritor(bClass, true)) {
|
||||
descendants.add(bClass);
|
||||
}
|
||||
else {
|
||||
final PsiSearchHelper helper = aClass.getManager().getSearchHelper();
|
||||
final PsiClass[] bSubs = helper.findInheritors(bClass, helper.getUseScope(bClass), true);
|
||||
for (int i = 0; i < bSubs.length; i++) {
|
||||
getLeastUpperClassesInner(bSubs[i], aClass, descendants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.getGreatestLowerClasses(aClass, bClass, descendants);
|
||||
|
||||
return descendants.toArray(new PsiClass[descendants.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,10 @@ public class System {
|
||||
final PsiElement element = i.next();
|
||||
final PsiType type = myTypes.get(element);
|
||||
|
||||
if (type == null){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element instanceof PsiParameter) {
|
||||
final PsiParameter parm = (PsiParameter)element;
|
||||
final PsiMethod method = (PsiMethod)parm.getDeclarationScope();
|
||||
@@ -429,7 +433,11 @@ public class System {
|
||||
|
||||
for (final Iterator<PsiElement> e = myElements.iterator(); e.hasNext();) {
|
||||
final PsiElement element = e.next();
|
||||
data[i++] = binding.substitute(myTypes.get(element)).getCanonicalText() + "\\n" + elementString(element);
|
||||
final PsiType t = myTypes.get(element);
|
||||
if (t != null)
|
||||
data[i++] = binding.substitute(t).getCanonicalText() + "\\n" + elementString(element);
|
||||
else
|
||||
data[i++] = "\\n" + elementString(element);
|
||||
}
|
||||
|
||||
Arrays.sort(data,
|
||||
|
||||
@@ -33,6 +33,7 @@ public class SystemBuilder {
|
||||
private PsiManager myManager;
|
||||
private HashMap<PsiElement, Boolean> myMethodCache;
|
||||
private HashMap<PsiParameter, PsiParameter> myParameters;
|
||||
private HashMap<PsiMethod, PsiMethod> myMethods;
|
||||
private HashMap<PsiMethod, PsiMethod> mySuper;
|
||||
private HashMap<PsiElement, PsiType> myTypes;
|
||||
private HashSet<PsiAnchor> myVisitedConstructions;
|
||||
@@ -46,6 +47,7 @@ public class SystemBuilder {
|
||||
mySettings = settings;
|
||||
myMethodCache = new HashMap<PsiElement, Boolean>();
|
||||
myParameters = new HashMap<PsiParameter, PsiParameter>();
|
||||
myMethods = new HashMap<PsiMethod, PsiMethod>();
|
||||
mySuper = new HashMap<PsiMethod, PsiMethod>();
|
||||
myTypes = new HashMap<PsiElement, PsiType>();
|
||||
myVisitedConstructions = new HashSet<PsiAnchor>();
|
||||
@@ -95,16 +97,25 @@ public class SystemBuilder {
|
||||
|
||||
keyMethod = superMethod;
|
||||
|
||||
myMethods.put(method, keyMethod);
|
||||
|
||||
if (parameter != null) {
|
||||
keyParameter = (PsiParameter)e;
|
||||
myParameters.put(parameter, keyParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Boolean good = myMethodCache.get(method);
|
||||
|
||||
if (good != null) {
|
||||
return good.booleanValue();
|
||||
if (good != null && good.booleanValue()) {
|
||||
if (myMethods.get(method) == null) {
|
||||
myMethods.put(method, method);
|
||||
}
|
||||
|
||||
if (parameter != null && myParameters.get(parameter) == null) {
|
||||
myParameters.put(parameter, parameter);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
keyMethod = method;
|
||||
@@ -112,29 +123,35 @@ public class SystemBuilder {
|
||||
}
|
||||
|
||||
final PsiMethod[] overriders = helper.findOverridingMethods(keyMethod, keyMethod.getUseScope(), true);
|
||||
PsiMethod prev = keyMethod;
|
||||
|
||||
for (int i = 0; i < overriders.length; i++) {
|
||||
PsiMethod overrider = overriders[i];
|
||||
|
||||
if (prev != null) {
|
||||
mySuper.put(overrider, prev);
|
||||
prev = overrider;
|
||||
}
|
||||
|
||||
PsiElement e =
|
||||
parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
|
||||
final PsiMethod overrider = overriders[i];
|
||||
final PsiElement e = parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
|
||||
|
||||
if (!victims.contains(e)) {
|
||||
myMethodCache.put(keyMethod, new Boolean(false));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < overriders.length; i++) {
|
||||
final PsiMethod overrider = overriders[i];
|
||||
final PsiElement e = parameter == null ? (PsiElement)overrider : overrider.getParameterList().getParameters()[index];
|
||||
|
||||
mySuper.put(overrider, keyMethod);
|
||||
myMethods.put(overrider, keyMethod);
|
||||
|
||||
if (parameter != null) {
|
||||
myParameters.put(parameter, keyParameter);
|
||||
myParameters.put((PsiParameter)e, keyParameter);
|
||||
}
|
||||
}
|
||||
|
||||
myMethods.put(method, keyMethod);
|
||||
|
||||
if (parameter != null) {
|
||||
myParameters.put(parameter, keyParameter);
|
||||
}
|
||||
|
||||
myMethodCache.put(keyMethod, new Boolean(true));
|
||||
|
||||
return true;
|
||||
@@ -279,100 +296,106 @@ public class SystemBuilder {
|
||||
}
|
||||
else {
|
||||
final PsiType theType =
|
||||
new Object() {
|
||||
PsiType introduceAdditionalTypeVariables(final PsiType type,
|
||||
final PsiSubstitutor qualifier,
|
||||
final PsiSubstitutor supertype) {
|
||||
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
|
||||
final PsiClass aClass = result.getElement();
|
||||
new Object() {
|
||||
PsiType introduceAdditionalTypeVariables(final PsiType type,
|
||||
final PsiSubstitutor qualifier,
|
||||
final PsiSubstitutor supertype) {
|
||||
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
|
||||
final PsiClass aClass = result.getElement();
|
||||
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
final PsiTypeParameter tp = ((PsiTypeParameter)aClass);
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
final PsiTypeParameter tp = ((PsiTypeParameter)aClass);
|
||||
final PsiClassType[] extypes = tp.getExtendsListTypes();
|
||||
|
||||
PsiType pv = mapping.get(tp);
|
||||
PsiType pv = mapping.get(tp);
|
||||
|
||||
if (pv == null) {
|
||||
pv = myTypeVariableFactory.create();
|
||||
mapping.put(tp, pv);
|
||||
}
|
||||
|
||||
return pv;
|
||||
if (pv == null) {
|
||||
pv = myTypeVariableFactory.create();
|
||||
mapping.put(tp, pv);
|
||||
}
|
||||
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap = result.getSubstitutor().getSubstitutionMap();
|
||||
|
||||
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (Iterator<PsiTypeParameter> t = substitutionMap.keySet().iterator(); t.hasNext();) {
|
||||
final PsiTypeParameter p = t.next();
|
||||
final PsiType pType = substitutionMap.get(p);
|
||||
|
||||
if (pType instanceof PsiWildcardType) {
|
||||
final PsiWildcardType wildcard = ((PsiWildcardType)pType);
|
||||
final PsiType theBound = wildcard.getBound();
|
||||
|
||||
if (theBound != null) {
|
||||
final PsiType bound = Util.substituteType(Util.substituteType(theBound, supertype), qualifier);
|
||||
|
||||
if (Util.bindsTypeVariables(bound)) {
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(bound, var);
|
||||
}
|
||||
else {
|
||||
system.addSubtypeConstraint(var, bound);
|
||||
}
|
||||
|
||||
theSubst = theSubst.put(p, var);
|
||||
}
|
||||
else if (Util.bindsTypeParameters(bound, typeParameters)) {
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (int i = 0; i < aTypeParms.length; i++) {
|
||||
final PsiTypeParameter aTypeParm = aTypeParms[i];
|
||||
|
||||
PsiType parmVar = mapping.get(aTypeParm);
|
||||
|
||||
if (parmVar == null) {
|
||||
parmVar = myTypeVariableFactory.create();
|
||||
mapping.put(aTypeParm, parmVar);
|
||||
}
|
||||
|
||||
subst = subst.put(aTypeParm, parmVar);
|
||||
}
|
||||
|
||||
final PsiType bnd = Util.substituteType(bound, subst);
|
||||
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(bnd, var);
|
||||
}
|
||||
else {
|
||||
system.addSubtypeConstraint(var, bnd);
|
||||
}
|
||||
|
||||
theSubst = theSubst.put(p, var);
|
||||
}
|
||||
else {
|
||||
theSubst = theSubst.put(p, pType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
theSubst = theSubst.put(p, introduceAdditionalTypeVariables(pType, qualifier, supertype));
|
||||
}
|
||||
for (int j = 0; j < extypes.length; j++) {
|
||||
final PsiType extype = Util.substituteType(extypes[j], qualifier);
|
||||
system.addSubtypeConstraint(pv, extype);
|
||||
}
|
||||
|
||||
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
|
||||
return pv;
|
||||
}
|
||||
|
||||
return type;
|
||||
final Map<PsiTypeParameter, PsiType> substitutionMap = result.getSubstitutor().getSubstitutionMap();
|
||||
|
||||
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (Iterator<PsiTypeParameter> t = substitutionMap.keySet().iterator(); t.hasNext();) {
|
||||
final PsiTypeParameter p = t.next();
|
||||
final PsiType pType = substitutionMap.get(p);
|
||||
|
||||
if (pType instanceof PsiWildcardType) {
|
||||
final PsiWildcardType wildcard = ((PsiWildcardType)pType);
|
||||
final PsiType theBound = wildcard.getBound();
|
||||
|
||||
if (theBound != null) {
|
||||
final PsiType bound = Util.substituteType(Util.substituteType(theBound, supertype), qualifier);
|
||||
|
||||
if (Util.bindsTypeVariables(bound)) {
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(bound, var);
|
||||
}
|
||||
else {
|
||||
system.addSubtypeConstraint(var, bound);
|
||||
}
|
||||
|
||||
theSubst = theSubst.put(p, var);
|
||||
}
|
||||
else if (Util.bindsTypeParameters(bound, typeParameters)) {
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (int i = 0; i < aTypeParms.length; i++) {
|
||||
final PsiTypeParameter aTypeParm = aTypeParms[i];
|
||||
|
||||
PsiType parmVar = mapping.get(aTypeParm);
|
||||
|
||||
if (parmVar == null) {
|
||||
parmVar = myTypeVariableFactory.create();
|
||||
mapping.put(aTypeParm, parmVar);
|
||||
}
|
||||
|
||||
subst = subst.put(aTypeParm, parmVar);
|
||||
}
|
||||
|
||||
final PsiType bnd = Util.substituteType(bound, subst);
|
||||
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(bnd, var);
|
||||
}
|
||||
else {
|
||||
system.addSubtypeConstraint(var, bnd);
|
||||
}
|
||||
|
||||
theSubst = theSubst.put(p, var);
|
||||
}
|
||||
else {
|
||||
theSubst = theSubst.put(p, pType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
theSubst = theSubst.put(p, introduceAdditionalTypeVariables(pType, qualifier, supertype));
|
||||
}
|
||||
}
|
||||
|
||||
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
|
||||
}
|
||||
}.introduceAdditionalTypeVariables(
|
||||
Util.substituteType(Util.substituteType(parmType, supertypeSubstitutor), qualifierSubstitutor), qualifierSubstitutor,
|
||||
supertypeSubstitutor);
|
||||
|
||||
return type;
|
||||
}
|
||||
}.introduceAdditionalTypeVariables(
|
||||
Util.substituteType(Util.substituteType(parmType, supertypeSubstitutor), qualifierSubstitutor), qualifierSubstitutor,
|
||||
supertypeSubstitutor);
|
||||
|
||||
system.addSubtypeConstraint(argumenType, theType);
|
||||
}
|
||||
@@ -575,6 +598,24 @@ public class SystemBuilder {
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
final PsiType reType = getType(element);
|
||||
|
||||
element.accept(new PsiRecursiveElementVisitor() {
|
||||
public void visitReturnStatement(final PsiReturnStatement statement) {
|
||||
super.visitReturnStatement(statement);
|
||||
|
||||
final PsiExpression retExpr = statement.getReturnValue();
|
||||
|
||||
if (retExpr != null) {
|
||||
system.addSubtypeConstraint(e.valuateType(retExpr), reType);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiStatement root = (PsiStatement)PsiTreeUtil.getParentOfType(element, PsiStatement.class);
|
||||
|
||||
@@ -583,63 +624,65 @@ public class SystemBuilder {
|
||||
|
||||
if (!myVisitedConstructions.contains(anchor)) {
|
||||
root.accept(new PsiRecursiveElementVisitor() {
|
||||
public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
public void visitAssignmentExpression(final PsiAssignmentExpression expression) {
|
||||
super.visitAssignmentExpression(expression);
|
||||
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getRExpression()), e.valuateType(expression.getLExpression()));
|
||||
}
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getRExpression()), e.valuateType(expression.getLExpression()));
|
||||
}
|
||||
|
||||
public void visitConditionalExpression(final PsiConditionalExpression expression) {
|
||||
super.visitConditionalExpression(expression);
|
||||
public void visitConditionalExpression(final PsiConditionalExpression expression) {
|
||||
super.visitConditionalExpression(expression);
|
||||
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getThenExpression()), e.valuateType(expression.getElseExpression()));
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getElseExpression()), e.valuateType(expression.getThenExpression()));
|
||||
}
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getThenExpression()),
|
||||
e.valuateType(expression.getElseExpression()));
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getElseExpression()),
|
||||
e.valuateType(expression.getThenExpression()));
|
||||
}
|
||||
|
||||
public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
e.valuateType(expression);
|
||||
}
|
||||
public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
e.valuateType(expression);
|
||||
}
|
||||
|
||||
public void visitReturnStatement(final PsiReturnStatement statement) {
|
||||
super.visitReturnStatement(statement);
|
||||
public void visitReturnStatement(final PsiReturnStatement statement) {
|
||||
super.visitReturnStatement(statement);
|
||||
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(statement, PsiMethod.class);
|
||||
|
||||
if (method != null) {
|
||||
system.addSubtypeConstraint(e.valuateType(statement.getReturnValue()), getType(method));
|
||||
}
|
||||
}
|
||||
if (method != null) {
|
||||
system.addSubtypeConstraint(e.valuateType(statement.getReturnValue()), getType(method));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTypeCastExpression(final PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
public void visitTypeCastExpression(final PsiTypeCastExpression expression) {
|
||||
super.visitTypeCastExpression(expression);
|
||||
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getOperand()), e.valuateType(expression));
|
||||
}
|
||||
system.addSubtypeConstraint(e.valuateType(expression.getOperand()), e.valuateType(expression));
|
||||
}
|
||||
|
||||
public void visitNewExpression(final PsiNewExpression expression) {
|
||||
super.visitNewExpression(expression);
|
||||
public void visitNewExpression(final PsiNewExpression expression) {
|
||||
super.visitNewExpression(expression);
|
||||
|
||||
final PsiArrayInitializerExpression init = expression.getArrayInitializer();
|
||||
final PsiArrayInitializerExpression init = expression.getArrayInitializer();
|
||||
|
||||
if (init != null) {
|
||||
final PsiExpression[] inits = init.getInitializers();
|
||||
final PsiType type = getType(expression);
|
||||
if (init != null) {
|
||||
final PsiExpression[] inits = init.getInitializers();
|
||||
final PsiType type = getType(expression);
|
||||
|
||||
for (int i = 0; i < inits.length; i++) {
|
||||
system.addSubtypeConstraint(e.valuateType(inits[i]).createArrayType(), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < inits.length; i++) {
|
||||
system.addSubtypeConstraint(e.valuateType(inits[i]).createArrayType(), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitReferenceExpression(final PsiReferenceExpression expression) {
|
||||
final PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||
public void visitReferenceExpression(final PsiReferenceExpression expression) {
|
||||
final PsiExpression qualifierExpression = expression.getQualifierExpression();
|
||||
|
||||
if (qualifierExpression != null) {
|
||||
qualifierExpression.accept(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (qualifierExpression != null) {
|
||||
qualifierExpression.accept(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myVisitedConstructions.add(anchor);
|
||||
}
|
||||
@@ -673,47 +716,47 @@ public class SystemBuilder {
|
||||
if (definedType instanceof PsiTypeVariable) {
|
||||
for (int j = 0; j < extendsList.length; j++) {
|
||||
final PsiType extendsType =
|
||||
new Object() {
|
||||
PsiType replaceWildCards(final PsiType type) {
|
||||
if (type instanceof PsiWildcardType) {
|
||||
final PsiWildcardType wildcard = ((PsiWildcardType)type);
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
final PsiType bound = wildcard.getBound();
|
||||
new Object() {
|
||||
PsiType replaceWildCards(final PsiType type) {
|
||||
if (type instanceof PsiWildcardType) {
|
||||
final PsiWildcardType wildcard = ((PsiWildcardType)type);
|
||||
final PsiType var = myTypeVariableFactory.create();
|
||||
final PsiType bound = wildcard.getBound();
|
||||
|
||||
if (bound != null) {
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(Util.substituteType(replaceWildCards(bound), definedSubst), var);
|
||||
}
|
||||
else {
|
||||
system.addSubtypeConstraint(var, Util.substituteType(replaceWildCards(bound), definedSubst));
|
||||
}
|
||||
if (bound != null) {
|
||||
if (wildcard.isExtends()) {
|
||||
system.addSubtypeConstraint(Util.banalize(Util.substituteType(replaceWildCards(bound), definedSubst)), var);
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
else if (type instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
|
||||
final PsiClass aClass = result.getElement();
|
||||
final PsiSubstitutor aSubst = result.getSubstitutor();
|
||||
|
||||
if (aClass != null) {
|
||||
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (Iterator<PsiTypeParameter> i = aSubst.getSubstitutionMap().keySet().iterator(); i.hasNext();) {
|
||||
final PsiTypeParameter p = i.next();
|
||||
|
||||
theSubst = theSubst.put(p, replaceWildCards(aSubst.substitute(p)));
|
||||
}
|
||||
|
||||
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
|
||||
else {
|
||||
system.addSubtypeConstraint(var, Util.banalize(Util.substituteType(replaceWildCards(bound), definedSubst)));
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
return var;
|
||||
}
|
||||
}.replaceWildCards(extendsList[j]);
|
||||
else if (type instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
|
||||
final PsiClass aClass = result.getElement();
|
||||
final PsiSubstitutor aSubst = result.getSubstitutor();
|
||||
|
||||
system.addSubtypeConstraint(Util.substituteType(extendsType, definedSubst), definedType);
|
||||
if (aClass != null) {
|
||||
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
|
||||
|
||||
for (Iterator<PsiTypeParameter> i = aSubst.getSubstitutionMap().keySet().iterator(); i.hasNext();) {
|
||||
final PsiTypeParameter p = i.next();
|
||||
|
||||
theSubst = theSubst.put(p, replaceWildCards(aSubst.substitute(p)));
|
||||
}
|
||||
|
||||
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}.replaceWildCards(extendsList[j]);
|
||||
|
||||
system.addSubtypeConstraint(definedType, Util.banalize(Util.substituteType(extendsType, definedSubst)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -731,21 +774,17 @@ public class SystemBuilder {
|
||||
System system = new System(myProject, victims, myTypes, myTypeVariableFactory);
|
||||
|
||||
for (Iterator<PsiElement> i = victims.iterator(); i.hasNext();) {
|
||||
PsiElement element = i.next();
|
||||
final PsiElement element = i.next();
|
||||
|
||||
if (element instanceof PsiParameter) {
|
||||
if (!verifyMethod(element, victims, helper)) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
element = myParameters.get(element);
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
if (!verifyMethod(element, victims, helper)) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
element = mySuper.get(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,17 +800,17 @@ public class SystemBuilder {
|
||||
setType(element, definedType = defineType(p));
|
||||
}
|
||||
else {
|
||||
definedType = defineType(element);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
final PsiMethod m = mySuper.get(element);
|
||||
final PsiMethod m = myMethods.get(element);
|
||||
|
||||
if (m != null) {
|
||||
system.addSubtypeConstraint(defineType(element), definedType = defineType(m));
|
||||
}
|
||||
else {
|
||||
definedType = defineType(element);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -784,6 +823,21 @@ public class SystemBuilder {
|
||||
for (Iterator<PsiElement> i = victims.iterator(); i.hasNext();) {
|
||||
final PsiElement element = i.next();
|
||||
|
||||
if (element instanceof PsiParameter) {
|
||||
final PsiParameter p = myParameters.get(element);
|
||||
|
||||
if (p == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (element instanceof PsiMethod) {
|
||||
final PsiMethod m = myMethods.get(element);
|
||||
|
||||
if (m == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
addUsage(system, element);
|
||||
|
||||
if (!(element instanceof PsiExpression)) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.intellij.refactoring.typeCook.deductive.PsiExtendedTypeVisitor;
|
||||
import com.intellij.refactoring.typeCook.Util;
|
||||
import com.intellij.refactoring.typeCook.Bottom;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -13,10 +15,7 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
@@ -33,6 +32,35 @@ public class BindingFactory {
|
||||
private HashSet<PsiTypeVariable> myBoundVariables;
|
||||
private Project myProject;
|
||||
|
||||
private PsiClass[] getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(aClass, bClass, true)) {
|
||||
return new PsiClass[]{aClass};
|
||||
}
|
||||
|
||||
if (InheritanceUtil.isInheritorOrSelf(bClass, aClass, true)) {
|
||||
return new PsiClass[]{bClass};
|
||||
}
|
||||
|
||||
final Set<PsiClass> descendants = new LinkedHashSet<PsiClass>();
|
||||
|
||||
new Object() {
|
||||
public void getGreatestLowerClasses(final PsiClass aClass, final PsiClass bClass, final Set<PsiClass> descendants) {
|
||||
if (aClass.isInheritor(bClass, true)) {
|
||||
descendants.add(bClass);
|
||||
}
|
||||
else {
|
||||
final PsiSearchHelper helper = aClass.getManager().getSearchHelper();
|
||||
final PsiClass[] bSubs = helper.findInheritors(bClass, GlobalSearchScope.allScope(myProject), false);
|
||||
for (int i = 0; i < bSubs.length; i++) {
|
||||
getGreatestLowerClasses(bSubs[i], aClass, descendants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.getGreatestLowerClasses(aClass, bClass, descendants);
|
||||
|
||||
return descendants.toArray(new PsiClass[descendants.size()]);
|
||||
}
|
||||
|
||||
private class BindingImpl extends Binding {
|
||||
private PsiType[] myBindings;
|
||||
private boolean myCyclic;
|
||||
@@ -107,35 +135,35 @@ public class BindingFactory {
|
||||
final int flag = (b1i == null ? 0 : 1) + (b2i == null ? 0 : 2);
|
||||
|
||||
switch (flag) {
|
||||
case 0:
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1: /* b1(i)\b2(i) */
|
||||
{
|
||||
final PsiType type = b2.apply(b1i);
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
}
|
||||
break;
|
||||
case 1: /* b1(i)\b2(i) */
|
||||
{
|
||||
final PsiType type = b2.apply(b1i);
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* b2(i)\b1(i) */
|
||||
{
|
||||
final PsiType type = b1.apply(b2i);
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
}
|
||||
break;
|
||||
case 2: /* b2(i)\b1(i) */
|
||||
{
|
||||
final PsiType type = b1.apply(b2i);
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: /* b2(i) \cap b1(i) */
|
||||
final Binding common = rise(b1i, b2i);
|
||||
case 3: /* b2(i) \cap b1(i) */
|
||||
final Binding common = rise(b1i, b2i);
|
||||
|
||||
if (common == null) {
|
||||
return null;
|
||||
}
|
||||
if (common == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiType type = b2.apply(common.apply(b1i));
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
final PsiType type = b2.apply(common.apply(b1i));
|
||||
b3.myBindings[i] = type;
|
||||
b3.myCyclic = type instanceof PsiTypeVariable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +185,7 @@ public class BindingFactory {
|
||||
}
|
||||
|
||||
private PsiType normalize(final PsiType t) {
|
||||
if (t == null || t instanceof PsiTypeVariable){
|
||||
if (t == null || t instanceof PsiTypeVariable) {
|
||||
return Bottom.BOTTOM;
|
||||
}
|
||||
|
||||
@@ -234,12 +262,40 @@ public class BindingFactory {
|
||||
}
|
||||
|
||||
if (kindX != kindY) {
|
||||
if (kindX == 4){
|
||||
if (kindX == 4) {
|
||||
return Binding.WORSE;
|
||||
}
|
||||
|
||||
if (kindY == 4){
|
||||
return Binding.BETTER;
|
||||
if (kindY == 4) {
|
||||
return Binding.BETTER;
|
||||
}
|
||||
|
||||
if (kindX + kindY == 5) {
|
||||
try {
|
||||
final PsiElementFactory f = PsiManager.getInstance(myProject).getElementFactory();
|
||||
final PsiType cloneable = f.createTypeFromText("java.lang.Cloneable", null);
|
||||
final PsiType object = f.createTypeFromText("java.lang.Object", null);
|
||||
final PsiType serializable = f.createTypeFromText("java.io.Serializable", null);
|
||||
|
||||
PsiType type = null;
|
||||
int flag = 0;
|
||||
|
||||
if (kindX == 3) {
|
||||
type = x;
|
||||
flag = Binding.WORSE;
|
||||
}
|
||||
else {
|
||||
type = y;
|
||||
flag = Binding.BETTER;
|
||||
}
|
||||
|
||||
if (type.equals(object) || type.equals(cloneable) || type.equals(serializable)) {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Binding.NONCOMPARABLE;
|
||||
@@ -351,7 +407,7 @@ public class BindingFactory {
|
||||
final PsiType type = binding.myBindings[i];
|
||||
|
||||
if (type == null) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
final int index = i;
|
||||
@@ -393,78 +449,164 @@ public class BindingFactory {
|
||||
Binding typeVar(PsiType x, PsiTypeVariable y);
|
||||
}
|
||||
|
||||
interface Unifier {
|
||||
Binding unify(PsiType x, PsiType y);
|
||||
}
|
||||
|
||||
public Binding balance(final PsiType x, final PsiType y, final Balancer balancer) {
|
||||
final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);
|
||||
|
||||
switch (indicator) {
|
||||
case 0:
|
||||
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
|
||||
final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType)x).getBound() : x;
|
||||
final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType)y).getBound() : y;
|
||||
case 0:
|
||||
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
|
||||
final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType)x).getBound() : x;
|
||||
final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType)y).getBound() : y;
|
||||
|
||||
return balance(xType, yType, balancer);
|
||||
}
|
||||
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
|
||||
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
|
||||
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
|
||||
return balance(xType, yType, balancer);
|
||||
}
|
||||
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
|
||||
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
|
||||
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
|
||||
|
||||
return balance(xType, yType, balancer);
|
||||
}
|
||||
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
|
||||
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
|
||||
return balance(xType, yType, balancer);
|
||||
}
|
||||
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
|
||||
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
|
||||
|
||||
final PsiClass xClass = resultX.getElement();
|
||||
final PsiClass yClass = resultY.getElement();
|
||||
final PsiClass xClass = resultX.getElement();
|
||||
final PsiClass yClass = resultY.getElement();
|
||||
|
||||
if (xClass != null && yClass != null) {
|
||||
final PsiSubstitutor ySubst = resultY.getSubstitutor();
|
||||
if (xClass != null && yClass != null) {
|
||||
final PsiSubstitutor ySubst = resultY.getSubstitutor();
|
||||
|
||||
PsiSubstitutor xSubst = resultX.getSubstitutor();
|
||||
PsiSubstitutor xSubst = resultX.getSubstitutor();
|
||||
|
||||
if (!xClass.equals(yClass)) {
|
||||
if (InheritanceUtil.isCorrectDescendant(xClass, yClass, true)) {
|
||||
xSubst = TypeConversionUtil.getSuperClassSubstitutor(yClass, xClass, xSubst);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!xClass.equals(yClass)) {
|
||||
if (InheritanceUtil.isCorrectDescendant(xClass, yClass, true)) {
|
||||
xSubst = TypeConversionUtil.getSuperClassSubstitutor(yClass, xClass, xSubst);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Binding b = create();
|
||||
Binding b = create();
|
||||
|
||||
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
|
||||
final PsiTypeParameter aParm = p.next();
|
||||
final PsiType xType = xSubst.substitute(aParm);
|
||||
final PsiType yType = ySubst.substitute(aParm);
|
||||
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
|
||||
final PsiTypeParameter aParm = p.next();
|
||||
final PsiType xType = xSubst.substitute(aParm);
|
||||
final PsiType yType = ySubst.substitute(aParm);
|
||||
|
||||
final Binding b1 = balance(xType, yType, balancer);
|
||||
final Binding b1 = unify(xType, yType, new Unifier() {
|
||||
public Binding unify(final PsiType x, final PsiType y) {
|
||||
return balance(x, y, balancer);
|
||||
}
|
||||
});
|
||||
|
||||
if (b1 == null) {
|
||||
return null;
|
||||
}
|
||||
if (b1 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
b = b.compose(b1);
|
||||
}
|
||||
b = b.compose(b1);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
}
|
||||
else if (x instanceof Bottom || y instanceof Bottom) {
|
||||
return create();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
else if (y instanceof Bottom) {
|
||||
return create();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
case 1:
|
||||
return balancer.varType((PsiTypeVariable)x, y);
|
||||
case 1:
|
||||
return balancer.varType((PsiTypeVariable)x, y);
|
||||
|
||||
case 2:
|
||||
return balancer.typeVar(x, (PsiTypeVariable)y);
|
||||
case 2:
|
||||
return balancer.typeVar(x, (PsiTypeVariable)y);
|
||||
|
||||
case 3:
|
||||
return balancer.varVar((PsiTypeVariable)x, (PsiTypeVariable)y);
|
||||
case 3:
|
||||
return balancer.varVar((PsiTypeVariable)x, (PsiTypeVariable)y);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Binding unify(final PsiType x, final PsiType y, final Unifier unifier) {
|
||||
final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0);
|
||||
|
||||
switch (indicator) {
|
||||
case 0:
|
||||
if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
|
||||
return unifier.unify(x, y);
|
||||
}
|
||||
else if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
|
||||
final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType)x).getComponentType() : x;
|
||||
final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType)y).getComponentType() : y;
|
||||
|
||||
return unify(xType, yType, unifier);
|
||||
}
|
||||
else if (x instanceof PsiClassType && y instanceof PsiClassType) {
|
||||
final PsiClassType.ClassResolveResult resultX = Util.resolveType(x);
|
||||
final PsiClassType.ClassResolveResult resultY = Util.resolveType(y);
|
||||
|
||||
final PsiClass xClass = resultX.getElement();
|
||||
final PsiClass yClass = resultY.getElement();
|
||||
|
||||
if (xClass != null && yClass != null) {
|
||||
final PsiSubstitutor ySubst = resultY.getSubstitutor();
|
||||
|
||||
PsiSubstitutor xSubst = resultX.getSubstitutor();
|
||||
|
||||
if (!xClass.equals(yClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Binding b = create();
|
||||
|
||||
for (Iterator<PsiTypeParameter> p = xSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
|
||||
final PsiTypeParameter aParm = p.next();
|
||||
final PsiType xType = xSubst.substitute(aParm);
|
||||
final PsiType yType = ySubst.substitute(aParm);
|
||||
|
||||
final Binding b1 = unify(xType, yType, unifier);
|
||||
|
||||
if (b1 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
b = b.compose(b1);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
}
|
||||
else if (y instanceof Bottom) {
|
||||
return create();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
case 1:
|
||||
return create((PsiTypeVariable)x, y);
|
||||
|
||||
case 2:
|
||||
return create((PsiTypeVariable)y, x);
|
||||
|
||||
case 3:
|
||||
{
|
||||
final PsiTypeVariable xVar = ((PsiTypeVariable)x);
|
||||
final PsiTypeVariable yVar = ((PsiTypeVariable)y);
|
||||
|
||||
if (xVar.getIndex() == yVar.getIndex()) {
|
||||
return create();
|
||||
}
|
||||
|
||||
return xVar.getIndex() < yVar.getIndex() ? create(xVar, y) : create(yVar, x);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -472,47 +614,45 @@ public class BindingFactory {
|
||||
|
||||
public Binding rise(final PsiType x, final PsiType y) {
|
||||
return balance(x, y, new Balancer() {
|
||||
public Binding varType(PsiTypeVariable x, PsiType y) {
|
||||
return create(x, y);
|
||||
}
|
||||
|
||||
public Binding varType(PsiTypeVariable x, PsiType y) {
|
||||
return create(x, y);
|
||||
}
|
||||
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
|
||||
final int xi = x.getIndex();
|
||||
final int yi = y.getIndex();
|
||||
|
||||
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
|
||||
final int xi = x.getIndex();
|
||||
final int yi = y.getIndex();
|
||||
if (xi < yi) {
|
||||
return create(((PsiTypeVariable)x), y);
|
||||
}
|
||||
else if (yi < xi) {
|
||||
return create(((PsiTypeVariable)y), x);
|
||||
}
|
||||
else {
|
||||
return create();
|
||||
}
|
||||
}
|
||||
|
||||
if (xi < yi) {
|
||||
return create(((PsiTypeVariable)x), y);
|
||||
}
|
||||
else if (yi < xi) {
|
||||
return create(((PsiTypeVariable)y), x);
|
||||
}
|
||||
else {
|
||||
return create();
|
||||
}
|
||||
}
|
||||
|
||||
public Binding typeVar(PsiType x, PsiTypeVariable y) {
|
||||
return create(y, x);
|
||||
}
|
||||
});
|
||||
public Binding typeVar(PsiType x, PsiTypeVariable y) {
|
||||
return create(y, x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Binding sink(final PsiType x, final PsiType y) {
|
||||
return balance(x, y, new Balancer() {
|
||||
public Binding varType(PsiTypeVariable x, PsiType y) {
|
||||
return create(x, Bottom.BOTTOM);
|
||||
}
|
||||
|
||||
public Binding varType(PsiTypeVariable x, PsiType y) {
|
||||
return create(x, Bottom.BOTTOM);
|
||||
}
|
||||
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
|
||||
return create(x, Bottom.BOTTOM);
|
||||
}
|
||||
|
||||
public Binding varVar(PsiTypeVariable x, PsiTypeVariable y) {
|
||||
return create(x, Bottom.BOTTOM);
|
||||
}
|
||||
|
||||
public Binding typeVar(PsiType x, PsiTypeVariable y) {
|
||||
return create(y, x);
|
||||
}
|
||||
});
|
||||
public Binding typeVar(PsiType x, PsiTypeVariable y) {
|
||||
return create(y, x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LinkedList<Pair<PsiType, Binding>> union(final PsiType x, final PsiType y) {
|
||||
@@ -547,7 +687,7 @@ public class BindingFactory {
|
||||
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
|
||||
}
|
||||
else {
|
||||
final PsiClass[] descendants = GenericsUtil.getGreatestLowerClasses(xClass, yClass);
|
||||
final PsiClass[] descendants = getGreatestLowerClasses(xClass, yClass);
|
||||
|
||||
for (int i = 0; i < descendants.length; i++) {
|
||||
final PsiClass descendant = descendants[i];
|
||||
@@ -613,10 +753,14 @@ public class BindingFactory {
|
||||
final Binding risen = rise(x, y);
|
||||
|
||||
if (risen == null) {
|
||||
return;
|
||||
}
|
||||
final PsiElementFactory factory = xClass.getManager().getElementFactory();
|
||||
|
||||
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
|
||||
list.addFirst(new Pair<PsiType, Binding>(Util.banalize(factory.createType(xClass, factory.createRawSubstitutor(xClass))),
|
||||
create()));
|
||||
}
|
||||
else {
|
||||
list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiClass[] ancestors = GenericsUtil.getLeastUpperClasses(xClass, yClass);
|
||||
@@ -625,7 +769,7 @@ public class BindingFactory {
|
||||
final PsiClass ancestor = ancestors[i];
|
||||
|
||||
if (ancestor.getQualifiedName().equals("java.lang.Object") && ancestors.length > 1) {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
final PsiSubstitutor x2aSubst = TypeConversionUtil.getSuperClassSubstitutor(ancestor, xClass, xSubst);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
class List<T> {
|
||||
T t;
|
||||
}
|
||||
|
||||
class Test{
|
||||
class Super {
|
||||
void f (List x){
|
||||
x = new List<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
x.t = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
class List<T> {
|
||||
T t;
|
||||
}
|
||||
|
||||
class Test{
|
||||
class Super {
|
||||
void f (List x){
|
||||
x = new List<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
x.t = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ class Test{
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
g(x);
|
||||
x.t = "";
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ class Test{
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
g(x);
|
||||
x.t = "";
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,7 @@ class List<T> {
|
||||
}
|
||||
|
||||
class Test{
|
||||
class Super {
|
||||
void f (List x){
|
||||
x = new List<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
x.t = "";
|
||||
}
|
||||
|
||||
List g (){
|
||||
return new List<Integer>();
|
||||
}
|
||||
@@ -21,7 +11,6 @@ class Test{
|
||||
|
||||
class Sub extends Middle{
|
||||
List g (){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,7 @@ class List<T> {
|
||||
}
|
||||
|
||||
class Test{
|
||||
class Super {
|
||||
void f (List x){
|
||||
x = new List<Integer>();
|
||||
}
|
||||
}
|
||||
|
||||
class Middle extends Super {
|
||||
void f (List x){
|
||||
x.t = "";
|
||||
}
|
||||
|
||||
List g (){
|
||||
return new List<Integer>();
|
||||
}
|
||||
@@ -21,7 +11,6 @@ class Test{
|
||||
|
||||
class Sub extends Middle{
|
||||
List g (){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user