]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5389 Reset measure and issue builders after creation of object to allow reuse
authorJulien HENRY <julien.henry@sonarsource.com>
Wed, 23 Jul 2014 16:00:32 +0000 (18:00 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Wed, 23 Jul 2014 16:17:22 +0000 (18:17 +0200)
sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssuePerLineSensor.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/MeasureBuilder.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureBuilder.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java

index bd38dee8fbcc60b0c4a2ca6958952047f2368a7b..2a811068e547c8fe4acc7a71b34349d5dfc8b5f7 100644 (file)
@@ -24,6 +24,7 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.sensor.Sensor;
 import org.sonar.api.batch.sensor.SensorContext;
 import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.batch.sensor.issue.IssueBuilder;
 import org.sonar.api.batch.sensor.measure.Measure;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.rule.RuleKey;
@@ -58,8 +59,9 @@ public class OneIssuePerLineSensor implements Sensor {
     if (linesMeasure == null) {
       LoggerFactory.getLogger(getClass()).warn("Missing measure " + CoreMetrics.LINES_KEY + " on " + file);
     } else {
+      IssueBuilder issueBuilder = context.issueBuilder();
       for (int line = 1; line <= (Integer) linesMeasure.value(); line++) {
-        context.addIssue(context.issueBuilder()
+        context.addIssue(issueBuilder
           .ruleKey(ruleKey)
           .onFile(file)
           .atLine(line)
index 873fed63243b914ff0d5cfe3d0491dbb1c61359b..234b3865ca345d85b3dc720b50e3b496c996a65c 100644 (file)
  */
 package org.sonar.api.batch.sensor;
 
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.IssueBuilder;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.MeasureBuilder;
-
 import com.google.common.annotations.Beta;
 import org.sonar.api.batch.fs.FileSystem;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.Metric;
 import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.IssueBuilder;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.MeasureBuilder;
 import org.sonar.api.config.Settings;
 
 import javax.annotation.CheckForNull;
@@ -101,7 +100,11 @@ public interface SensorContext {
 
   /**
    * Add an issue. Use {@link #issueBuilder()} to create the new issue.
-   * @return true if the new issue is registered, false if the related rule does not exist or is disabled in the Quality profile.
+   * @return <code>true</code> if the new issue is registered, <code>false</code> if:
+   * <ul>
+   * <li>the rule does not exist</li>
+   * <li>the rule is disabled in the Quality profile</li>
+   * </ul>
    */
   boolean addIssue(Issue issue);
 
index c56e623056c48afca89c94b670a6ad52658996df..a8d2512542af2ccccb30734bc5e669bc3f87ab18 100644 (file)
@@ -48,6 +48,7 @@ public interface Issue {
   /**
    * Message of the issue.
    */
+  @CheckForNull
   String message();
 
   /**
@@ -65,7 +66,7 @@ public interface Issue {
 
   /**
    * See constants in {@link org.sonar.api.rule.Severity}.
-   * Can be null before issue is saved to tell to use severity configured in quality profile.
+   * Can be null before issue is saved. Means to use severity configured in quality profile.
    */
   @CheckForNull
   String severity();
index 5480103b1e7d9df266dc4fb13092fda803a13b1e..f6b4fa85aaaecc58ff17bb8a7a81fd7ccf327be5 100644 (file)
@@ -56,7 +56,8 @@ public interface IssueBuilder {
   IssueBuilder onProject();
 
   /**
-   * Line of the issue. Only available for {@link #onFile(InputFile)} issues. If no line is specified then issue is supposed to be global to the file.
+   * Line of the issue. Only available for {@link #onFile(InputFile)} issues. 
+   * If no line is specified it means that issue is global to the file.
    */
   IssueBuilder atLine(int line);
 
@@ -77,7 +78,7 @@ public interface IssueBuilder {
   IssueBuilder severity(@Nullable String severity);
 
   /**
-   * Build the issue.
+   * Build the issue. After call of this method the builder is cleaned and can be used to build another issue.
    */
   Issue build();
 
index 9ca0fdd4f824cc7f22834963d529dc798967160c..f3b56f73b6c77cab8fa1a308431a3113bff8c11c 100644 (file)
@@ -70,6 +70,7 @@ public class DefaultIssue implements Issue, Serializable {
     return ruleKey;
   }
 
+  @CheckForNull
   @Override
   public String message() {
     return message;
index 62e89813f1c9e492a2a62e4a416feb77c2075a5a..fefbfb1e4c83f5f1b4a316328afbbc49ca20f395 100644 (file)
@@ -23,7 +23,6 @@ import com.google.common.base.Preconditions;
 import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.sensor.issue.Issue;
 import org.sonar.api.batch.sensor.issue.IssueBuilder;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
@@ -108,8 +107,21 @@ public class DefaultIssueBuilder implements IssueBuilder {
   }
 
   @Override
-  public Issue build() {
-    return new DefaultIssue(this);
+  public DefaultIssue build() {
+    DefaultIssue result = new DefaultIssue(this);
+    reset();
+    return result;
+  }
+
+  private void reset() {
+    key = null;
+    onProject = false;
+    path = null;
+    ruleKey = null;
+    message = null;
+    line = null;
+    effortToFix = null;
+    severity = null;
   }
 
 }
index ea606d45bd8177ee889a9dd58f0b7e1303263db9..e7805affe652e8cb782dc0b00556e49869c9a002 100644 (file)
  */
 package org.sonar.api.batch.sensor.measure;
 
-import org.sonar.api.batch.sensor.Sensor;
-
 import com.google.common.annotations.Beta;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.sensor.Sensor;
 
-import javax.annotation.Nullable;
+import javax.annotation.CheckForNull;
 
 import java.io.Serializable;
 
@@ -39,7 +38,7 @@ public interface Measure<G extends Serializable> {
   /**
    * The {@link InputFile} this measure belongs to. Returns null if measure is global to the project.
    */
-  @Nullable
+  @CheckForNull
   InputFile inputFile();
 
   Metric<G> metric();
index 05b16bee9324e33af51517e2b506e27bc7be35bc..8dcfd9e37dd317077cdcf7556949ed5559cdb7b5 100644 (file)
  */
 package org.sonar.api.batch.sensor.measure;
 
-import org.sonar.api.batch.measure.Metric;
-
 import com.google.common.annotations.Beta;
 import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.Metric;
 
 import java.io.Serializable;
 
@@ -54,7 +53,7 @@ public interface MeasureBuilder<G extends Serializable> {
   MeasureBuilder<G> withValue(G value);
 
   /**
-   * Build the measure.
+   * Build the measure. After call of this method the builder is cleaned and can be used to build another measure.
    */
   Measure<G> build();
 }
index 6664a055b8ac6c17a53755a76dbac230287fa0ab..e51f548d529234d6925ca2e9742cafd9c97f3e76 100644 (file)
@@ -19,8 +19,6 @@
  */
 package org.sonar.api.batch.sensor.measure.internal;
 
-import org.sonar.api.batch.sensor.measure.Measure;
-
 import com.google.common.base.Preconditions;
 import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.builder.HashCodeBuilder;
@@ -28,8 +26,9 @@ import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.sensor.measure.Measure;
 
-import javax.annotation.Nullable;
+import javax.annotation.CheckForNull;
 
 import java.io.Serializable;
 
@@ -48,7 +47,7 @@ public class DefaultMeasure<G extends Serializable> implements Measure<G>, Seria
     this.value = builder.value;
   }
 
-  @Nullable
+  @CheckForNull
   @Override
   public InputFile inputFile() {
     return inputFile;
index a1ef2e508d9d6daa3726a5bb446654881cf7141c..31fddee765299fb18b70829710e218474bd2abf2 100644 (file)
  */
 package org.sonar.api.batch.sensor.measure.internal;
 
-import org.sonar.api.batch.sensor.measure.MeasureBuilder;
-
 import com.google.common.base.Preconditions;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.sensor.measure.MeasureBuilder;
 
 import java.io.Serializable;
 
 public class DefaultMeasureBuilder<G extends Serializable> implements MeasureBuilder<G> {
 
-  Boolean onProject = null;
+  boolean onProject = false;
   InputFile file;
   Metric<G> metric;
   G value;
 
   @Override
   public DefaultMeasureBuilder<G> onFile(InputFile inputFile) {
-    onProject(false);
-    Preconditions.checkNotNull(inputFile, "inputFile should be non null");
+    Preconditions.checkState(!this.onProject, "onProject already called");
+    Preconditions.checkState(this.file == null, "onFile already called");
+    Preconditions.checkNotNull(inputFile, "InputFile should be non null");
     this.file = inputFile;
     return this;
   }
 
   @Override
   public DefaultMeasureBuilder<G> onProject() {
-    onProject(true);
-    this.file = null;
+    Preconditions.checkState(!this.onProject, "onProject already called");
+    Preconditions.checkState(this.file == null, "onFile already called");
+    this.onProject = true;
     return this;
   }
 
-  private void onProject(boolean isOnProject) {
-    Preconditions.checkState(this.onProject == null, "onFile or onProject can be called only once");
-    this.onProject = isOnProject;
-  }
-
   @Override
   public DefaultMeasureBuilder<G> forMetric(Metric<G> metric) {
     Preconditions.checkState(metric != null, "Metric already defined");
@@ -72,6 +68,15 @@ public class DefaultMeasureBuilder<G extends Serializable> implements MeasureBui
 
   @Override
   public DefaultMeasure<G> build() {
-    return new DefaultMeasure<G>(this);
+    DefaultMeasure<G> result = new DefaultMeasure<G>(this);
+    reset();
+    return result;
+  }
+
+  private void reset() {
+    onProject = false;
+    file = null;
+    metric = null;
+    value = null;
   }
 }
index c75a31679b2da3146f4006e0e2656854f25a7141..b894ffec0920529da84ce1450a26596a90df06cd 100644 (file)
  */
 package org.sonar.api.batch.sensor.measure.internal;
 
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder;
-
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.Measure;
 import org.sonar.api.measures.CoreMetrics;
+
 import static org.fest.assertions.Assertions.assertThat;
 
 public class DefaultMeasureTest {
@@ -63,7 +62,7 @@ public class DefaultMeasureTest {
   @Test
   public void not_allowed_to_call_onFile_and_onProject() {
     thrown.expect(IllegalStateException.class);
-    thrown.expectMessage("onFile or onProject can be called only once");
+    thrown.expectMessage("onProject already called");
     new DefaultMeasureBuilder<Integer>()
       .onProject()
       .onFile(new DefaultInputFile("src/Foo.php"))