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); }
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())); }
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); }
@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); }
@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); }
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); }