From 9425fa701c70ac4f4bcf17f9b2147648b18f0bfb Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 21 May 2015 11:12:52 +0200 Subject: [PATCH] NullableStuffInspectionBase: break field analysis into smaller methods --- .../nullable/NullableStuffInspectionBase.java | 286 ++++++++++-------- 1 file changed, 158 insertions(+), 128 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 9f6253402c86..a3ee44c376f6 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 @@ -101,142 +101,18 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable(); final List annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls(); - if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) { - final PsiAnnotation notNull = AnnotationUtil.findAnnotation(field, manager.getNotNulls()); - final PsiAnnotation nullable = AnnotationUtil.findAnnotation(field, manager.getNullables()); - final PsiAnnotation annotation; - String message = "Not \'"; - if (annotated.isDeclaredNullable) { - message += nullable.getQualifiedName(); - annotation = nullable; - } else { - message += notNull.getQualifiedName(); - annotation = notNull; - } - message += "\' but \'" + anno + "\' would be used for code generation."; - final PsiJavaCodeReferenceElement annotationNameReferenceElement = annotation.getNameReferenceElement(); - holder.registerProblem(annotationNameReferenceElement != null && annotationNameReferenceElement.isPhysical() ? annotationNameReferenceElement : field.getNameIdentifier(), - message, - ProblemHighlightType.WEAK_WARNING, - new ChangeNullableDefaultsFix(notNull, nullable, manager)); - return; - } + if (!checkNonStandardAnnotations(field, annotated, manager, anno, holder)) return; - String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD); - final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); - final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false); - final PsiIdentifier nameIdentifier = getter == null ? null : getter.getNameIdentifier(); - if (nameIdentifier != null && nameIdentifier.isPhysical()) { - if (PropertyUtil.isSimpleGetter(getter)) { - AnnotateMethodFix getterAnnoFix = new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)) { - @Override - public int shouldAnnotateBaseMethod(PsiMethod method, PsiMethod superMethod, Project project) { - return 1; - } - }; - if (REPORT_NOT_ANNOTATED_GETTER) { - if (!manager.hasNullability(getter) && !TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) { - holder.registerProblem(nameIdentifier, InspectionsBundle - .message("inspection.nullable.problems.annotated.field.getter.not.annotated", getPresentableAnnoName(field)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); - } - } - if (annotated.isDeclaredNotNull && isNullableNotInferred(getter, false) || - annotated.isDeclaredNullable && isNotNullNotInferred(getter, false, false)) { - holder.registerProblem(nameIdentifier, InspectionsBundle.message( - "inspection.nullable.problems.annotated.field.getter.conflict", getPresentableAnnoName(field), getPresentableAnnoName(getter)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); - } - } - } - - final PsiClass containingClass = field.getContainingClass(); - final PsiMethod setter = PropertyUtil.findPropertySetter(containingClass, propName, isStatic, false); - if (setter != null && setter.isPhysical()) { - final PsiParameter[] parameters = setter.getParameterList().getParameters(); - assert parameters.length == 1 : setter.getText(); - final PsiParameter parameter = parameters[0]; - LOG.assertTrue(parameter != null, setter.getText()); - AddAnnotationPsiFix addAnnoFix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove)); - if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { - final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assertValidElement(setter, parameter, nameIdentifier1); - holder.registerProblem(nameIdentifier1, - InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated", - getPresentableAnnoName(field)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - addAnnoFix); - } - if (PropertyUtil.isSimpleSetter(setter)) { - if (annotated.isDeclaredNotNull && isNullableNotInferred(parameter, false)) { - final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assertValidElement(setter, parameter, nameIdentifier1); - holder.registerProblem(nameIdentifier1, InspectionsBundle.message( - "inspection.nullable.problems.annotated.field.setter.parameter.conflict", - getPresentableAnnoName(field), getPresentableAnnoName(parameter)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - addAnnoFix); - } - } - } + checkAccessors(field, annotated, project, manager, anno, annoToRemove, holder); if (REQUIRE_NOTNULL_FIELDS_INITIALIZED) { - if (annotated.isDeclaredNotNull && !HighlightControlFlowUtil.isFieldInitializedAfterObjectConstruction(field)) { - 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); - } - } + checkNotNullFieldsInitialized(field, annotated, manager, holder); } - for (PsiExpression rhs : DfaPsiUtil.findAllConstructorInitializers(field)) { - if (rhs instanceof PsiReferenceExpression) { - PsiElement target = ((PsiReferenceExpression)rhs).resolve(); - if (target instanceof PsiParameter && target.isPhysical()) { - PsiParameter parameter = (PsiParameter)target; - AddAnnotationPsiFix fix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove)); - if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { - final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); - assert nameIdentifier2 != null : parameter; - assert nameIdentifier2.isPhysical() : parameter; - holder.registerProblem(nameIdentifier2, InspectionsBundle - .message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated", - getPresentableAnnoName(field)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix); - continue; - } - if (annotated.isDeclaredNullable && isNotNullNotInferred(parameter, false, false)) { - boolean usedAsQualifier = !ReferencesSearch.search(parameter).forEach(new Processor() { - @Override - public boolean process(PsiReference reference) { - final PsiElement element = reference.getElement(); - return !(element instanceof PsiReferenceExpression && element.getParent() instanceof PsiReferenceExpression); - } - }); - if (!usedAsQualifier) { - final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); - assert nameIdentifier2 != null : parameter; - holder.registerProblem(nameIdentifier2, InspectionsBundle.message( - "inspection.nullable.problems.annotated.field.constructor.parameter.conflict", getPresentableAnnoName(field), - getPresentableAnnoName(parameter)), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - fix); - } - } - - } - } - } + checkConstructorParameters(field, annotated, manager, anno, annoToRemove, holder); } } - private void assertValidElement(PsiMethod setter, PsiParameter parameter, PsiIdentifier nameIdentifier1) { - LOG.assertTrue(nameIdentifier1 != null && nameIdentifier1.isPhysical(), setter.getText()); - LOG.assertTrue(parameter.isPhysical(), setter.getText()); - } - @Override public void visitParameter(PsiParameter parameter) { check(parameter, holder, parameter.getType()); @@ -250,6 +126,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo if (value instanceof PsiClassObjectAccessExpression) { PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(((PsiClassObjectAccessExpression)value).getOperand().getType()); if (psiClass != null && !hasStringConstructor(psiClass)) { + //noinspection DialogTitleCapitalization holder.registerProblem(value, "Custom exception class should have a constructor with a single message parameter of String type", ProblemHighlightType.GENERIC_ERROR_OR_WARNING); @@ -271,6 +148,159 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo }; } + private static boolean checkNonStandardAnnotations(PsiField field, + Annotated annotated, + NullableNotNullManager manager, String anno, @NotNull ProblemsHolder holder) { + if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) { + final PsiAnnotation notNull = AnnotationUtil.findAnnotation(field, manager.getNotNulls()); + final PsiAnnotation nullable = AnnotationUtil.findAnnotation(field, manager.getNullables()); + final PsiAnnotation annotation; + String message = "Not \'"; + if (annotated.isDeclaredNullable) { + message += nullable.getQualifiedName(); + annotation = nullable; + } else { + message += notNull.getQualifiedName(); + annotation = notNull; + } + message += "\' but \'" + anno + "\' would be used for code generation."; + final PsiJavaCodeReferenceElement annotationNameReferenceElement = annotation.getNameReferenceElement(); + holder.registerProblem(annotationNameReferenceElement != null && annotationNameReferenceElement.isPhysical() ? annotationNameReferenceElement : field.getNameIdentifier(), + message, + ProblemHighlightType.WEAK_WARNING, + new ChangeNullableDefaultsFix(notNull, nullable, manager)); + return false; + } + return true; + } + + private void checkAccessors(PsiField field, + Annotated annotated, + Project project, + NullableNotNullManager manager, final String anno, final List annoToRemove, @NotNull ProblemsHolder holder) { + String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD); + final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); + final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false); + final PsiIdentifier nameIdentifier = getter == null ? null : getter.getNameIdentifier(); + if (nameIdentifier != null && nameIdentifier.isPhysical()) { + if (PropertyUtil.isSimpleGetter(getter)) { + AnnotateMethodFix getterAnnoFix = new AnnotateMethodFix(anno, ArrayUtil.toStringArray(annoToRemove)) { + @Override + public int shouldAnnotateBaseMethod(PsiMethod method, PsiMethod superMethod, Project project) { + return 1; + } + }; + if (REPORT_NOT_ANNOTATED_GETTER) { + if (!manager.hasNullability(getter) && !TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) { + holder.registerProblem(nameIdentifier, InspectionsBundle + .message("inspection.nullable.problems.annotated.field.getter.not.annotated", getPresentableAnnoName(field)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); + } + } + if (annotated.isDeclaredNotNull && isNullableNotInferred(getter, false) || + annotated.isDeclaredNullable && isNotNullNotInferred(getter, false, false)) { + holder.registerProblem(nameIdentifier, InspectionsBundle.message( + "inspection.nullable.problems.annotated.field.getter.conflict", getPresentableAnnoName(field), getPresentableAnnoName(getter)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix); + } + } + } + + final PsiClass containingClass = field.getContainingClass(); + final PsiMethod setter = PropertyUtil.findPropertySetter(containingClass, propName, isStatic, false); + if (setter != null && setter.isPhysical()) { + final PsiParameter[] parameters = setter.getParameterList().getParameters(); + assert parameters.length == 1 : setter.getText(); + final PsiParameter parameter = parameters[0]; + LOG.assertTrue(parameter != null, setter.getText()); + AddAnnotationPsiFix addAnnoFix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove)); + if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { + final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); + assertValidElement(setter, parameter, nameIdentifier1); + holder.registerProblem(nameIdentifier1, + InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated", + getPresentableAnnoName(field)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + addAnnoFix); + } + if (PropertyUtil.isSimpleSetter(setter)) { + if (annotated.isDeclaredNotNull && isNullableNotInferred(parameter, false)) { + final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); + assertValidElement(setter, parameter, nameIdentifier1); + holder.registerProblem(nameIdentifier1, InspectionsBundle.message( + "inspection.nullable.problems.annotated.field.setter.parameter.conflict", + getPresentableAnnoName(field), getPresentableAnnoName(parameter)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + addAnnoFix); + } + } + } + } + + private static void assertValidElement(PsiMethod setter, PsiParameter parameter, PsiIdentifier nameIdentifier1) { + LOG.assertTrue(nameIdentifier1 != null && nameIdentifier1.isPhysical(), setter.getText()); + LOG.assertTrue(parameter.isPhysical(), setter.getText()); + } + + private static void checkNotNullFieldsInitialized(PsiField field, + Annotated annotated, + NullableNotNullManager manager, @NotNull ProblemsHolder holder) { + if (annotated.isDeclaredNotNull && !HighlightControlFlowUtil.isFieldInitializedAfterObjectConstruction(field)) { + 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); + } + } + } + + private void checkConstructorParameters(PsiField field, + Annotated annotated, + NullableNotNullManager manager, + String anno, List annoToRemove, @NotNull ProblemsHolder holder) { + for (PsiExpression rhs : DfaPsiUtil.findAllConstructorInitializers(field)) { + if (rhs instanceof PsiReferenceExpression) { + PsiElement target = ((PsiReferenceExpression)rhs).resolve(); + if (target instanceof PsiParameter && target.isPhysical()) { + PsiParameter parameter = (PsiParameter)target; + AddAnnotationPsiFix + fix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove)); + if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil + .isPrimitiveAndNotNull(parameter.getType())) { + final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); + assert nameIdentifier2 != null : parameter; + assert nameIdentifier2.isPhysical() : parameter; + holder.registerProblem(nameIdentifier2, InspectionsBundle + .message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated", + getPresentableAnnoName(field)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix); + continue; + } + if (annotated.isDeclaredNullable && isNotNullNotInferred(parameter, false, false)) { + boolean usedAsQualifier = !ReferencesSearch.search(parameter).forEach(new Processor() { + @Override + public boolean process(PsiReference reference) { + final PsiElement element = reference.getElement(); + return !(element instanceof PsiReferenceExpression && element.getParent() instanceof PsiReferenceExpression); + } + }); + if (!usedAsQualifier) { + final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier(); + assert nameIdentifier2 != null : parameter; + holder.registerProblem(nameIdentifier2, InspectionsBundle.message( + "inspection.nullable.problems.annotated.field.constructor.parameter.conflict", getPresentableAnnoName(field), + getPresentableAnnoName(parameter)), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + fix); + } + } + + } + } + } + } + @NotNull private static String getPresentableAnnoName(@NotNull PsiModifierListOwner owner) { NullableNotNullManager manager = NullableNotNullManager.getInstance(owner.getProject());