mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
NullableStuffInspectionBase: break field analysis into smaller methods
This commit is contained in:
+158
-128
@@ -101,142 +101,18 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
|
||||
final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable();
|
||||
final List<String> 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<PsiReference>() {
|
||||
@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<String> 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<String> 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<PsiReference>() {
|
||||
@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());
|
||||
|
||||
Reference in New Issue
Block a user