private static void reportCastMayFail(ProblemsHolder holder, TypeCastInstruction instruction) { PsiTypeCastExpression typeCast = instruction.getCastExpression(); PsiExpression operand = typeCast.getOperand(); PsiTypeElement castType = typeCast.getCastType(); assert castType != null; assert operand != null; holder.registerProblem( castType, InspectionsBundle.message("dataflow.message.cce", operand.getText())); }
static boolean isComplexArrayExpression(PsiExpression expression) { expression = ParenthesesUtils.stripParentheses(expression); if (expression == null) { return false; } if (expression instanceof PsiNewExpression) { final PsiNewExpression newExpression = (PsiNewExpression) expression; final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer(); return isComplexArrayExpression(arrayInitializer); } else if (expression instanceof PsiArrayInitializerExpression) { final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression) expression; for (PsiExpression initializer : arrayInitializerExpression.getInitializers()) { if (isComplexArrayExpression(initializer)) { return true; } } return false; } else if (expression instanceof PsiReferenceExpression) { return expression.getType() instanceof PsiArrayType; } else if (expression instanceof PsiArrayAccessExpression) { return true; } else if (expression instanceof PsiTypeCastExpression) { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) expression; return isComplexArrayExpression(typeCastExpression.getOperand()); } else if (expression instanceof PsiConditionalExpression) { final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression) expression; return isComplexArrayExpression(conditionalExpression.getThenExpression()) || isComplexArrayExpression(conditionalExpression.getElseExpression()); } else if (expression instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) expression; final PsiMethod method = methodCallExpression.resolveMethod(); if (method == null) { return true; } if (CloneUtils.isClone(method)) { return false; } @NonNls final String name = method.getName(); if ("copyOf".equals(name) || "copyOfRange".equals(name)) { final PsiClass aClass = method.getContainingClass(); if (aClass != null && CommonClassNames.JAVA_UTIL_ARRAYS.equals(aClass.getQualifiedName())) { return false; } } else if ("toArray".equals(name) && InheritanceUtil.isInheritor(method.getContainingClass(), "java.util.Collection")) { return false; } return true; } return true; }
@Nullable private ProblemDescriptor createDescription( @NotNull PsiTypeCastExpression cast, @NotNull InspectionManager manager, boolean onTheFly) { PsiExpression operand = cast.getOperand(); PsiTypeElement castType = cast.getCastType(); if (operand == null || castType == null) return null; PsiElement parent = cast.getParent(); while (parent instanceof PsiParenthesizedExpression) { parent = parent.getParent(); } if (parent instanceof PsiReferenceExpression) { if (IGNORE_ANNOTATED_METHODS) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiMethodCallExpression) { final PsiMethod psiMethod = ((PsiMethodCallExpression) gParent).resolveMethod(); if (psiMethod != null && NullableNotNullManager.isNotNull(psiMethod)) { final PsiClass superClass = PsiUtil.resolveClassInType(operand.getType()); final PsiClass containingClass = psiMethod.getContainingClass(); if (containingClass != null && superClass != null && containingClass.isInheritor(superClass, true)) { for (PsiMethod method : psiMethod.findSuperMethods(superClass)) { if (NullableNotNullManager.isNullable(method)) { return null; } } } } } } } else if (parent instanceof PsiExpressionList) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiMethodCallExpression && IGNORE_SUSPICIOUS_METHOD_CALLS) { final String message = SuspiciousCollectionsMethodCallsInspection.getSuspiciousMethodCallMessage( (PsiMethodCallExpression) gParent, operand.getType(), true, new ArrayList<PsiMethod>(), new IntArrayList()); if (message != null) { return null; } } } String message = InspectionsBundle.message( "inspection.redundant.cast.problem.descriptor", "<code>" + operand.getText() + "</code>", "<code>#ref</code> #loc"); return manager.createProblemDescriptor( castType, message, myQuickFixAction, ProblemHighlightType.LIKE_UNUSED_SYMBOL, onTheFly); }
private static boolean typeCastExpressionsAreEquivalent( @NotNull PsiTypeCastExpression typeCastExpression1, @NotNull PsiTypeCastExpression typeCastExpression2) { final PsiTypeElement typeElement1 = typeCastExpression1.getCastType(); final PsiTypeElement typeElement2 = typeCastExpression2.getCastType(); if (!typeElementsAreEquivalent(typeElement1, typeElement2)) { return false; } final PsiExpression operand1 = typeCastExpression1.getOperand(); final PsiExpression operand2 = typeCastExpression2.getOperand(); return expressionsAreEquivalent(operand1, operand2); }
@Override protected final void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement element = descriptor.getPsiElement(); final PsiTypeElement castTypeElement; final PsiReferenceExpression reference; if (element instanceof PsiTypeCastExpression) { final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression) element; castTypeElement = typeCastExpression.getCastType(); final PsiExpression operand = typeCastExpression.getOperand(); if (!(operand instanceof PsiReferenceExpression)) { return; } reference = (PsiReferenceExpression) operand; } else if (element instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) element; final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiClassObjectAccessExpression)) { return; } final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression) qualifier; castTypeElement = classObjectAccessExpression.getOperand(); final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length != 1) { return; } final PsiExpression argument = arguments[0]; if (!(argument instanceof PsiReferenceExpression)) { return; } reference = (PsiReferenceExpression) argument; } else { return; } if (castTypeElement == null) { return; } final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(castTypeElement.getType(), reference, element); final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); if (instanceofTypeElement == null) { return; } final PsiElement newElement = replace(castTypeElement, instanceofTypeElement); final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); codeStyleManager.shortenClassReferences(newElement); }
private static void removeParensFromTypeCastExpression( @NotNull PsiTypeCastExpression typeCastExpression, boolean ignoreClarifyingParentheses) { final PsiExpression operand = typeCastExpression.getOperand(); if (operand != null) { removeParentheses(operand, ignoreClarifyingParentheses); } }
private static boolean typecastExpressionsAreEquivalent( @NotNull PsiTypeCastExpression typecastExp1, @NotNull PsiTypeCastExpression typecastExp2) { final PsiTypeElement typeElement1 = typecastExp1.getCastType(); final PsiTypeElement typeElement2 = typecastExp2.getCastType(); if (typeElement1 == null && typeElement2 == null) { return true; } if (typeElement1 == null || typeElement2 == null) { return false; } final PsiType type1 = typeElement1.getType(); final PsiType type2 = typeElement2.getType(); if (!typesAreEquivalent(type1, type2)) { return false; } final PsiExpression operand1 = typecastExp1.getOperand(); final PsiExpression operand2 = typecastExp2.getOperand(); return expressionsAreEquivalent(operand1, operand2); }
private boolean isIteratorNext( PsiElement element, String iteratorName, PsiType contentType) { if (element == null) { return false; } if (element instanceof PsiTypeCastExpression) { final PsiTypeCastExpression castExpression = (PsiTypeCastExpression)element; final PsiType type = castExpression.getType(); if (type == null) { return false; } if (!type.equals(contentType)) { return false; } final PsiExpression operand = castExpression.getOperand(); return isIteratorNext(operand, iteratorName, contentType); } if (!(element instanceof PsiMethodCallExpression)) { return false; } final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)element; final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] args = argumentList.getExpressions(); if (args.length != 0) { return false; } final PsiReferenceExpression reference = callExpression.getMethodExpression(); final PsiExpression qualifier = reference.getQualifierExpression(); if (qualifier == null) { return false; } if (!iteratorName.equals(qualifier.getText())) { return false; } final String referenceName = reference.getReferenceName(); return HardcodedMethodConstants.NEXT.equals(referenceName); }
@Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement castTypeElement = descriptor.getPsiElement(); final PsiTypeCastExpression expression = (PsiTypeCastExpression) castTypeElement.getParent(); if (expression == null) { return; } final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true); if (expectedType == null) { return; } final PsiExpression operand = expression.getOperand(); if (operand == null) { return; } @NonNls final String newExpression = '(' + expectedType.getCanonicalText() + ')' + operand.getText(); replaceExpressionAndShorten(expression, newExpression); }
static PsiExpression createCastExpression( PsiExpression originalExpression, Project project, PsiType type) throws IncorrectOperationException { // remove nested casts PsiElement element = PsiUtil.deparenthesizeExpression(originalExpression); PsiElementFactory factory = JavaPsiFacade.getInstance(originalExpression.getProject()).getElementFactory(); PsiTypeCastExpression typeCast = (PsiTypeCastExpression) factory.createExpressionFromText("(Type)value", null); typeCast = (PsiTypeCastExpression) CodeStyleManager.getInstance(project).reformat(typeCast); typeCast.getCastType().replace(factory.createTypeElement(type)); if (element instanceof PsiConditionalExpression) { // we'd better cast one branch of ternary expression if we could PsiConditionalExpression expression = (PsiConditionalExpression) element.copy(); PsiExpression thenE = expression.getThenExpression(); PsiExpression elseE = expression.getElseExpression(); PsiType thenType = thenE == null ? null : thenE.getType(); PsiType elseType = elseE == null ? null : elseE.getType(); if (elseType != null && thenType != null) { boolean replaceThen = !TypeConversionUtil.isAssignable(type, thenType); boolean replaceElse = !TypeConversionUtil.isAssignable(type, elseType); if (replaceThen != replaceElse) { if (replaceThen) { typeCast.getOperand().replace(thenE); thenE.replace(typeCast); } else { typeCast.getOperand().replace(elseE); elseE.replace(typeCast); } return expression; } } } typeCast.getOperand().replace(element); return typeCast; }
@Override public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); final PsiTypeElement castType = expression.getCastType(); if (castType == null) { return; } final PsiType type = castType.getType(); final PsiExpression operand = expression.getOperand(); if (!(operand instanceof PsiReferenceExpression)) { return; } final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) operand; final PsiInstanceOfExpression conflictingInstanceof = InstanceOfUtils.getConflictingInstanceof(type, referenceExpression, expression); if (conflictingInstanceof == null) { return; } final PsiTypeElement instanceofTypeElement = conflictingInstanceof.getCheckType(); if (instanceofTypeElement == null) { return; } registerError(expression, referenceExpression, castType, instanceofTypeElement); }
@Override public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) { super.visitTypeCastExpression(expression); final PsiExpression operand = expression.getOperand(); if (operand == null) { return; } final PsiType operandType = operand.getType(); if (operandType == null) { return; } final PsiType type = expression.getType(); if (type == null) { return; } final PsiType expectedType = ExpectedTypeUtils.findExpectedType(expression, true); if (expectedType == null) { return; } if (expectedType.equals(type)) { return; } final PsiClass resolved = PsiUtil.resolveClassInType(expectedType); if (resolved != null && !resolved.isPhysical()) { return; } if (expectedType.isAssignableFrom(operandType)) { // then it's redundant, and caught by the built-in exception return; } if (isTypeParameter(expectedType)) { return; } if (expectedType instanceof PsiArrayType) { final PsiArrayType arrayType = (PsiArrayType) expectedType; final PsiType componentType = arrayType.getDeepComponentType(); if (isTypeParameter(componentType)) { return; } } if (type instanceof PsiPrimitiveType || expectedType instanceof PsiPrimitiveType) { return; } if (PsiPrimitiveType.getUnboxedType(type) != null || PsiPrimitiveType.getUnboxedType(expectedType) != null) { return; } if (expectedType instanceof PsiClassType) { final PsiClassType expectedClassType = (PsiClassType) expectedType; final PsiClassType expectedRawType = expectedClassType.rawType(); if (type.equals(expectedRawType)) { return; } if (type instanceof PsiClassType) { final PsiClassType classType = (PsiClassType) type; final PsiClassType rawType = classType.rawType(); if (rawType.equals(expectedRawType)) { return; } } if (type instanceof PsiArrayType) { return; } } if (ignoreInMatchingInstanceof && InstanceOfUtils.hasAgreeingInstanceof(expression)) { return; } final PsiTypeElement castTypeElement = expression.getCastType(); if (castTypeElement == null) { return; } registerError(castTypeElement, expectedType); }