Typecook tests passed

This commit is contained in:
Dmitri Boulytchev
2005-02-05 22:41:53 +03:00
parent 53a3c534cf
commit b81f8bb7c8
5 changed files with 240 additions and 105 deletions
@@ -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<PsiTypeParameter> p=theSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();){
for (final Iterator<PsiTypeParameter> 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) {
@@ -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<PsiTypeParameter> typeParameters = new HashSet<PsiTypeParameter>();
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<PsiTypeParameter> 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<PsiTypeParameter, PsiType> 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);
}
@@ -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<A, List<B>> ());
f(new Map<A, ArrayList<B>> ());
}
}
@@ -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<A, List<B>> ());
f(new Map<A, ArrayList<B>> ());
}
}
@@ -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;