summaryrefslogtreecommitdiff
path: root/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
diff options
context:
space:
mode:
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.java87
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;