create field from parameter: all erase unavailable type params (IDEA-56163)

This commit is contained in:
unknown
2010-07-01 13:37:08 +04:00
committed by unknown
parent 69db2ce7ef
commit f25abb008c
8 changed files with 110 additions and 36 deletions
@@ -37,16 +37,15 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;
public class CreateFieldFromParameterAction implements IntentionAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction");
@@ -57,15 +56,29 @@ public class CreateFieldFromParameterAction implements IntentionAction {
if (parameter == null) return null;
PsiType type = parameter.getType();
if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType();
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass instanceof PsiTypeParameter && parameter.getDeclarationScope() == ((PsiTypeParameter)psiClass).getOwner()) {
final PsiReferenceList extendsList = psiClass.getExtendsList();
LOG.assertTrue(extendsList != null);
final PsiClassType[] types = extendsList.getReferencedTypes();
if (types.length > 0) return types;
return new PsiType[]{PsiType.getJavaLangObject(parameter.getManager(), GlobalSearchScope.allScope(parameter.getProject()))};
final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type);
final PsiClass psiClass = result.getElement();
if (psiClass == null) return new PsiType[] {type};
final HashSet<PsiTypeParameter> usedTypeParameters = new HashSet<PsiTypeParameter>();
RefactoringUtil.collectTypeParameters(usedTypeParameters, parameter);
for (Iterator<PsiTypeParameter> iterator = usedTypeParameters.iterator(); iterator.hasNext();) {
PsiTypeParameter usedTypeParameter = iterator.next();
if (parameter.getDeclarationScope() != usedTypeParameter.getOwner()) {
iterator.remove();
}
}
return new PsiType[]{type};
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(parameter.getProject());
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
for (PsiTypeParameter usedTypeParameter : usedTypeParameters) {
subst = subst.put(usedTypeParameter, TypeConversionUtil.typeParameterErasure(usedTypeParameter));
}
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
final Map<PsiTypeParameter, PsiType> typeMap = result.getSubstitutor().getSubstitutionMap();
for (PsiTypeParameter typeParameter : typeMap.keySet()) {
final PsiType psiType = typeMap.get(typeParameter);
substitutor = substitutor.put(typeParameter, psiType != null ? subst.substitute(psiType) : null);
}
return new PsiType[]{psiClass instanceof PsiTypeParameter ? subst.substitute((PsiTypeParameter)psiClass) : elementFactory.createType(psiClass, substitutor)};
}
@NotNull
@@ -1173,31 +1173,8 @@ public class RefactoringUtil {
final Set<PsiTypeParameter> used = new HashSet<PsiTypeParameter>();
for (final PsiElement element : elements) {
if (element == null) continue;
element.accept(new JavaRecursiveElementVisitor() { //pull up extends cls class with type params
collectTypeParameters(used, element); //pull up extends cls class with type params
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
if (!reference.isQualified()) {
final PsiElement resolved = reference.resolve();
if (resolved instanceof PsiTypeParameter) {
final PsiTypeParameter typeParameter = (PsiTypeParameter)resolved;
if (PsiTreeUtil.isAncestor(typeParameter.getOwner(), element, true)) {
used.add(typeParameter);
}
}
}
}
@Override
public void visitExpression(final PsiExpression expression) {
super.visitExpression(expression);
final PsiType type = expression.getType();
final PsiClass resolved = PsiUtil.resolveClassInType(type);
if (resolved instanceof PsiTypeParameter && PsiTreeUtil.isAncestor(((PsiTypeParameter)resolved).getOwner(), element, true)){
used.add((PsiTypeParameter)resolved);
}
}
});
}
if (fromList != null) {
@@ -1228,4 +1205,31 @@ public class RefactoringUtil {
return null;
}
}
public static void collectTypeParameters(final Set<PsiTypeParameter> used, final PsiElement element) {
element.accept(new JavaRecursiveElementVisitor() {
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
if (!reference.isQualified()) {
final PsiElement resolved = reference.resolve();
if (resolved instanceof PsiTypeParameter) {
final PsiTypeParameter typeParameter = (PsiTypeParameter)resolved;
if (PsiTreeUtil.isAncestor(typeParameter.getOwner(), element, true)) {
used.add(typeParameter);
}
}
}
}
@Override
public void visitExpression(final PsiExpression expression) {
super.visitExpression(expression);
final PsiType type = expression.getType();
final PsiClass resolved = PsiUtil.resolveClassInType(type);
if (resolved instanceof PsiTypeParameter && PsiTreeUtil.isAncestor(((PsiTypeParameter)resolved).getOwner(), element, true)){
used.add((PsiTypeParameter)resolved);
}
}
});
}
}
@@ -0,0 +1,11 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test{
private final List<String> myP1;
<T extends String> void f(List<T> p1){
myP1 = p1;
}
}
@@ -0,0 +1,11 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test<T>{
private final List<T> myP1;
void f(List<T> p1){
myP1 = p1;
}
}
@@ -0,0 +1,11 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test{
private final List<Object> myP1;
<T> void f(List<T> p1){
myP1 = p1;
}
}
@@ -0,0 +1,8 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test{
<T extends String> void f(List<T> p<caret>1){
}
}
@@ -0,0 +1,8 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test<T>{
void f(List<T> p<caret>1){
}
}
@@ -0,0 +1,8 @@
// "Create Field For Parameter 'p1'" "true"
import java.util.*;
class Test{
<T> void f(List<T> p<caret>1){
}
}