From b81f8bb7c8801e5b81460b67e2eb2e0b1ee79aee Mon Sep 17 00:00:00 2001 From: Dmitri Boulytchev Date: Sat, 5 Feb 2005 22:41:53 +0300 Subject: [PATCH] Typecook tests passed --- .../intellij/refactoring/typeCook/Util.java | 74 +++--- .../deductive/builder/SystemBuilder.java | 214 ++++++++++++------ .../refactoring/typeCook/t130/after/test.java | 2 +- .../typeCook/t130/before/test.java | 2 +- .../intellij/refactoring/TypeCookTest.java | 53 ++++- 5 files changed, 240 insertions(+), 105 deletions(-) diff --git a/source/com/intellij/refactoring/typeCook/Util.java b/source/com/intellij/refactoring/typeCook/Util.java index f3f23396e842..d2107422561f 100644 --- a/source/com/intellij/refactoring/typeCook/Util.java +++ b/source/com/intellij/refactoring/typeCook/Util.java @@ -233,7 +233,7 @@ public class Util { final PsiClassType.ClassResolveResult result = resolveType(t); final PsiClass theClass = result.getElement(); - if (theClass == null){ + if (theClass == null) { return t; } @@ -242,7 +242,7 @@ public class Util { PsiSubstitutor subst = PsiSubstitutor.EMPTY; - for (final Iterator p=theSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();){ + for (final Iterator p = theSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) { final PsiTypeParameter theParm = p.next(); final PsiType actualType = theSubst.substitute(theParm); @@ -262,7 +262,7 @@ public class Util { return theManager.getElementFactory().createType(theClass, subst); } - else if (t instanceof PsiArrayType){ + else if (t instanceof PsiArrayType) { return banalize(((PsiArrayType)t).getComponentType()).createArrayType(); } @@ -391,7 +391,7 @@ public class Util { return aClass.getManager().getElementFactory() .createType(aClass); } - ; + ; return PsiType.getJavaLangObject(aClass.getManager()); } @@ -630,7 +630,7 @@ public class Util { for (int i = 0; i < parms.length; i++) { max = Math.max(max, getHeight(aSubst.substitute(parms[i]))); if (max > HEIGHT_BOUND) { - break; + break; } } @@ -671,14 +671,14 @@ public class Util { final PsiTypeParameter parm = i.next(); final PsiType type = createParameterizedType(aSubst.substitute(parm), factory); - if (type instanceof PsiTypeVariable){ + if (type instanceof PsiTypeVariable) { cluster.add((PsiTypeVariable)type); } theSubst = theSubst.put(parm, type); } - if (cluster.size() > 1){ + if (cluster.size() > 1) { factory.registerCluster(cluster); } @@ -692,33 +692,53 @@ public class Util { } public static PsiType substituteType(final PsiType type, final PsiSubstitutor subst) { - final int level = getArrayLevel(type); - final PsiClassType.ClassResolveResult result = resolveType(type); + if (type instanceof PsiWildcardType) { + final PsiWildcardType wcType = ((PsiWildcardType)type); + final PsiType bound = wcType.getBound(); - if (result.getElement() != null) { - final PsiClass aClass = result.getElement(); - final PsiSubstitutor aSubst = result.getSubstitutor(); - final PsiManager manager = aClass.getManager(); + if (bound != null) { + final PsiClass aClass = resolveType(bound).getElement(); - if (aClass instanceof PsiTypeParameter) { - final PsiType sType = subst.substitute(((PsiTypeParameter)aClass)); + if (aClass != null) { + final PsiManager manager = aClass.getManager(); - return createArrayType(sType == null ? PsiType.getJavaLangObject(manager) : sType, level); + return wcType.isExtends() + ? PsiWildcardType.createExtends(manager, substituteType(bound, subst)) + : PsiWildcardType.createSuper(manager, substituteType(bound, subst)); + } } - final PsiTypeParameter[] aParms = getTypeParametersList(aClass); - PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; - - for (int i = 0; i < aParms.length; i++) { - PsiTypeParameter aParm = aParms[i]; - - theSubst = theSubst.put(aParm, substituteType(aSubst.substitute(aParm), subst)); - } - - return createArrayType(aClass.getManager().getElementFactory().createType(aClass, theSubst), level); + return type; } + else { + final int level = getArrayLevel(type); + final PsiClassType.ClassResolveResult result = resolveType(type); + final PsiClass aClass = result.getElement(); - return createArrayType(type, level); + if (aClass != null) { + final PsiSubstitutor aSubst = result.getSubstitutor(); + final PsiManager manager = aClass.getManager(); + + if (aClass instanceof PsiTypeParameter) { + final PsiType sType = subst.substitute(((PsiTypeParameter)aClass)); + + return createArrayType(sType == null ? PsiType.getJavaLangObject(manager) : sType, level); + } + + final PsiTypeParameter[] aParms = getTypeParametersList(aClass); + PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; + + for (int i = 0; i < aParms.length; i++) { + PsiTypeParameter aParm = aParms[i]; + + theSubst = theSubst.put(aParm, substituteType(aSubst.substitute(aParm), subst)); + } + + return createArrayType(aClass.getManager().getElementFactory().createType(aClass, theSubst), level); + } + + return createArrayType(type, level); + } } public static boolean bindsTypeVariables(final PsiType t) { diff --git a/source/com/intellij/refactoring/typeCook/deductive/builder/SystemBuilder.java b/source/com/intellij/refactoring/typeCook/deductive/builder/SystemBuilder.java index 6f91200e3896..14ad4db0a92b 100644 --- a/source/com/intellij/refactoring/typeCook/deductive/builder/SystemBuilder.java +++ b/source/com/intellij/refactoring/typeCook/deductive/builder/SystemBuilder.java @@ -233,8 +233,8 @@ public class SystemBuilder { else if (expr instanceof PsiAssignmentExpression) { return evaluateType(((PsiAssignmentExpression)expr).getLExpression()); } - else if (expr instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression call = ((PsiMethodCallExpression)expr); + else if (expr instanceof PsiCallExpression) { + final PsiCallExpression call = ((PsiCallExpression)expr); final PsiMethod method = call.resolveMethod(); if (method != null) { @@ -242,8 +242,9 @@ public class SystemBuilder { final PsiTypeParameter[] aTypeParms = method.getTypeParameterList().getTypeParameters(); final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiExpression[] arguments = call.getArgumentList().getExpressions(); - final PsiExpression aQualifier = call.getMethodExpression().getQualifierExpression(); - final PsiExpression[] actualParms = call.getArgumentList().getExpressions(); + final PsiExpression aQualifier = expr instanceof PsiMethodCallExpression + ? ((PsiMethodCallExpression)expr).getMethodExpression().getQualifierExpression() + : null; final HashSet typeParameters = new HashSet(); for (int i = 0; i < aTypeParms.length; i++) { @@ -253,8 +254,31 @@ public class SystemBuilder { PsiSubstitutor qualifierSubstitutor = PsiSubstitutor.EMPTY; PsiSubstitutor supertypeSubstitutor = PsiSubstitutor.EMPTY; - final PsiType rType = myTypes.get(method); - PsiType aType = rType != null ? rType : method.getReturnType(); + PsiType aType = null; + + if (method.isConstructor()) { + if (isCooked(expr)) { + aType = getType(expr); + + qualifierSubstitutor = Util.resolveType(aType).getSubstitutor(); + } + else { + final PsiClass cClass = method.getContainingClass(); + final PsiTypeParameter[] classParms = Util.getTypeParametersList(cClass); + + for (int i = 0; i < classParms.length; i++) { + final PsiTypeParameter classParm = classParms[i]; + final PsiTypeVariable var = myTypeVariableFactory.create(); + + qualifierSubstitutor = qualifierSubstitutor.put(classParm, var); + } + + aType = myManager.getElementFactory().createType(method.getContainingClass(), qualifierSubstitutor); + } + } + else { + aType = getType(method); + } if (aQualifier != null) { final PsiType qualifierType = evaluateType(aQualifier); @@ -289,17 +313,26 @@ public class SystemBuilder { for (int i = 0; i < Math.min(parameters.length, arguments.length); i++) { final PsiType argumenType = evaluateType(arguments[i]); - final PsiType parmType = getType(parameters[i]); + + PsiType parmType = null; if (isCooked(parameters[i])) { + parmType = getType(parameters[i]); system.addSubtypeConstraint(argumenType, parmType); } else { + parmType = Util.substituteType(Util.substituteType(parameters[i].getType(), supertypeSubstitutor), qualifierSubstitutor); + + if (!Util.bindsTypeVariables(parmType)) { + parmType = Util.banalize(parmType); + } + final PsiType theType = new Object() { PsiType introduceAdditionalTypeVariables(final PsiType type, final PsiSubstitutor qualifier, final PsiSubstitutor supertype) { + final int level = Util.getArrayLevel(type); final PsiClassType.ClassResolveResult result = Util.resolveType(type); final PsiClass aClass = result.getElement(); @@ -316,11 +349,52 @@ public class SystemBuilder { } for (int j = 0; j < extypes.length; j++) { - final PsiType extype = Util.substituteType(extypes[j], qualifier); + final PsiClassType ext = extypes[j]; + final PsiType extype = Util.substituteType(new Object() { + public PsiType substitute(final PsiType ext) { + final PsiClassType.ClassResolveResult result = + Util.resolveType(ext); + final PsiClass aClass = result.getElement(); + + if (aClass != null) { + if (aClass instanceof PsiTypeParameter) { + final PsiType type = mapping.get(aClass); + + if (type != null) { + return type; + } + + return ext; + } + + final PsiSubstitutor aSubst = result.getSubstitutor(); + PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; + + for (final Iterator p = + aSubst.getSubstitutionMap().keySet().iterator(); + p.hasNext();) { + final PsiTypeParameter parm = p.next(); + + PsiType type = aSubst.substitute(parm); + + if (type != null) { + type = substitute(type); + } + + theSubst = theSubst.put(parm, type); + } + + return aClass.getManager().getElementFactory() + .createType(aClass, theSubst); + } + + return ext; + } + }.substitute(ext), qualifier); system.addSubtypeConstraint(pv, extype); } - return pv; + return Util.createArrayType(pv, level); } final Map substitutionMap = result.getSubstitutor().getSubstitutionMap(); @@ -342,10 +416,10 @@ public class SystemBuilder { final PsiType var = myTypeVariableFactory.create(); if (wildcard.isExtends()) { - system.addSubtypeConstraint(bound, var); + system.addSubtypeConstraint(var, bound); } else { - system.addSubtypeConstraint(var, bound); + system.addSubtypeConstraint(bound, var); } theSubst = theSubst.put(p, var); @@ -388,68 +462,69 @@ public class SystemBuilder { } } - return aClass.getManager().getElementFactory().createType(aClass, theSubst); + return Util.createArrayType(aClass.getManager().getElementFactory().createType(aClass, theSubst), level); } - return type; + return Util.createArrayType(type, level); } - }.introduceAdditionalTypeVariables( - Util.substituteType(Util.substituteType(parmType, supertypeSubstitutor), qualifierSubstitutor), qualifierSubstitutor, - supertypeSubstitutor); + }.introduceAdditionalTypeVariables(parmType, qualifierSubstitutor, supertypeSubstitutor); system.addSubtypeConstraint(argumenType, theType); } - new Object() { - private void update(final PsiTypeParameter p, final PsiType t) { - final PsiType binding = mapping.get(p); + //new Object() { + // private void update(final PsiTypeParameter p, final PsiType t) { + // final PsiType binding = mapping.get(p); + // + // if (binding == null) { + // mapping.put(p, t); + // } + // else if (t != null) { + // mapping.put(p, new PsiTypeIntersection(binding, t)); + // } + // } - if (binding == null) { - mapping.put(p, t); - } - else if (t != null) { - mapping.put(p, new PsiTypeIntersection(binding, t)); - } - } - - void bindTypeParameters(final PsiType formal, final PsiType actual) { - final PsiClassType.ClassResolveResult resultF = Util.resolveType(formal); - - if (resultF.getElement() != null) { - final PsiClass classF = resultF.getElement(); - - if (classF instanceof PsiTypeParameter) { - update((PsiTypeParameter)classF, actual); - return; - } - - final PsiClassType.ClassResolveResult resultA = Util.resolveType(actual); - - if (resultA.getElement() == null) { - return; - } - - final PsiClass classA = resultA.getElement(); - - if (!classA.equals(classF)) { - final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(classF, classA, - PsiSubstitutor.EMPTY); - final PsiType aligned = classF.getManager().getElementFactory().createType(classF, superClassSubstitutor); - - bindTypeParameters(formal, Util.substituteType(aligned, resultA.getSubstitutor())); - } - - final PsiTypeParameter[] typeParms = Util.getTypeParametersList(classA); - final PsiSubstitutor substA = resultA.getSubstitutor(); - final PsiSubstitutor substF = resultF.getSubstitutor(); - - for (int i = 0; i < typeParms.length; i++) { - PsiTypeParameter typeParm = typeParms[i]; - bindTypeParameters(substF.substitute(typeParm), substA.substitute(typeParm)); - } - } - } - }.bindTypeParameters(parmType, evaluateType(actualParms[i])); + // void bindTypeParameters(final PsiType formal, PsiType actual) { + // final PsiClassType.ClassResolveResult resultF = Util.resolveType(formal); + // final PsiClass classF = resultF.getElement(); + // + // if (actual instanceof PsiArrayType){ + // actual = ((PsiArrayType)actual).getDeepComponentType(); + // } + // + // if (classF != null) { + // if (classF instanceof PsiTypeParameter) { + // update((PsiTypeParameter)classF, actual); + // return; + // } + // + // final PsiClassType.ClassResolveResult resultA = Util.resolveType(actual); + // + // if (resultA.getElement() == null) { + // return; + // } + // + // final PsiClass classA = resultA.getElement(); + // + // if (!classA.equals(classF)) { + // final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(classF, classA, + // PsiSubstitutor.EMPTY); + // final PsiType aligned = classF.getManager().getElementFactory().createType(classF, superClassSubstitutor); + // + // bindTypeParameters(formal, Util.substituteType(aligned, resultA.getSubstitutor())); + // } + // + // final PsiTypeParameter[] typeParms = Util.getTypeParametersList(classA); + // final PsiSubstitutor substA = resultA.getSubstitutor(); + // final PsiSubstitutor substF = resultF.getSubstitutor(); + // + // for (int i = 0; i < typeParms.length; i++) { + // PsiTypeParameter typeParm = typeParms[i]; + // bindTypeParameters(substF.substitute(typeParm), substA.substitute(typeParm)); + // } + // } + // } + //}.bindTypeParameters(parmType, evaluateType(actualParms[i])); } PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; @@ -639,8 +714,13 @@ public class SystemBuilder { e.valuateType(expression.getThenExpression())); } - public void visitMethodCallExpression(final PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); + //public void visitMethodCallExpression(final PsiMethodCallExpression expression) { + // super.visitMethodCallExpression(expression); + // e.valuateType(expression); + //} + + public void visitCallExpression(final PsiCallExpression expression) { + super.visitCallExpression(expression); e.valuateType(expression); } diff --git a/testData/refactoring/typeCook/t130/after/test.java b/testData/refactoring/typeCook/t130/after/test.java index 6f5d6d3f488f..1a7db4f9d1cd 100644 --- a/testData/refactoring/typeCook/t130/after/test.java +++ b/testData/refactoring/typeCook/t130/after/test.java @@ -20,6 +20,6 @@ public class Test { private static void f(Map requestMap) { ArrayList requests = (ArrayList)requestMap.get(new A()); requests.add(new Object()); - f(new Map> ()); + f(new Map> ()); } } diff --git a/testData/refactoring/typeCook/t130/before/test.java b/testData/refactoring/typeCook/t130/before/test.java index 6f5d6d3f488f..1a7db4f9d1cd 100644 --- a/testData/refactoring/typeCook/t130/before/test.java +++ b/testData/refactoring/typeCook/t130/before/test.java @@ -20,6 +20,6 @@ public class Test { private static void f(Map requestMap) { ArrayList requests = (ArrayList)requestMap.get(new A()); requests.add(new Object()); - f(new Map> ()); + f(new Map> ()); } } diff --git a/testSource/com/intellij/refactoring/TypeCookTest.java b/testSource/com/intellij/refactoring/TypeCookTest.java index 6a2593334879..703b590aaafb 100644 --- a/testSource/com/intellij/refactoring/TypeCookTest.java +++ b/testSource/com/intellij/refactoring/TypeCookTest.java @@ -10,6 +10,8 @@ import com.intellij.psi.PsiElement; import com.intellij.refactoring.typeCook.Kitchen; import com.intellij.refactoring.typeCook.Settings; import com.intellij.refactoring.typeCook.deductive.builder.*; +import com.intellij.refactoring.typeCook.deductive.resolver.ResolverTree; +import com.intellij.refactoring.typeCook.deductive.resolver.Binding; import junit.textui.TestRunner; import java.io.File; @@ -615,6 +617,10 @@ public class TypeCookTest extends MultiFileTestCase { // start(); //} + public void testT146() throws Exception { + start(); + } + public void start() throws Exception { doTest(new PerformAction() { public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception { @@ -628,7 +634,9 @@ public class TypeCookTest extends MultiFileTestCase { assertNotNull("Class " + className + " not found", aClass); + SystemBuilder b = new SystemBuilder(aClass.getManager(), SystemBuilder b = new SystemBuilder(aClass.getManager().getProject(), + SystemBuilder b = new SystemBuilder(myPsiManager.getProject(), new Settings() { public boolean dropObsoleteCasts() { return true; @@ -643,17 +651,44 @@ public class TypeCookTest extends MultiFileTestCase { } }); - //final com.intellij.refactoring.typeCook.deductive.builder.System system = b.build(b.collect(new PsiElement[]{aClass})); - // + final com.intellij.refactoring.typeCook.deductive.builder.System commonSystem = b.build(b.collect(new PsiElement[]{aClass})); + + System.out.println("System built:\n" + commonSystem); + + final com.intellij.refactoring.typeCook.deductive.builder.System[] systems = commonSystem.isolate(); + + System.out.println("Systems isolated:\n" + commonSystem); + + com.intellij.refactoring.typeCook.deductive.builder.System system = null; + + for (int i = 0; i < systems.length; i++) { + com.intellij.refactoring.typeCook.deductive.builder.System s = systems[i]; + + if (s != null && system == null) { + System.out.println(s); + system = s; + } + } + + Binding[] bindings = null; + + if (system != null) { + final ResolverTree tree = new ResolverTree(system); + + tree.resolve(); + + bindings = tree.getSolutions(); + } + //System.out.println("" + system); - // + //if (system != null) return; - Kitchen d = new Kitchen(aClass.getManager()); + //Kitchen d = new Kitchen(aClass.getManager()); - d.buildGraph(new PsiElement[]{aClass}); + //d.buildGraph(new PsiElement[]{aClass}); - String itemRepr = d.resultString(); + String itemRepr = system != null ? system.dumpString() : commonSystem.dumpString();// d.resultString(); String itemName = className + ".items"; String patternName = PathManagerEx.getTestDataPath() + getTestRoot() + getTestName(true) + "/after/" + itemName; @@ -679,10 +714,10 @@ public class TypeCookTest extends MultiFileTestCase { LocalFileSystem.getInstance().refreshAndFindFileByIoFile(graFile); - d.analyze(); - d.relax(); + //d.analyze(); + //d.relax(); - itemRepr = d.resultString(); + itemRepr = system != null ? system.dumpResult(bindings) : commonSystem.dumpString(); //d.resultString(); itemName = className + ".1.items"; patternName = PathManagerEx.getTestDataPath() + getTestRoot() + getTestName(true) + "/after/" + itemName;