support instanceof and casts expressions

This commit is contained in:
Alexey Kudravtsev
2018-05-16 17:15:23 +03:00
parent d945f6dde2
commit 512a5c01e5
2 changed files with 46 additions and 13 deletions
@@ -337,11 +337,11 @@ public class BoundedWildcardInspection extends AbstractBaseJavaLocalInspectionTo
if (PsiTreeUtil.isAncestor(ignoreUsagesIn, ref.getElement(), false)) return true;
PsiMethod calledMethod = getMethodCallOnReference(ref);
if (calledMethod == null) {
if (isInPolyadicExpression(ref)) return true; // ignore "x == y"
if (isInPolyadicOrInstanceOf(ref)) return true; // ignore "x == y"
PsiField field = isAssignedToField(ref);
if (field != null) {
// check if e.g. "Processor<String> field" is used in "field.process(xxx)" only
PsiElement ignoreUsagesInAssignment = PsiUtil.skipParenthesizedExprUp(ref.getElement().getParent());
PsiElement ignoreUsagesInAssignment = skipParensAndCastsUp(ref.getElement());
PsiFile fieldFile = field.getContainingFile();
Variance fv = fieldFile == null ? Variance.INVARIANT :
getVariance(field, new LocalSearchScope(fieldFile), ignoreUsagesInAssignment, containingMethod, typeParameter, extendsT, superT);
@@ -385,7 +385,7 @@ public class BoundedWildcardInspection extends AbstractBaseJavaLocalInspectionTo
@NotNull PsiClassReferenceType suggestedMethodParameterType,
@NotNull PsiMethod myself) {
PsiElement refElement = ref.getElement();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(refElement.getParent());
PsiElement parent = skipParensAndCastsUp(refElement);
if (!(parent instanceof PsiExpressionList)) return false;
List<PsiExpression> exprs = Arrays.asList(((PsiExpressionList)parent).getExpressions());
int index = ContainerUtil.indexOf(exprs, (Condition<PsiExpression>)(PsiExpression e) -> PsiTreeUtil.isAncestor(e, refElement, false));
@@ -421,12 +421,37 @@ public class BoundedWildcardInspection extends AbstractBaseJavaLocalInspectionTo
return TypeConversionUtil.isAssignable(paramType, capturedSuggested);
}
private static PsiElement skipParensAndCastsUp(@NotNull PsiElement element) {
PsiElement prev = element;
PsiElement parent = element.getParent();
while (parent instanceof PsiParenthesizedExpression ||
parent instanceof PsiTypeCastExpression && ((PsiTypeCastExpression)parent).getOperand() == prev) {
prev = parent;
parent = parent.getParent();
}
return parent;
}
private static PsiExpression skipParensAndCastsDown(@Nullable PsiExpression element) {
while (element instanceof PsiParenthesizedExpression || element instanceof PsiTypeCastExpression) {
if (element instanceof PsiParenthesizedExpression) {
element = ((PsiParenthesizedExpression)element).getExpression();
}
if (element instanceof PsiTypeCastExpression) {
element = ((PsiTypeCastExpression)element).getOperand();
}
}
return element;
}
private static PsiMethod getMethodCallOnReference(@NotNull PsiReference ref) {
PsiElement refElement = ref.getElement();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(refElement.getParent());
PsiElement parent = skipParensAndCastsUp(refElement);
if (!(parent instanceof PsiReferenceExpression)) return null;
PsiReferenceExpression refExpression = (PsiReferenceExpression)parent;
if (!refElement.equals(PsiUtil.skipParenthesizedExprDown(refExpression.getQualifierExpression()))) {
if (!refElement.equals(skipParensAndCastsDown(refExpression.getQualifierExpression()))) {
return null;
}
// "foo(parameter::consume)" variance is equivalent to "parameter.consume(xxx)"
@@ -447,9 +472,9 @@ public class BoundedWildcardInspection extends AbstractBaseJavaLocalInspectionTo
private static boolean isIteratedValueInForeachExpression(@NotNull PsiReference ref) {
PsiElement refElement = ref.getElement();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(refElement.getParent());
PsiElement parent = skipParensAndCastsUp(refElement);
if (!(parent instanceof PsiForeachStatement)) return false;
PsiExpression iteratedValue = PsiUtil.skipParenthesizedExprDown(((PsiForeachStatement)parent).getIteratedValue());
PsiExpression iteratedValue = skipParensAndCastsDown(((PsiForeachStatement)parent).getIteratedValue());
if (iteratedValue != ref) return false;
PsiType type = iteratedValue.getType();
@@ -459,22 +484,22 @@ public class BoundedWildcardInspection extends AbstractBaseJavaLocalInspectionTo
return aClass != null;
}
private static boolean isInPolyadicExpression(@NotNull PsiReference ref) {
private static boolean isInPolyadicOrInstanceOf(@NotNull PsiReference ref) {
PsiElement refElement = ref.getElement();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(refElement.getParent());
return parent instanceof PsiPolyadicExpression;
PsiElement parent = skipParensAndCastsUp(refElement);
return parent instanceof PsiPolyadicExpression || parent instanceof PsiInstanceOfExpression;
}
private static PsiField isAssignedToField(@NotNull PsiReference ref) {
PsiElement refElement = ref.getElement();
PsiElement parent = PsiUtil.skipParenthesizedExprUp(refElement.getParent());
PsiElement parent = skipParensAndCastsUp(refElement);
if (!(parent instanceof PsiAssignmentExpression) || ((PsiAssignmentExpression)parent).getOperationTokenType() != JavaTokenType.EQ) return null;
PsiExpression r = ((PsiAssignmentExpression)parent).getRExpression();
if (!PsiTreeUtil.isAncestor(r, refElement, false)) return null;
PsiExpression l = PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)parent).getLExpression());
PsiExpression l = skipParensAndCastsDown(((PsiAssignmentExpression)parent).getLExpression());
if (!(l instanceof PsiReferenceExpression)) return null;
PsiReferenceExpression lExpression = (PsiReferenceExpression)l;
PsiExpression lQualifier = PsiUtil.skipParenthesizedExprDown(lExpression.getQualifierExpression());
PsiExpression lQualifier = skipParensAndCastsDown(lExpression.getQualifierExpression());
if (lQualifier != null && !(lQualifier instanceof PsiThisExpression)) return null;
PsiElement field = lExpression.resolve();
// too expensive to search for usages of public field otherwise
@@ -194,4 +194,12 @@ public class Simple<T> {
return myProcessor;
}
}
///////// instanceof and cast
boolean castandinstanceof(Processor<<warning descr="Can generalize to '? super Number'">Number</warning>> p) {
if (p instanceof Number) return ((Number)p).intValue()==0;
if ((p) instanceof Number) return ((Number)(p)).intValue()==0;
return p.process(null);
}
}