Type cook finished

This commit is contained in:
Dmitri Boulytchev
2005-02-07 20:25:12 +03:00
parent 248398569f
commit d984e82954
37 changed files with 289 additions and 59 deletions

View File

@@ -8,7 +8,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringImpl;
import com.intellij.refactoring.TypeCookRefactoring;
import com.intellij.refactoring.typeCook.TypeCookProcessor;
import com.intellij.refactoring.typeCook.deductive.TypeCookProcessor;
import java.util.List;

View File

@@ -778,5 +778,71 @@ public class Util {
return false;
}
public static void changeType(final PsiElement element, final PsiType type) {
try {
if (element instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression cast = ((PsiTypeCastExpression)element);
cast.getCastType().replace(cast.getManager().getElementFactory().createTypeElement(type));
}
else if (element instanceof PsiVariable) {
final PsiVariable field = ((PsiVariable)element);
field.normalizeDeclaration();
field.getTypeElement().replace(field.getManager().getElementFactory().createTypeElement(type));
}
else if (element instanceof PsiMethod) {
final PsiMethod method = ((PsiMethod)element);
method.getReturnTypeElement().replace(method.getManager().getElementFactory().createTypeElement(type));
}
else if (element instanceof PsiNewExpression) {
final PsiNewExpression newx = (PsiNewExpression)element;
final PsiClassType.ClassResolveResult result = Util.resolveType(type);
if (result == null) {
return;
}
final PsiSubstitutor subst = result.getSubstitutor();
final PsiTypeParameter[] parms = Util.getTypeParametersList(result.getElement());
if (parms.length >= 0 && subst.substitute(parms[0]) != null) {
PsiJavaCodeReferenceElement classReference = newx.getClassReference();
PsiReferenceParameterList list = null;
if (classReference == null) {
list = newx.getAnonymousClass().getBaseClassReference().getParameterList();
}
else {
list = classReference.getParameterList();
}
if (list == null) {
return;
}
final PsiElementFactory factory = newx.getManager().getElementFactory();
PsiTypeElement[] elements = list.getTypeParameterElements();
for (int i = 0; i < elements.length; i++) {
elements[i].delete();
}
for (int i = 0; i < parms.length; i++) {
PsiType aType = subst.substitute(parms[i]);
list.add(factory.createTypeElement(aType == null ? PsiType.getJavaLangObject(list.getManager()) : aType));
}
}
}
else {
LOG.error ("Unexpected element type " + element.getClass().getName());
}
}
catch (IncorrectOperationException e) {
LOG.error("Incorrect Operation Exception thrown in CastRole.\n");
}
}
}

View File

