return type fix: change type arguments of dependant type parameters only (IDEA-158361)

This commit is contained in:
Anna.Kozlova
2016-07-11 18:05:00 +02:00
parent 0d706238cb
commit 750afb8497
4 changed files with 78 additions and 8 deletions
@@ -35,6 +35,7 @@ import com.intellij.psi.controlFlow.ControlFlow;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
@@ -47,10 +48,7 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.*;
public class MethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement implements HighPriorityAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.MethodReturnBooleanFix");
@@ -345,10 +343,11 @@ public class MethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiEle
TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
final PsiType superReturnTypeInBaseClassType = superClassSubstitutor.substitute(superReturnType);
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
final PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments(baseClass.getTypeParameters(),
new PsiType[]{superReturnTypeInBaseClassType},
new PsiType[]{returnType},
PsiUtil.getLanguageLevel(superClass));
final PsiSubstitutor psiSubstitutor =
resolveHelper.inferTypeArguments(PsiTypesUtil.filterUnusedTypeParameters(superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
new PsiType[]{superReturnTypeInBaseClassType},
new PsiType[]{returnType},
PsiUtil.getLanguageLevel(superClass));
final TypeMigrationRules rules = new TypeMigrationRules();
final PsiSubstitutor compoundSubstitutor =
@@ -22,12 +22,15 @@ import com.intellij.openapi.util.Condition;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class PsiTypesUtil {
@NonNls private static final Map<String, String> ourUnboxedTypes = new THashMap<String, String>();
@@ -309,4 +312,40 @@ public class PsiTypesUtil {
}
return parameterType;
}
public static PsiTypeParameter[] filterUnusedTypeParameters(final PsiType superReturnTypeInBaseClassType,
final PsiTypeParameter[] typeParameters) {
if (typeParameters.length == 0) return typeParameters;
final Set<PsiTypeParameter> usedParameters = new HashSet<PsiTypeParameter>();
superReturnTypeInBaseClassType.accept(new PsiTypeVisitor<Object>(){
@Nullable
@Override
public Object visitClassType(PsiClassType classType) {
final PsiClass aClass = classType.resolve();
if (aClass instanceof PsiTypeParameter && ArrayUtil.find(typeParameters, aClass) > -1) {
usedParameters.add((PsiTypeParameter)aClass);
return null;
}
for (PsiType type : classType.getParameters()) {
type.accept(this);
}
return null;
}
@Nullable
@Override
public Object visitWildcardType(PsiWildcardType wildcardType) {
final PsiType bound = wildcardType.getBound();
return bound != null ? bound.accept(this) : null;
}
@Nullable
@Override
public Object visitArrayType(PsiArrayType arrayType) {
return arrayType.getComponentType().accept(this);
}
});
return usedParameters.toArray(new PsiTypeParameter[usedParameters.size()]);
}
}
@@ -0,0 +1,16 @@
// "Make 'foo' return 'java.util.List<java.lang.Integer>'" "true"
import java.util.List;
interface Main<A, B> {
List<A> foo();
}
class MainImpl implements Main<Integer,String> {
@Override
public List<Integer> foo() {
return bar();
}
private List<Integer> bar() {
return null;
}
}
@@ -0,0 +1,16 @@
// "Make 'foo' return 'java.util.List<java.lang.Integer>'" "true"
import java.util.List;
interface Main<A, B> {
List<A> foo();
}
class MainImpl implements Main<String, String> {
@Override
public List<String> foo() {
return b<caret>ar();
}
private List<Integer> bar() {
return null;
}
}