private void reportNullableReturns( DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors, @NotNull PsiElement block) { final PsiMethod method = getScopeMethod(block); if (method == null || NullableStuffInspectionBase.isNullableNotInferred(method, true)) return; boolean notNullRequired = NullableNotNullManager.isNotNull(method); if (!notNullRequired && !SUGGEST_NULLABLE_ANNOTATIONS) return; PsiType returnType = method.getReturnType(); // no warnings in void lambdas, where the expression is not returned anyway if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && returnType == PsiType.VOID) return; // no warnings for Void methods, where only null can be possibly returned if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return; for (PsiElement statement : visitor.getProblems(NullabilityProblem.nullableReturn)) { assert statement instanceof PsiExpression; final PsiExpression expr = (PsiExpression) statement; if (!reportedAnchors.add(expr)) continue; if (notNullRequired) { final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message("dataflow.message.return.null.from.notnull") : InspectionsBundle.message("dataflow.message.return.nullable.from.notnull"); holder.registerProblem(expr, text); } else if (AnnotationUtil.isAnnotatingApplicable(statement)) { final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject()); final String defaultNullable = manager.getDefaultNullable(); final String presentableNullable = StringUtil.getShortName(defaultNullable); final String text = isNullLiteralExpression(expr) ? InspectionsBundle.message( "dataflow.message.return.null.from.notnullable", presentableNullable) : InspectionsBundle.message( "dataflow.message.return.nullable.from.notnullable", presentableNullable); final LocalQuickFix[] fixes = PsiTreeUtil.getParentOfType(expr, PsiMethod.class, PsiLambdaExpression.class) instanceof PsiLambdaExpression ? LocalQuickFix.EMPTY_ARRAY : new LocalQuickFix[] { new AnnotateMethodFix( defaultNullable, ArrayUtil.toStringArray(manager.getNotNulls())) { @Override public int shouldAnnotateBaseMethod( PsiMethod method, PsiMethod superMethod, Project project) { return 1; } } }; holder.registerProblem(expr, text, fixes); } } }
private void reportNullableArgumentsPassedToNonAnnotated( DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) { for (PsiElement expr : visitor.getProblems(NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter)) { if (reportedAnchors.contains(expr)) continue; final String text = isNullLiteralExpression(expr) ? "Passing <code>null</code> argument to non annotated parameter" : "Argument <code>#ref</code> #loc might be null but passed to non annotated parameter"; LocalQuickFix[] fixes = createNPEFixes((PsiExpression) expr, (PsiExpression) expr, holder.isOnTheFly()); final PsiElement parent = expr.getParent(); if (parent instanceof PsiExpressionList) { final int idx = ArrayUtilRt.find(((PsiExpressionList) parent).getExpressions(), expr); if (idx > -1) { final PsiElement gParent = parent.getParent(); if (gParent instanceof PsiCallExpression) { final PsiMethod psiMethod = ((PsiCallExpression) gParent).resolveMethod(); if (psiMethod != null && psiMethod.getManager().isInProject(psiMethod) && AnnotationUtil.isAnnotatingApplicable(psiMethod)) { final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); if (idx < parameters.length) { final AddNullableAnnotationFix addNullableAnnotationFix = new AddNullableAnnotationFix(parameters[idx]); fixes = fixes == null ? new LocalQuickFix[] {addNullableAnnotationFix} : ArrayUtil.append(fixes, addNullableAnnotationFix); holder.registerProblem(expr, text, fixes); reportedAnchors.add(expr); } } } } } } }