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;
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)
*/
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;
/**
* 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);
/**
* Message of the issue.
*/
+ @CheckForNull
String message();
/**
/**
* 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();
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);
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();
return ruleKey;
}
+ @CheckForNull
@Override
public String message() {
return message;
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;
}
@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;
}
}
*/
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;
/**
* The {@link InputFile} this measure belongs to. Returns null if measure is global to the project.
*/
- @Nullable
+ @CheckForNull
InputFile inputFile();
Metric<G> metric();
*/
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;
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();
}
*/
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;
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;
this.value = builder.value;
}
- @Nullable
+ @CheckForNull
@Override
public InputFile inputFile() {
return inputFile;
*/
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");
@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;
}
}
*/
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 {
@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"))