mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 02:09:59 +07:00
NullableStuffInspection: an option to not complain about generated implementation (IDEA-187625)
This commit is contained in:
@@ -4,6 +4,7 @@ package com.intellij.codeInspection;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
|
||||
import com.intellij.codeInspection.nullable.NullableStuffInspectionBase;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -83,9 +84,9 @@ public class AnnotateMethodFix implements LocalQuickFix {
|
||||
for (PsiMethod psiMethod : methods) {
|
||||
ReadAction.run(() -> {
|
||||
if (psiMethod.isPhysical() &&
|
||||
psiMethod.getManager().isInProject(psiMethod) &&
|
||||
AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) &&
|
||||
!AnnotationUtil.isAnnotated(psiMethod, myAnnotation, CHECK_EXTERNAL | CHECK_TYPE)) {
|
||||
!AnnotationUtil.isAnnotated(psiMethod, myAnnotation, CHECK_EXTERNAL | CHECK_TYPE) &&
|
||||
!NullableStuffInspectionBase.shouldSkipOverriderAsGenerated(psiMethod)) {
|
||||
toAnnotate.add(psiMethod);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -71,11 +71,13 @@ class AnnotateOverriddenMethodParameterFix implements LocalQuickFix {
|
||||
|
||||
PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
for (PsiMethod psiMethod : methods) {
|
||||
if (NullableStuffInspectionBase.shouldSkipOverriderAsGenerated(psiMethod)) continue;
|
||||
|
||||
PsiParameter[] psiParameters = psiMethod.getParameterList().getParameters();
|
||||
if (index >= psiParameters.length) continue;
|
||||
PsiParameter psiParameter = psiParameters[index];
|
||||
if (PsiManager.getInstance(project).isInProject(psiMethod) && AddAnnotationPsiFix.isAvailable(psiMethod, myAnnotation)) {
|
||||
toAnnotate.add(psiParameter);
|
||||
|
||||
if (AddAnnotationPsiFix.isAvailable(psiMethod, myAnnotation)) {
|
||||
toAnnotate.add(psiParameters[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,12 @@ import com.intellij.codeInspection.dataFlow.Nullness;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
@@ -844,14 +847,13 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
|
||||
hasAnnotatedParameter |= parameterAnnotated[i];
|
||||
}
|
||||
if (hasAnnotatedParameter || annotated.isDeclaredNotNull && !hasInheritableNotNull(method)) {
|
||||
PsiManager manager = method.getManager();
|
||||
final String defaultNotNull = nullableManager.getDefaultNotNull();
|
||||
final boolean superMethodApplicable = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull);
|
||||
PsiMethod[] overridings =
|
||||
OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
|
||||
boolean methodQuickFixSuggested = false;
|
||||
for (PsiMethod overriding : overridings) {
|
||||
if (!manager.isInProject(overriding)) continue;
|
||||
if (shouldSkipOverriderAsGenerated(overriding)) continue;
|
||||
|
||||
if (!methodQuickFixSuggested
|
||||
&& annotated.isDeclaredNotNull
|
||||
@@ -908,6 +910,14 @@ public class NullableStuffInspectionBase extends AbstractBaseJavaLocalInspection
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldSkipOverriderAsGenerated(PsiMethod overriding) {
|
||||
if (Registry.is("idea.report.nullity.missing.in.generated.overriders")) return false;
|
||||
|
||||
PsiFile file = overriding.getContainingFile();
|
||||
VirtualFile virtualFile = file != null ? file.getVirtualFile() : null;
|
||||
return virtualFile != null && GeneratedSourcesFilter.isGeneratedSourceByAnyFilter(virtualFile, overriding.getProject());
|
||||
}
|
||||
|
||||
private static boolean isNotNullNotInferred(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean skipExternal) {
|
||||
Project project = owner.getProject();
|
||||
NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface MyTestClass {
|
||||
@NotNull
|
||||
String implementMe(@NotNull String arg);
|
||||
}
|
||||
|
||||
public class MyRealTestClass implements MyTestClass {
|
||||
@NotNull
|
||||
String implementMe(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface MyTestClass {
|
||||
@NotNull
|
||||
String implementMe(@NotNull String arg);
|
||||
}
|
||||
|
||||
public class MyRealTestClass implements MyTestClass {
|
||||
String implementMe(@NotNull String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface MyTestClass {
|
||||
@NotNull<caret>
|
||||
String implementMe(@NotNull String arg);
|
||||
}
|
||||
|
||||
public class MyRealTestClass implements MyTestClass {
|
||||
String implementMe(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface MyTestClass {
|
||||
@NotNull
|
||||
String implementMe(@NotNull<caret> String arg);
|
||||
}
|
||||
|
||||
public class MyRealTestClass implements MyTestClass {
|
||||
String implementMe(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package foo;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
interface MyTestClass {
|
||||
@NotNull
|
||||
String implementMe();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.nullable.NullableStuffInspection;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AnnotateMethodInGeneratedFilesTest extends LightCodeInsightFixtureTestCase {
|
||||
private final GeneratedSourcesFilter myGeneratedSourcesFilter = new GeneratedSourcesFilter() {
|
||||
@Override
|
||||
public boolean isGeneratedSource(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
return file.getName().startsWith("Gen");
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() +
|
||||
"/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethodInGeneratedFiles";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
Registry.get("idea.report.nullity.missing.in.generated.overriders").setValue(false, getTestRootDisposable());
|
||||
myFixture.enableInspections(NullableStuffInspection.class);
|
||||
Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).registerExtension(myGeneratedSourcesFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).unregisterExtension(myGeneratedSourcesFilter);
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
public void testAnnotateOverriddenMethod() {
|
||||
doTest("Annotate overridden methods");
|
||||
}
|
||||
|
||||
public void testAnnotateOverriddenParameters() {
|
||||
doTest("Annotate overridden method parameters");
|
||||
}
|
||||
|
||||
private void doTest(String quickFixName) {
|
||||
PsiClass generated =
|
||||
myFixture.addClass("public class GenMyTestClass implements MyTestClass {String implementMe(String arg) { return \"\"; } }");
|
||||
String generatedTextBefore = generated.getText();
|
||||
|
||||
myFixture.configureByFile("before" + getTestName(false) + ".java");
|
||||
myFixture.launchAction(myFixture.findSingleIntention(quickFixName));
|
||||
myFixture.checkResultByFile("after" + getTestName(false) + ".java");
|
||||
assertEquals(generatedTextBefore, generated.getText());
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,13 @@ package com.intellij.java.codeInspection;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInspection.nullable.NullableStuffInspection;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
@@ -37,6 +42,13 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
|
||||
};
|
||||
private NullableStuffInspection myInspection = new NullableStuffInspection();
|
||||
|
||||
private final GeneratedSourcesFilter myGeneratedSourcesFilter = new GeneratedSourcesFilter() {
|
||||
@Override
|
||||
public boolean isGeneratedSource(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
return file.getName().startsWith("Gen");
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
@@ -57,11 +69,13 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myInspection.REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = false;
|
||||
Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).registerExtension(myGeneratedSourcesFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myInspection = null;
|
||||
Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).unregisterExtension(myGeneratedSourcesFilter);
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@@ -105,6 +119,13 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testOverriddenMethodsInGeneratedCode() {
|
||||
Registry.get("idea.report.nullity.missing.in.generated.overriders").setValue(false, getTestRootDisposable());
|
||||
myInspection.REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true;
|
||||
myFixture.addClass("package foo; public class GenMyTestClass implements MyTestClass { String implementMe() {} }");
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testOverriddenViaMethodReference() { doTest(); }
|
||||
public void testOverridingExternalNotNull() { doTest(); }
|
||||
|
||||
|
||||
@@ -674,6 +674,9 @@ ide.dfa.state.limit.description=Maximal allowed number of instruction states ana
|
||||
idea.dfa.live.variables.analysis=true
|
||||
idea.dfa.live.variables.analysis.description=Whether to flush dead variables when they're not needed when performing data flow analysis
|
||||
|
||||
idea.report.nullity.missing.in.generated.overriders=true
|
||||
idea.report.nullity.missing.in.generated.overriders.description=Whether "@NotNull/@Nullable problems" inspection should complain about overriding methods or parameters missing @NotNull, which occur in generated code
|
||||
|
||||
ide.ignore.call.result.inspection.honor.inferred.pure=true
|
||||
ide.ignore.call.result.inspection.honor.inferred.pure.description=Whether inferred @Contract(pure=true) annotations should be taken into account in ''Result of method call ignored'' inspection
|
||||
|
||||
|
||||
Reference in New Issue
Block a user