@@ -0,0 +1,128 @@
package com.intellij.refactoring.typeCook.deductive.builder;
import com.intellij.psi.*;
import com.intellij.refactoring.typeCook.deductive.PsiTypeVariable;
import com.intellij.refactoring.typeCook.deductive.resolver.Binding;
import com.intellij.refactoring.typeCook.Bottom;
import com.intellij.refactoring.typeCook.Util;
import com.intellij.openapi.project.Project;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Iterator;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: Feb 7, 2005
* Time: 7:40:34 PM
* To change this template use File | Settings | File Templates.
*/
public class Result {
final HashSet<PsiElement> myVictims;
final HashMap<PsiElement, PsiType> myTypes;
final Project myProject;
Binding myBinding;
public Result(final System system) {
myVictims = system.myElements;
myTypes = system.myTypes;
myProject = system.myProject;
}
final private PsiType substitute(final PsiType t) {
if (t instanceof PsiWildcardType) {
final PsiWildcardType wcType = (PsiWildcardType)t;
final PsiType bound = wcType.getBound();
if (bound == null) {
return t;
}
final PsiManager manager = PsiManager.getInstance(myProject);
final PsiType subst = substitute(bound);
return wcType.isExtends() ? PsiWildcardType.createExtends(manager, subst) : PsiWildcardType.createSuper(manager, subst);
}
else if (t instanceof PsiTypeVariable) {
final PsiType b = myBinding.apply(t);
if (b instanceof Bottom || b instanceof PsiTypeVariable) {
return null;
}
return substitute(b);
}
else if (t instanceof Bottom) {
return null;
}
else if (t instanceof PsiArrayType) {
return substitute(((PsiArrayType)t).getComponentType()).createArrayType();
}
else if (t instanceof PsiClassType) {
final PsiClassType.ClassResolveResult result = ((PsiClassType)t).resolveGenerics();
final PsiClass aClass = result.getElement();
final PsiSubstitutor aSubst = result.getSubstitutor();
if (aClass == null) {
return t;
}
PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;
for (final Iterator<PsiTypeParameter> p = aSubst.getSubstitutionMap().keySet().iterator(); p.hasNext();) {
final PsiTypeParameter parm = p.next();
final PsiType type = aSubst.substitute(parm);
theSubst = theSubst.put(parm, substitute(type));
}
return aClass.getManager().getElementFactory().createType(aClass, theSubst);
}
else {
return t;
}
}
public void incorporateSolution(final Binding binding) {
if (myBinding == null) {
myBinding = binding;
}
else {
myBinding.merge(binding);
}
}
public PsiType getCookedType(final PsiElement element) {
return substitute(myTypes.get(element));
}
public HashSet<PsiElement> getCookedElements() {
final HashSet<PsiElement> set = new HashSet<PsiElement>();
for (final Iterator<PsiElement> e = myVictims.iterator(); e.hasNext();) {
final PsiElement element = e.next();
final PsiType originalType =
element instanceof PsiMethod
? ((PsiMethod)element).getReturnType()
: element instanceof PsiVariable
? ((PsiVariable)element).getType()
: ((PsiExpression)element).getType();
if (!originalType.equals(getCookedType(element))){
set.add(element);
}
}
return set;
}
public void apply(final HashSet<PsiElement> victims) {
for (final Iterator<PsiElement> e=victims.iterator(); e.hasNext();){
final PsiElement element = e.next();
Util.changeType(element, getCookedType(element));
}
}
}

View File

