make isDenotableType compliant to specification

This commit is contained in:
Roman.Ivanov
2018-05-30 11:01:19 +07:00
parent 06166d1382
commit cd72be6365
10 changed files with 28 additions and 31 deletions
@@ -58,7 +58,7 @@ public class AddTypeCastFix extends LocalQuickFixAndIntentionActionOnPsiElement
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
return myType.isValid() &&
PsiTypesUtil.isDenotableType(myType) &&
PsiTypesUtil.isDenotableType(myType, startElement) &&
PsiTypesUtil.allTypeParametersResolved(startElement, myType) &&
startElement.getManager().isInProject(startElement);
}
@@ -23,7 +23,7 @@ public class VariableTypeCanBeExplicitInspection extends AbstractBaseJavaLocalIn
PsiTypeElement typeElement = variable.getTypeElement();
if (typeElement != null && typeElement.isInferredType()) {
PsiType type = variable.getType();
if (!PsiTypesUtil.isNonDenotableType(type, variable)) {
if (PsiTypesUtil.isDenotableType(type, variable)) {
holder.registerProblem(typeElement,
"'var' can be replaced with explicit type",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
@@ -140,7 +140,7 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor {
if (method.isVarArgs() && method.hasTypeParameters() && args.length > method.getParameterList().getParametersCount() + 50) {
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
for (PsiTypeParameter typeParameter : method.getTypeParameters()) {
if (!PsiTypesUtil.isDenotableType(substitutor.substitute(typeParameter))) {
if (!PsiTypesUtil.isDenotableType(substitutor.substitute(typeParameter), typeParameter)) {
return;
}
}
@@ -79,20 +79,20 @@ public class AddNewArrayExpressionFix implements IntentionAction {
final PsiElement parent = myInitializer.getParent();
if (!(parent instanceof PsiAssignmentExpression)) {
if (initializers.length <= 0) return null;
return validateType(initializers[0].getType());
return validateType(initializers[0].getType(), parent);
}
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
final PsiType type = assignmentExpression.getType();
if (!(type instanceof PsiArrayType)) {
if (initializers.length <= 0) return null;
return validateType(initializers[0].getType());
return validateType(initializers[0].getType(), parent);
}
return validateType(((PsiArrayType)type).getComponentType());
return validateType(((PsiArrayType)type).getComponentType(), parent);
}
private static PsiType validateType(PsiType type) {
private static PsiType validateType(PsiType type, @NotNull PsiElement context) {
if (PsiType.NULL.equals(type)) return null;
return LambdaUtil.notInferredType(type) || !PsiTypesUtil.isDenotableType(type) ? null
return LambdaUtil.notInferredType(type) || !PsiTypesUtil.isDenotableType(type, context) ? null
: TypeConversionUtil.erasure(type);
}
@@ -92,7 +92,7 @@ public class SurroundWithArrayFix extends PsiElementBaseIntentionAction {
final PsiType paramType = psiParameters[idx].getType();
if (paramType instanceof PsiArrayType) {
final PsiType expressionType = TypeConversionUtil.erasure(expression.getType());
if (expressionType != null && PsiTypesUtil.isDenotableType(expressionType) && expressionType != PsiType.NULL) {
if (expressionType != null && PsiTypesUtil.isDenotableType(expressionType, element) && expressionType != PsiType.NULL) {
final PsiType componentType = ((PsiArrayType)paramType).getComponentType();
if (TypeConversionUtil.isAssignable(componentType, expressionType)) {
return expression;
@@ -67,7 +67,7 @@ public class VariableAccessFromInnerClassJava10Fix extends BaseIntentionAction {
if (name == null) return false;
PsiType type = variable.getType();
if (PsiTypesUtil.isNonDenotableType(type, variable)) {
if (!PsiTypesUtil.isDenotableType(type, variable)) {
return false;
}
setText(QuickFixBundle.message("convert.variable.to.field.in.anonymous.class.fix.name", name));
@@ -315,7 +315,7 @@ public class LambdaRefactoringUtil {
for (int i = 0; i < parameters.length; i++) {
PsiType psiType = substitutor.substitute(parameters[i].getType());
if (psiType == null) return null;
if (!PsiTypesUtil.isDenotableType(psiType)) {
if (!PsiTypesUtil.isDenotableType(psiType, interfaceMethod)) {
return null;
}
@@ -320,8 +320,19 @@ public class PsiTypesUtil {
return Comparing.equal(leftType, rightType);
}
public static boolean isDenotableType(PsiType type) {
return !(type instanceof PsiWildcardType || type instanceof PsiCapturedWildcardType);
/**
* @param context in which type should be checked
* @return false if type is null or has no explicit canonical type representation (e. g. intersection type)
*/
public static boolean isDenotableType(@Nullable PsiType type, @NotNull PsiElement context) {
if (type == null) return false;
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(context.getProject());
try {
PsiType typeAfterReplacement = elementFactory.createTypeElementFromText(type.getCanonicalText(), context).getType();
return type.equals(typeAfterReplacement);
} catch (IncorrectOperationException e) {
return false;
}
}
public static boolean hasUnresolvedComponents(@NotNull PsiType type) {
@@ -468,18 +479,4 @@ public class PsiTypesUtil {
return false;
}
}
/**
* @param context in which type should be checked
* @return true if type has no explicit canonical type representation (e. g. intersection type)
*/
public static boolean isNonDenotableType(@NotNull PsiType type, @NotNull PsiElement context) {
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(context.getProject());
try {
PsiType typeAfterReplacement = elementFactory.createTypeElementFromText(type.getCanonicalText(), context).getType();
return !type.equals(typeAfterReplacement);
} catch (IncorrectOperationException e) {
return true;
}
}
}
@@ -228,12 +228,12 @@ public class LambdaCanBeReplacedWithAnonymousInspection extends BaseInspection {
final PsiSubstitutor substitutor =
LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(functionalInterfaceType));
for (PsiType type : interfaceMethod.getSignature(substitutor).getParameterTypes()) {
if (!PsiTypesUtil.isDenotableType(type)) {
if (!PsiTypesUtil.isDenotableType(type, parent)) {
return false;
}
}
final PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
return PsiTypesUtil.isDenotableType(returnType);
return PsiTypesUtil.isDenotableType(returnType, parent);
}
}
}
@@ -161,9 +161,9 @@ object LambdaToAnonymousTransformer : PsiElementTransformer.Base() {
val interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType)
if (interfaceMethod != null) {
val substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(functionalInterfaceType))
if (interfaceMethod.getSignature(substitutor).parameterTypes.any { !PsiTypesUtil.isDenotableType(it) }) return false
if (interfaceMethod.getSignature(substitutor).parameterTypes.any { !PsiTypesUtil.isDenotableType(it, lambdaExpression) }) return false
val returnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType)
return PsiTypesUtil.isDenotableType(returnType)
return PsiTypesUtil.isDenotableType(returnType, lambdaExpression)
}
}