IDEA-135004 New “non null fields must be initialised” not helpful when DI is used
authorpeter <peter@jetbrains.com>
Fri, 6 Feb 2015 14:51:47 +0000 (15:51 +0100)
committerpeter <peter@jetbrains.com>
Fri, 6 Feb 2015 15:11:12 +0000 (16:11 +0100)
java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java
java/java-impl/src/com/intellij/codeInspection/nullable/OptionsPanel.form
java/java-tests/testData/inspection/nullableProblems/NotNullFieldNotInitializedSetting.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java

index cb2c3fda0b68d1fffda00caa7db426929a2e33b2..bda9f4be9581448eed5bb3ce568a04a35a0b1f68 100644 (file)
@@ -53,6 +53,7 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
   @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL = true;
   @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_GETTER = true;
   @SuppressWarnings({"WeakerAccess"}) public boolean IGNORE_EXTERNAL_SUPER_NOTNULL = false;
+  @SuppressWarnings({"WeakerAccess"}) public boolean REQUIRE_NOTNULL_FIELDS_INITIALIZED = true;
   @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED = false;
   @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_SETTER_PARAMETER = true;
   @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true; // remains for test
@@ -67,7 +68,8 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
       String name = child.getAttributeValue("name");
       String value = child.getAttributeValue("value");
       if ("IGNORE_EXTERNAL_SUPER_NOTNULL".equals(name) && "false".equals(value) ||
-          "REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED".equals(name) && "false".equals(value)) {
+          "REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED".equals(name) && "false".equals(value) ||
+          "REQUIRE_NOTNULL_FIELDS_INITIALIZED".equals(name) && "true".equals(value)) {
         node.removeContent(child);
       }
     }
@@ -178,12 +180,14 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo
           }
 
           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);
+          if (REQUIRE_NOTNULL_FIELDS_INITIALIZED) {
+            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);
+              }
             }
           }
 
index b860a937d4126bf8a32d0446cfd1ea3a866c9b99..125bb6a2c11bbcd71a114b34ae698f2821131b30 100644 (file)
@@ -40,6 +40,7 @@ public class NullableStuffInspection extends NullableStuffInspectionBase {
     private JButton myConfigureAnnotationsButton;
     private JCheckBox myIgnoreExternalSuperNotNull;
     private JCheckBox myNNParameterOverridesNA;
+    private JCheckBox myRequireNNFieldsInitialized;
 
     private OptionsPanel() {
       super(new BorderLayout());
@@ -56,6 +57,7 @@ public class NullableStuffInspection extends NullableStuffInspectionBase {
       myNNParameterOverridesNA.addActionListener(actionListener);
       myReportNotAnnotatedGetter.addActionListener(actionListener);
       myIgnoreExternalSuperNotNull.addActionListener(actionListener);
+      myRequireNNFieldsInitialized.addActionListener(actionListener);
       myConfigureAnnotationsButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
@@ -74,6 +76,7 @@ public class NullableStuffInspection extends NullableStuffInspectionBase {
       myReportNotAnnotatedGetter.setSelected(REPORT_NOT_ANNOTATED_GETTER);
       myIgnoreExternalSuperNotNull.setSelected(IGNORE_EXTERNAL_SUPER_NOTNULL);
       myNNParameterOverridesNA.setSelected(REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED);
+      myRequireNNFieldsInitialized.setSelected(REQUIRE_NOTNULL_FIELDS_INITIALIZED);
 
       myIgnoreExternalSuperNotNull.setEnabled(myNAMethodOverridesNN.isSelected());
     }
@@ -84,6 +87,7 @@ public class NullableStuffInspection extends NullableStuffInspectionBase {
       REPORT_NOT_ANNOTATED_GETTER = myReportNotAnnotatedGetter.isSelected();
       IGNORE_EXTERNAL_SUPER_NOTNULL = myIgnoreExternalSuperNotNull.isSelected();
       REPORT_NOTNULL_PARAMETERS_OVERRIDES_NOT_ANNOTATED = myNNParameterOverridesNA.isSelected();
+      REQUIRE_NOTNULL_FIELDS_INITIALIZED = myRequireNNFieldsInitialized.isSelected();
       REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL;
 
       myIgnoreExternalSuperNotNull.setEnabled(myNAMethodOverridesNN.isSelected());
index 34c5535fa6fd0d13dd54da7a5627c64cc44c9f8a..c9d38f447b364cf2f2c462b6b5ed7c91297c2734 100644 (file)
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInspection.nullable.NullableStuffInspection.OptionsPanel">
-  <grid id="cc1c9" binding="myPanel" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+  <grid id="cc1c9" binding="myPanel" layout-manager="GridLayoutManager" row-count="8" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
     <margin top="0" left="0" bottom="0" right="0"/>
     <constraints>
-      <xy x="69" y="57" width="634" height="235"/>
+      <xy x="69" y="57" width="634" height="239"/>
     </constraints>
     <properties/>
     <border type="none"/>
     <children>
       <vspacer id="c3eef">
         <constraints>
-          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
         </constraints>
       </vspacer>
       <component id="2f304" class="javax.swing.JCheckBox" binding="myReportNotAnnotatedGetter">
@@ -39,7 +39,7 @@
       </component>
       <component id="ef852" class="javax.swing.JButton" binding="myConfigureAnnotationsButton" default-binding="true">
         <constraints>
-          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
         </constraints>
         <properties>
           <text resource-bundle="messages/InspectionsBundle" key="configure.annotations.option"/>
           <text value="Report @NotNull &amp;parameters overriding non-annotated"/>
         </properties>
       </component>
+      <component id="f6e46" class="javax.swing.JCheckBox" binding="myRequireNNFieldsInitialized">
+        <constraints>
+          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties>
+          <text value="Require @NotNull fields to be initialized explicitly"/>
+        </properties>
+      </component>
     </children>
   </grid>
 </form>
diff --git a/java/java-tests/testData/inspection/nullableProblems/NotNullFieldNotInitializedSetting.java b/java/java-tests/testData/inspection/nullableProblems/NotNullFieldNotInitializedSetting.java
new file mode 100644 (file)
index 0000000..5513b01
--- /dev/null
@@ -0,0 +1,9 @@
+import org.jetbrains.annotations.*;
+
+class Test {
+  @NotNull Object member;
+
+  private void accessMember() {
+    member = new Object();
+  }
+}
\ No newline at end of file
index 0b8e6c086b16394297685231e02552a89aae943f..40302703f0455b48223dc337d3c9017bda527524 100644 (file)
@@ -48,7 +48,13 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
   public void testNullableFieldNotnullParam() throws Exception{ doTest(); }
   public void testNotNullFieldNullableParam() throws Exception{ doTest(); }
   public void testNotNullCustomException() throws Exception{ doTest(); }
+
   public void testNotNullFieldNotInitialized() throws Exception{ doTest(); }
+  public void testNotNullFieldNotInitializedSetting() {
+    myInspection.REQUIRE_NOTNULL_FIELDS_INITIALIZED = false;
+    doTest();
+  }
+
   public void testNotNullAnnotationChecksInChildClassMethods() { doTest(); }
 
   public void testGetterSetterProblems() throws Exception{ doTest(); }