hide fixes which expose unresolved type parameters; add fixes for boxing

IDEA-150081
This commit is contained in:
Anna.Kozlova
2018-01-12 18:50:42 +01:00
parent ab2ebdfbf2
commit 8ce7fac354
9 changed files with 61 additions and 29 deletions

View File

@@ -257,13 +257,26 @@ public class HighlightFixUtil {
public static List<IntentionAction> getChangeVariableTypeFixes(@NotNull PsiVariable variable, PsiType itemType) {
if (itemType instanceof PsiMethodReferenceType) return Collections.emptyList();
List<IntentionAction> result = new ArrayList<>();
if (itemType != null) {
if (itemType != null && PsiTypesUtil.allTypeParametersResolved(variable, itemType)) {
for (ChangeVariableTypeQuickFixProvider fixProvider : Extensions.getExtensions(ChangeVariableTypeQuickFixProvider.EP_NAME)) {
Collections.addAll(result, fixProvider.getFixes(variable, itemType));
}
IntentionAction changeFix = getChangeParameterClassFix(variable.getType(), itemType);
if (changeFix != null) result.add(changeFix);
}
IntentionAction changeFix = getChangeParameterClassFix(variable.getType(), itemType);
if (changeFix != null) result.add(changeFix);
else if (itemType instanceof PsiArrayType) {
PsiType type = variable.getType();
if (type instanceof PsiArrayType && type.getArrayDimensions() == itemType.getArrayDimensions()) {
PsiType componentType = type.getDeepComponentType();
if (componentType instanceof PsiPrimitiveType) {
PsiClassType boxedType = ((PsiPrimitiveType)componentType).getBoxedType(variable);
if (boxedType != null) {
return getChangeVariableTypeFixes(variable, PsiTypesUtil.createArrayType(boxedType, type.getArrayDimensions()));
}
}
}
}
return result;
}

View File

@@ -392,7 +392,7 @@ public class CodeInsightUtil {
PsiClassType inheritorType = typeArgs == null || typeArgs.contains(null)
? factory.createType(inheritor, factory.createRawSubstitutor(inheritor))
: factory.createType(inheritor, typeArgs.toArray(PsiType.EMPTY_ARRAY));
PsiType toAdd = addArrayDimensions(arrayDim, inheritorType);
PsiType toAdd = PsiTypesUtil.createArrayType(inheritorType, arrayDim);
if (baseType.isAssignableFrom(toAdd)) {
result.consume(toAdd);
}
@@ -401,13 +401,6 @@ public class CodeInsightUtil {
};
}
private static PsiType addArrayDimensions(int arrayDim, PsiType newType) {
for(int i = 0; i < arrayDim; i++){
newType = newType.createArrayType();
}
return newType;
}
@NotNull
public static List<PsiType> getExpectedTypeArgs(PsiElement context,
PsiTypeParameterListOwner paramOwner,

View File

@@ -39,7 +39,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class MethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement implements HighPriorityAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.MethodReturnBooleanFix");
@@ -84,19 +83,12 @@ public class MethodReturnTypeFix extends LocalQuickFixAndIntentionActionOnPsiEle
!TypeConversionUtil.isNullType(myReturnType)) {
final PsiType returnType = myMethod.getReturnType();
if (returnType != null && returnType.isValid() && !Comparing.equal(myReturnType, returnType)) {
return allTypeParametersResolved(myMethod, myReturnType);
return PsiTypesUtil.allTypeParametersResolved(myMethod, myReturnType);
}
}
return false;
}
private static boolean allTypeParametersResolved(PsiMethod myMethod, PsiType myReturnType) {
PsiTypesUtil.TypeParameterSearcher searcher = new PsiTypesUtil.TypeParameterSearcher();
myReturnType.accept(searcher);
Set<PsiTypeParameter> parameters = searcher.getTypeParameters();
return parameters.stream().allMatch(parameter -> PsiTypesUtil.isAccessibleAt(parameter, myMethod));
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,

View File

@@ -398,9 +398,7 @@ public class GenericsUtil {
PsiType componentType = transformed != null ? transformed.getDeepComponentType() : null;
if (componentType instanceof PsiWildcardType) {
componentType = ((PsiWildcardType)componentType).getExtendsBound();
int dims = transformed.getArrayDimensions();
for (int i = 0; i < dims; i++) componentType = componentType.createArrayType();
return componentType;
return PsiTypesUtil.createArrayType(componentType, transformed.getArrayDimensions());
}
return transformed;

View File

@@ -408,6 +408,20 @@ public class PsiTypesUtil {
return false;
}
public static boolean allTypeParametersResolved(PsiElement context, PsiType targetType) {
TypeParameterSearcher searcher = new TypeParameterSearcher();
targetType.accept(searcher);
Set<PsiTypeParameter> parameters = searcher.getTypeParameters();
return parameters.stream().allMatch(parameter -> isAccessibleAt(parameter, context));
}
public static PsiType createArrayType(PsiType newType, int arrayDim) {
for(int i = 0; i < arrayDim; i++){
newType = newType.createArrayType();
}
return newType;
}
public static class TypeParameterSearcher extends PsiTypeVisitor<Boolean> {
private final Set<PsiTypeParameter> myTypeParams = new HashSet<>();

View File

@@ -460,12 +460,7 @@ public final class PsiUtil extends PsiUtilCore {
public static PsiType convertAnonymousToBaseType(@NotNull PsiType type) {
PsiClass psiClass = resolveClassInType(type);
if (psiClass instanceof PsiAnonymousClass) {
int dims = type.getArrayDimensions();
type = ((PsiAnonymousClass) psiClass).getBaseClassType();
while (dims != 0) {
type = type.createArrayType();
dims--;
}
type = PsiTypesUtil.createArrayType(((PsiAnonymousClass) psiClass).getBaseClassType(), type.getArrayDimensions());
}
return type;
}

View File

@@ -0,0 +1,9 @@
// "Change parameter 'a' type to 'java.lang.Long[]'" "true"
class Base {
void m(Long[] a) {
mg(a);
}
<T> void mg(T[] p) {}
}

View File

@@ -0,0 +1,9 @@
// "Change parameter 'a' type to 'java.lang.Long[]'" "true"
class Base {
void m(long[] a) {
mg(<caret>a);
}
<T> void mg(T[] p) {}
}

View File

@@ -0,0 +1,9 @@
// "Change parameter 'a' type to 'T[]'" "false"
class Base {
void m(long[] a) {
mg(<caret>a);
}
<T> void mg(T[] p) {}
}