@@ -54,7 +54,7 @@ public class SystemBuilder {
myTypeVariableFactory = new PsiTypeVariableFactory();
}
public HashSet<PsiElement> collect(final PsiElement[] scopes) {
private HashSet<PsiElement> collect(final PsiElement[] scopes) {
return new VictimCollector(scopes, mySettings).getVictims();
}
@@ -848,6 +848,10 @@ public class SystemBuilder {
}
}
public System build (final PsiElement[] scopes) {
return build(collect(scopes));
}
public System build(final HashSet<PsiElement> victims) {
final PsiSearchHelper helper = myManager.getSearchHelper();

View File

@@ -4,6 +4,8 @@ import com.intellij.psi.PsiType;
import com.intellij.refactoring.typeCook.deductive.PsiTypeVariableFactory;
import com.intellij.refactoring.typeCook.deductive.PsiTypeVariable;
import java.util.HashSet;
/**
* Created by IntelliJ IDEA.
* User: db
@@ -30,4 +32,8 @@ public abstract class Binding {
public abstract Binding reduceRecursive();
public abstract boolean binds(final PsiTypeVariable var);
public abstract void merge (Binding b);
public abstract HashSet<PsiTypeVariable> getBoundVariables ();
}

View File

@@ -450,6 +450,24 @@ public class BindingFactory {
public boolean binds(final PsiTypeVariable var) {
return myBindings[var.getIndex()] != null;
}
public void merge(Binding b) {
for (final Iterator<PsiTypeVariable> v=b.getBoundVariables().iterator(); v.hasNext();){
final PsiTypeVariable var = v.next();
final int index = var.getIndex();
if (myBindings[index] != null){
LOG.error ("Oops... Binding conflict...");
}
else {
myBindings[index] = b.apply(var);
}
}
}
public HashSet<PsiTypeVariable> getBoundVariables() {
return myBoundVariables;
}
}
interface Balancer {

View File

@@ -1 +1 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x

View File

@@ -1 +1 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x

View File

@@ -1,2 +1,2 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x
LinkedList<Simple>\nPsiField:y

View File

@@ -1,2 +1,2 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x
LinkedList<java.lang.Object>\nPsiField:y

View File

@@ -1,2 +1,2 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x
LinkedList<Simple>\nPsiField:y

View File

@@ -1 +1 @@
List\nPsiLocalVariable:y
List<java.lang.String>\nPsiLocalVariable:y

View File

@@ -1,2 +1,2 @@
A\nPsiLocalVariable:a
List\nPsiLocalVariable:y
List<java.lang.String>\nPsiLocalVariable:y

View File

@@ -1 +1 @@
Collection\nparameter 0 of g
Collection<B>\nparameter 0 of g

View File

@@ -0,0 +1,2 @@
Collection<B>\nparameter 0 of g
Set<B>\nPsiLocalVariable:x

View File

@@ -0,0 +1,2 @@
Collection\nparameter 0 of g
Set\nPsiLocalVariable:x

View File

@@ -1,3 +1,3 @@
LinkedList<LinkedList>\nPsiField:y
LinkedList<? extends LinkedList>\nPsiField:y
LinkedList\nPsiField:x
LinkedList\nPsiTypeCastExpression:(LinkedList) y.get()

View File

@@ -1,3 +1,3 @@
List<java.lang.Object>\nPsiLocalVariable:requests
List<java.lang.Object>\nPsiTypeCastExpression:(ArrayList)requestMap.get(new A())
ArrayList\nPsiLocalVariable:requests
ArrayList\nPsiTypeCastExpression:(ArrayList)requestMap.get(new A())
Map\nparameter 0 of f

View File

@@ -1,2 +1,2 @@
LinkedList<? extends Simple>\nPsiField:y
LinkedList<Simple>\nPsiField:x
LinkedList<Simple>\nPsiField:y

View File

@@ -1,2 +1,2 @@
LinkedList<Simple>\nPsiField:x
LinkedList<? extends Simple>\nPsiField:x
LinkedList<Simple>\nPsiField:y

View File

@@ -1,3 +1,3 @@
LinkedList<LinkedList>\nPsiField:x
LinkedList<? extends LinkedList>\nPsiField:x
LinkedList<java.lang.Object>\nPsiField:y
LinkedList\nPsiTypeCastExpression:(LinkedList) x.get()

View File

@@ -1,3 +1,3 @@
LinkedList<java.lang.Integer,java.lang.String>\nPsiLocalVariable:y
ListLinked<java.lang.String,java.lang.Integer>\nPsiLocalVariable:x
ListLinked<java.lang.String,java.lang.Integer>\nnew
LinkedList<? extends java.lang.Integer,java.lang.String>\nPsiLocalVariable:y
ListLinked<java.lang.String,? extends java.lang.Integer>\nPsiLocalVariable:x
ListLinked<java.lang.String,? extends java.lang.Integer>\nnew

View File

@@ -1,3 +1,3 @@
LinkedList<java.lang.Integer,java.lang.Object>\nPsiLocalVariable:y
ListLinked<java.lang.Object,java.lang.Integer>\nPsiLocalVariable:x
ListLinked<java.lang.Object,java.lang.Integer>\nnew
LinkedList<? extends java.lang.Integer,java.io.Serializable>\nPsiLocalVariable:y
ListLinked<java.io.Serializable,? extends java.lang.Integer>\nPsiLocalVariable:x
ListLinked<java.io.Serializable,? extends java.lang.Integer>\nnew

View File

@@ -1,3 +1,3 @@
LinkedList<java.lang.Object>\nPsiLocalVariable:y
LinkedList<java.lang.Object>\nnew
LinkedList<java.lang.Object>\nparameter 0 of f
LinkedList<java.io.Serializable>\nPsiLocalVariable:y
LinkedList<java.io.Serializable>\nnew
LinkedList<java.io.Serializable>\nparameter 0 of f

View File

@@ -1,3 +1,3 @@
LinkedList<LinkedList<java.lang.Object>>\nPsiLocalVariable:x
LinkedList<java.lang.Object>\nPsiLocalVariable:y
LinkedList<java.lang.Object>\nPsiLocalVariable:z
LinkedList<LinkedList<java.io.Serializable>>\nPsiLocalVariable:x
LinkedList<java.io.Serializable>\nPsiLocalVariable:y
LinkedList<java.io.Serializable>\nPsiLocalVariable:z

View File

@@ -1,2 +1,2 @@
List<java.lang.String,java.lang.String>\nPsiLocalVariable:x
List<java.lang.String,java.lang.String>\nnew
List\nPsiLocalVariable:x
List\nnew

View File

@@ -1,4 +1,4 @@
List<java.lang.Object>\nPsiLocalVariable:x
List<java.lang.Object>\nPsiLocalVariable:y
List<java.lang.Object>\nnew
List<java.lang.Object>\nnew
List<java.io.Serializable>\nPsiLocalVariable:x
List<java.io.Serializable>\nPsiLocalVariable:y
List<java.io.Serializable>\nnew
List<java.io.Serializable>\nnew

View File

@@ -1,5 +1,5 @@
Iterator<Set<java.lang.String>>\nPsiLocalVariable:i
OfList<Set<java.lang.String>>\nPsiLocalVariable:x
OfList<Set<java.lang.String>>\nnew
Iterator<? extends Set<java.lang.String>>\nPsiLocalVariable:i
OfList<? extends Set<java.lang.String>>\nPsiLocalVariable:x
OfList<? extends Set<java.lang.String>>\nnew
Set<java.lang.String>\nPsiLocalVariable:u
Set<java.lang.String>\nPsiTypeCastExpression:(Set) i.get()

View File

@@ -1,5 +1,5 @@
Iterator<Set<java.lang.String>>\nPsiLocalVariable:i
OfList<Set<java.lang.String>>\nPsiLocalVariable:x
OfList<Set<java.lang.String>>\nnew
Set<java.lang.String>\nPsiLocalVariable:u
Set<java.lang.String>\nPsiTypeCastExpression:(Set) i.get()
Iterator<? extends Set<? extends java.lang.String>>\nPsiLocalVariable:i
OfList<? extends Set<? extends java.lang.String>>\nPsiLocalVariable:x
OfList<? extends Set<? extends java.lang.String>>\nnew
Set<? extends java.lang.String>\nPsiLocalVariable:u
Set<? extends java.lang.String>\nPsiTypeCastExpression:(Set) i.get()

View File

@@ -1,5 +1,5 @@
Iterator<Set<java.lang.String>>\nPsiLocalVariable:i
OfList<Set<java.lang.String>>\nPsiLocalVariable:x
OfList<Set<java.lang.String>>\nnew
Iterator<? extends Set<java.lang.String>>\nPsiLocalVariable:i
OfList<? extends Set<java.lang.String>>\nPsiLocalVariable:x
OfList<? extends Set<java.lang.String>>\nnew
Set<java.lang.String>\nPsiLocalVariable:u
Set<java.lang.String>\nPsiTypeCastExpression:(Set) i.get()

View File

@@ -1,6 +1,6 @@
List<java.lang.Object>[]\nPsiLocalVariable:x
List<java.lang.Object>[]\nnew
List<java.lang.Object>\nPsiLocalVariable:y
List<java.lang.Object>\nPsiLocalVariable:z
List<java.lang.Object>\nnew
List<java.lang.Object>\nnew
List<java.io.Serializable>[]\nPsiLocalVariable:x
List<java.io.Serializable>[]\nnew
List<java.io.Serializable>\nPsiLocalVariable:y
List<java.io.Serializable>\nPsiLocalVariable:z
List<java.io.Serializable>\nnew
List<java.io.Serializable>\nnew

View File

@@ -1 +1 @@
List\nPsiLocalVariable:x
List<java.lang.String>\nPsiLocalVariable:x

View File

@@ -1,2 +1,2 @@
List<int[]>\nPsiLocalVariable:x
List<int[]>\nnew
List<? extends int[]>\nPsiLocalVariable:x
List<? extends int[]>\nnew

View File

@@ -0,0 +1,2 @@
List\nparameter 0 of f
List\nparameter 0 of g

View File

@@ -0,0 +1,2 @@
List\nparameter 0 of f
List\nparameter 0 of g

View File

@@ -1,4 +1,4 @@
List<List<java.lang.Object>>\nPsiLocalVariable:x
List<List<java.lang.Object>>\nPsiLocalVariable:y
List<List<java.lang.Object>>\nnew
List<List<java.lang.Object>>\nnew
List<List<java.io.Serializable>>\nPsiLocalVariable:x
List<List<java.io.Serializable>>\nPsiLocalVariable:y
List<List<java.io.Serializable>>\nnew
List<List<java.io.Serializable>>\nnew

View File

@@ -649,7 +649,7 @@ public class TypeCookTest extends MultiFileTestCase {
}
});
final com.intellij.refactoring.typeCook.deductive.builder.System commonSystem = b.build(b.collect(new PsiElement[]{aClass}));
final com.intellij.refactoring.typeCook.deductive.builder.System commonSystem = b.build(new PsiElement[]{aClass});
System.out.println("System built:\n" + commonSystem);