diff options
Diffstat (limited to 'java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java')
-rw-r--r-- | java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java | 87 |
1 files changed, 71 insertions, 16 deletions
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java index 38f8d46fe10c..47d32a03bf8f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java @@ -114,8 +114,8 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); } } - if (annotated.isDeclaredNotNull && manager.isNullable(getter, false) || - annotated.isDeclaredNullable && manager.isNotNull(getter, false)) { + if (annotated.isDeclaredNotNull && isNullableNotInferred(getter, false) || + annotated.isDeclaredNullable && isNotNullNotInferred(getter, false)) { holder.registerProblem(nameIdentifier, InspectionsBundle.message( "inspection.nullable.problems.annotated.field.getter.conflict", getPresentableAnnoName(field), getPresentableAnnoName(getter)), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); @@ -141,8 +141,8 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo addAnnoFix); } if (PropertyUtil.isSimpleSetter(setter)) { - if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false) || - annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) { + if (annotated.isDeclaredNotNull && isNullableNotInferred(parameter, false) || + annotated.isDeclaredNullable && isNotNullNotInferred(parameter, false)) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message( @@ -154,7 +154,17 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo } } - for (PsiExpression rhs : DfaPsiUtil.findAllConstructorInitializers(field)) { + List<PsiExpression> initializers = DfaPsiUtil.findAllConstructorInitializers(field); + if (annotated.isDeclaredNotNull && initializers.isEmpty()) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(field, manager.getNotNulls()); + if (annotation != null) { + holder.registerProblem(annotation.isPhysical() ? annotation : field.getNameIdentifier(), + "Not-null fields must be initialized", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + } + } + + for (PsiExpression rhs : initializers) { if (rhs instanceof PsiReferenceExpression) { PsiElement target = ((PsiReferenceExpression)rhs).resolve(); if (target instanceof PsiParameter) { @@ -169,7 +179,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix); continue; } - if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) { + if (annotated.isDeclaredNullable && isNotNullNotInferred(parameter, false)) { boolean usedAsQualifier = !ReferencesSearch.search(parameter).forEach(new Processor<PsiReference>() { @Override public boolean process(PsiReference reference) { @@ -203,6 +213,33 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo if (!PsiUtil.isLanguageLevel5OrHigher(parameter)) return; check(parameter, holder, parameter.getType()); } + + @Override + public void visitAnnotation(PsiAnnotation annotation) { + if (!AnnotationUtil.NOT_NULL.equals(annotation.getQualifiedName())) return; + + PsiAnnotationMemberValue value = annotation.findDeclaredAttributeValue("exception"); + if (value instanceof PsiClassObjectAccessExpression) { + PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(((PsiClassObjectAccessExpression)value).getOperand().getType()); + if (psiClass != null && !hasStringConstructor(psiClass)) { + holder.registerProblem(value, + "Custom exception class should have a constructor with a single message parameter of String type", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + + } + } + } + + private boolean hasStringConstructor(PsiClass aClass) { + for (PsiMethod method : aClass.getConstructors()) { + PsiParameterList list = method.getParameterList(); + if (list.getParametersCount() == 1 && + list.getParameters()[0].getType().equalsToText(CommonClassNames.JAVA_LANG_STRING)) { + return true; + } + } + return false; + } }; } @@ -231,7 +268,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo PsiAnnotation isDeclaredNotNull = AnnotationUtil.findAnnotation(parameter, manager.getNotNulls()); PsiAnnotation isDeclaredNullable = AnnotationUtil.findAnnotation(parameter, manager.getNullables()); if (isDeclaredNullable != null && isDeclaredNotNull != null) { - reportNullableNotNullConflict(holder, parameter, isDeclaredNullable, isDeclaredNotNull); + reportNullableNotNullConflict(holder, parameter, isDeclaredNullable, isDeclaredNotNull); } if ((isDeclaredNotNull != null || isDeclaredNullable != null) && type != null && TypeConversionUtil.isPrimitive(type.getCanonicalText())) { PsiAnnotation annotation = isDeclaredNotNull == null ? isDeclaredNullable : isDeclaredNotNull; @@ -282,7 +319,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo if (!reported_nullable_method_overrides_notnull && REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE && annotated.isDeclaredNullable - && NullableNotNullManager.isNotNull(superMethod)) { + && isNotNullNotInferred(superMethod, true)) { reported_nullable_method_overrides_notnull = true; final PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNullables(), true); holder.registerProblem(annotation != null ? annotation : method.getNameIdentifier(), @@ -293,7 +330,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo && REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL && !annotated.isDeclaredNullable && !annotated.isDeclaredNotNull - && NullableNotNullManager.isNotNull(superMethod)) { + && isNotNullNotInferred(superMethod, true)) { reported_not_annotated_method_overrides_notnull = true; final String defaultNotNull = nullableManager.getDefaultNotNull(); final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); @@ -314,8 +351,8 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo PsiParameter parameter = parameters[i]; PsiParameter superParameter = superParameters[i]; if (!reported_notnull_parameter_overrides_nullable[i] && REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE && - nullableManager.isNotNull(parameter, false) && - nullableManager.isNullable(superParameter, false)) { + isNotNullNotInferred(parameter, false) && + isNullableNotInferred(superParameter, false)) { reported_notnull_parameter_overrides_nullable[i] = true; final PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameter, nullableManager.getNotNulls(), true); holder.registerProblem(annotation != null ? annotation : parameter.getNameIdentifier(), @@ -325,7 +362,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } if (!reported_not_annotated_parameter_overrides_notnull[i] && REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL) { - if (!nullableManager.hasNullability(parameter) && nullableManager.isNotNull(superParameter, false)) { + if (!nullableManager.hasNullability(parameter) && isNotNullNotInferred(superParameter, false)) { reported_not_annotated_parameter_overrides_notnull[i] = true; final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, nullableManager.getDefaultNotNull()) ? new AddNotNullAnnotationFix(parameter) @@ -346,7 +383,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo boolean hasAnnotatedParameter = false; for (int i = 0; i < parameters.length; i++) { PsiParameter parameter = parameters[i]; - parameterAnnotated[i] = nullableManager.isNotNull(parameter, false); + parameterAnnotated[i] = isNotNullNotInferred(parameter, false); hasAnnotatedParameter |= parameterAnnotated[i]; } if (hasAnnotatedParameter || annotated.isDeclaredNotNull) { @@ -362,8 +399,8 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo final boolean applicable = AnnotationUtil.isAnnotatingApplicable(overriding, defaultNotNull); if (!methodQuickFixSuggested && annotated.isDeclaredNotNull - && !nullableManager.isNotNull(overriding, false) - && (nullableManager.isNullable(overriding, false) || !nullableManager.isNullable(overriding, true))) { + && !isNotNullNotInferred(overriding, false) + && (isNullableNotInferred(overriding, false) || !isNullableNotInferred(overriding, true))) { method.getNameIdentifier(); //load tree PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls()); final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); @@ -391,7 +428,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo for (int i = 0; i < psiParameters.length; i++) { if (parameterQuickFixSuggested[i]) continue; PsiParameter parameter = psiParameters[i]; - if (parameterAnnotated[i] && !nullableManager.isNotNull(parameter, false) && !nullableManager.isNullable(parameter, false)) { + if (parameterAnnotated[i] && !isNotNullNotInferred(parameter, false) && !isNullableNotInferred(parameter, false)) { parameters[i].getNameIdentifier(); //be sure that corresponding tree element available PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameters[i], nullableManager.getNotNulls()); PsiElement psiElement = annotation; @@ -415,6 +452,24 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo } } + private static boolean isNotNullNotInferred(@NotNull PsiModifierListOwner owner, boolean checkBases) { + Project project = owner.getProject(); + NullableNotNullManager manager = NullableNotNullManager.getInstance(project); + if (!manager.isNotNull(owner, checkBases)) return false; + + PsiAnnotation anno = manager.getNotNullAnnotation(owner, checkBases); + return !(anno != null && AnnotationUtil.isInferredAnnotation(anno)); + } + + private static boolean isNullableNotInferred(@NotNull PsiModifierListOwner owner, boolean checkBases) { + Project project = owner.getProject(); + NullableNotNullManager manager = NullableNotNullManager.getInstance(project); + if (!manager.isNullable(owner, checkBases)) return false; + + PsiAnnotation anno = manager.getNullableAnnotation(owner, checkBases); + return !(anno != null && AnnotationUtil.isInferredAnnotation(anno)); + } + @NotNull private static LocalQuickFix[] wrapFix(LocalQuickFix fix) { if (fix == null) return LocalQuickFix.EMPTY_ARRAY; |