aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2015-08-04 10:23:52 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2015-08-04 15:53:02 +0200
commit15ec53105ce82aa3d85ad322b0a2cca16cfe7d0b (patch)
treebc8a60b3cee95ae46570517f5f20f15d4fd436d7 /sonar-plugin-api
parent5abbda8671afd4ba05653277e72b6a3005acff03 (diff)
downloadsonarqube-15ec53105ce82aa3d85ad322b0a2cca16cfe7d0b.tar.gz
sonarqube-15ec53105ce82aa3d85ad322b0a2cca16cfe7d0b.zip
Rework new measure API
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputComponent.java5
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java57
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java13
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java16
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java45
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java11
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java22
9 files changed, 58 insertions, 117 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputComponent.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputComponent.java
index e4f66be54b0..a2c7d5f59c0 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputComponent.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputComponent.java
@@ -29,6 +29,11 @@ package org.sonar.api.batch.fs;
public interface InputComponent {
/**
+ * Component key shared by all part of SonarQube (batch, server, WS...)
+ */
+ String key();
+
+ /**
* Is the component an {@link InputFile}
*/
boolean isFile();
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java
index 9a49dd4de66..2a213fc6629 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputComponent.java
@@ -26,8 +26,6 @@ import org.sonar.api.batch.fs.InputComponent;
*/
public abstract class DefaultInputComponent implements InputComponent {
- public abstract String key();
-
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
index 8bec2b65ea4..0b506e112b4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
@@ -20,6 +20,8 @@
package org.sonar.api.batch.sensor.internal;
import com.google.common.annotations.Beta;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
@@ -30,14 +32,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import org.sonar.api.batch.AnalysisMode;
-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.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputDir;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DefaultTextPointer;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
@@ -128,24 +124,16 @@ public class SensorContextTester implements SensorContext {
return new DefaultMeasure<>(sensorStorage);
}
- public Collection<Measure> measures(@Nullable String componetKey) {
- if (componetKey == null) {
- return sensorStorage.projectMeasuresByMetric.values();
- }
- Map<String, Measure> measures = sensorStorage.measuresByComponentAndMetric.get(componetKey);
- return measures != null ? measures.values() : Collections.<Measure>emptyList();
+ public Collection<Measure> measures(String componentKey) {
+ return sensorStorage.measuresByComponentAndMetric.row(componentKey).values();
}
public <G extends Serializable> Measure<G> measure(String componetKey, Metric<G> metric) {
return measure(componetKey, metric.key());
}
- public Measure measure(String componetKey, String metricKey) {
- if (componetKey == null) {
- return sensorStorage.projectMeasuresByMetric.get(metricKey);
- }
- Map<String, Measure> measures = sensorStorage.measuresByComponentAndMetric.get(componetKey);
- return measures != null ? measures.get(metricKey) : null;
+ public <G extends Serializable> Measure<G> measure(String componentKey, String metricKey) {
+ return sensorStorage.measuresByComponentAndMetric.row(componentKey).get(metricKey);
}
@Override
@@ -254,7 +242,7 @@ public class SensorContextTester implements SensorContext {
public boolean isQuick() {
return this.isSingle;
}
-
+
public void setSingle(boolean single) {
this.isSingle = single;
}
@@ -262,8 +250,7 @@ public class SensorContextTester implements SensorContext {
private static class InMemorySensorStorage implements SensorStorage {
- private Map<String, Measure> projectMeasuresByMetric = new HashMap<>();
- private Map<String, Map<String, Measure>> measuresByComponentAndMetric = new HashMap<>();
+ private Table<String, String, Measure> measuresByComponentAndMetric = HashBasedTable.create();
private Collection<Issue> allIssues = new ArrayList<>();
@@ -274,15 +261,7 @@ public class SensorContextTester implements SensorContext {
@Override
public void store(Measure measure) {
- String key = getKey(measure.inputFile());
- if (key == null) {
- projectMeasuresByMetric.put(measure.metric().key(), measure);
- } else {
- if (!measuresByComponentAndMetric.containsKey(key)) {
- measuresByComponentAndMetric.put(key, new HashMap<String, Measure>());
- }
- measuresByComponentAndMetric.get(key).put(measure.metric().key(), measure);
- }
+ measuresByComponentAndMetric.row(measure.inputComponent().key()).put(measure.metric().key(), measure);
}
@Override
@@ -297,32 +276,18 @@ public class SensorContextTester implements SensorContext {
@Override
public void store(DefaultHighlighting highlighting) {
- highlightingByComponent.put(getKey(highlighting.inputFile()), highlighting);
+ highlightingByComponent.put(highlighting.inputFile().key(), highlighting);
}
@Override
public void store(DefaultCoverage defaultCoverage) {
- String key = getKey(defaultCoverage.inputFile());
+ String key = defaultCoverage.inputFile().key();
if (!coverageByComponent.containsKey(key)) {
coverageByComponent.put(key, new EnumMap<CoverageType, DefaultCoverage>(CoverageType.class));
}
coverageByComponent.get(key).put(defaultCoverage.type(), defaultCoverage);
}
- @CheckForNull
- private static String getKey(@Nullable InputPath inputPath) {
- if (inputPath == null) {
- return null;
- }
- if (inputPath instanceof InputFile) {
- return ((DefaultInputFile) inputPath).key();
- }
- if (inputPath instanceof InputDir) {
- return ((DefaultInputDir) inputPath).key();
- }
- throw new IllegalStateException("Unknow component " + inputPath);
- }
-
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java
index 87b6ff67d44..df800a0bba2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueLocation.java
@@ -41,7 +41,7 @@ public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
}
@Override
- public NewIssueLocation at(TextRange location) {
+ public DefaultIssueLocation at(TextRange location) {
Preconditions.checkState(this.component != null, "at() should be called after on()");
Preconditions.checkState(this.component.isFile(), "at() should be called only for an InputFile.");
DefaultInputFile file = (DefaultInputFile) this.component;
@@ -51,7 +51,7 @@ public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
}
@Override
- public NewIssueLocation message(String message) {
+ public DefaultIssueLocation message(String message) {
Preconditions.checkNotNull(message, "Message can't be null");
Preconditions.checkArgument(message.length() <= MESSAGE_MAX_SIZE,
"Message of an issue can't be greater than " + MESSAGE_MAX_SIZE + ": [" + message + "] size is " + message.length());
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java
index 4f82f8587b7..469d073e1d9 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/Measure.java
@@ -20,12 +20,9 @@
package org.sonar.api.batch.sensor.measure;
import com.google.common.annotations.Beta;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.measure.Metric;
-
-import javax.annotation.CheckForNull;
-
import java.io.Serializable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
/**
* Measure on File, Directory or Project.
@@ -36,11 +33,9 @@ import java.io.Serializable;
public interface Measure<G extends Serializable> {
/**
- * The file the measure belong to.
- * @return null if measure is on project
+ * The {@link InputComponent} this measure belongs to.
*/
- @CheckForNull
- InputFile inputFile();
+ InputComponent inputComponent();
/**
* The metric this measure belong to.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java
index 412e4df9203..82f190ccd6c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java
@@ -20,28 +20,22 @@
package org.sonar.api.batch.sensor.measure;
import com.google.common.annotations.Beta;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.measure.Metric;
-
import java.io.Serializable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
/**
* Builder to create new Measure.
* Should not be implemented by client.
- * @since 5.1
+ * @since 5.2
*/
@Beta
public interface NewMeasure<G extends Serializable> {
/**
- * The file the measure belongs to.
- */
- NewMeasure<G> onFile(InputFile file);
-
- /**
- * Tell that the measure is global to the project.
+ * The {@link InputComponent} the measure belongs to. Mandatory.
*/
- NewMeasure<G> onProject();
+ NewMeasure<G> on(InputComponent component);
/**
* Set the metric this measure belong to.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
index f6cccb2f2e7..d80e2042afc 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasure.java
@@ -19,26 +19,21 @@
*/
package org.sonar.api.batch.sensor.measure.internal;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
import com.google.common.base.Preconditions;
+import java.io.Serializable;
+import javax.annotation.Nullable;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
-import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.NewMeasure;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.io.Serializable;
-
public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
- private boolean onProject = false;
- private InputFile file;
+ private InputComponent component;
private Metric<G> metric;
private G value;
private boolean fromCore = false;
@@ -52,19 +47,10 @@ public class DefaultMeasure<G extends Serializable> extends DefaultStorable impl
}
@Override
- public DefaultMeasure<G> onFile(InputFile inputFile) {
- 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 DefaultMeasure<G> onProject() {
- Preconditions.checkState(!this.onProject, "onProject already called");
- Preconditions.checkState(this.file == null, "onFile already called");
- this.onProject = true;
+ public DefaultMeasure<G> on(InputComponent component) {
+ Preconditions.checkArgument(component != null, "Component can't be null");
+ Preconditions.checkState(this.component == null, "on() already called");
+ this.component = component;
return this;
}
@@ -113,9 +99,8 @@ public class DefaultMeasure<G extends Serializable> extends DefaultStorable impl
}
@Override
- @CheckForNull
- public InputFile inputFile() {
- return file;
+ public InputComponent inputComponent() {
+ return component;
}
@Override
@@ -138,7 +123,7 @@ public class DefaultMeasure<G extends Serializable> extends DefaultStorable impl
}
DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
return new EqualsBuilder()
- .append(file, rhs.file)
+ .append(component, rhs.component)
.append(metric, rhs.metric)
.append(value, rhs.value)
.isEquals();
@@ -146,11 +131,7 @@ public class DefaultMeasure<G extends Serializable> extends DefaultStorable impl
@Override
public int hashCode() {
- return new HashCodeBuilder(27, 45).
- append(file).
- append(metric).
- append(value).
- toHashCode();
+ return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
}
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
index 7c15bd2c3f9..35ad51f3c40 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
@@ -27,6 +27,7 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
@@ -105,14 +106,14 @@ public class SensorContextTesterTest {
assertThat(tester.measures("foo:src/Foo.java")).isEmpty();
assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNull();
tester.<Integer>newMeasure()
- .onFile(new DefaultInputFile("foo", "src/Foo.java"))
+ .on(new DefaultInputFile("foo", "src/Foo.java"))
.forMetric(CoreMetrics.NCLOC)
.withValue(2)
.save();
assertThat(tester.measures("foo:src/Foo.java")).hasSize(1);
assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
tester.<Integer>newMeasure()
- .onFile(new DefaultInputFile("foo", "src/Foo.java"))
+ .on(new DefaultInputFile("foo", "src/Foo.java"))
.forMetric(CoreMetrics.LINES)
.withValue(4)
.save();
@@ -120,12 +121,12 @@ public class SensorContextTesterTest {
assertThat(tester.measure("foo:src/Foo.java", "ncloc")).isNotNull();
assertThat(tester.measure("foo:src/Foo.java", "lines")).isNotNull();
tester.<Integer>newMeasure()
- .onProject()
+ .on(new DefaultInputModule("foo"))
.forMetric(CoreMetrics.DIRECTORIES)
.withValue(4)
.save();
- assertThat(tester.measures(null)).hasSize(1);
- assertThat(tester.measure(null, "directories")).isNotNull();
+ assertThat(tester.measures("foo")).hasSize(1);
+ assertThat(tester.measure("foo", "directories")).isNotNull();
}
@Test
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java
index 6dae7fc2dbf..ba7af3f67c3 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/measure/internal/DefaultMeasureTest.java
@@ -19,13 +19,14 @@
*/
package org.sonar.api.batch.sensor.measure.internal;
-import org.sonar.api.batch.sensor.internal.SensorStorage;
-
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.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.measures.CoreMetrics;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -40,10 +41,10 @@ public class DefaultMeasureTest {
SensorStorage storage = mock(SensorStorage.class);
DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
.forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("foo", "src/Foo.php"))
+ .on(new DefaultInputFile("foo", "src/Foo.php"))
.withValue(3);
- assertThat(newMeasure.inputFile()).isEqualTo(new DefaultInputFile("foo", "src/Foo.php"));
+ assertThat(newMeasure.inputComponent()).isEqualTo(new DefaultInputFile("foo", "src/Foo.php"));
assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
assertThat(newMeasure.value()).isEqualTo(3);
@@ -55,12 +56,13 @@ public class DefaultMeasureTest {
@Test
public void build_project_measure() {
SensorStorage storage = mock(SensorStorage.class);
+ DefaultInputModule module = new DefaultInputModule("foo");
DefaultMeasure<Integer> newMeasure = new DefaultMeasure<Integer>(storage)
.forMetric(CoreMetrics.LINES)
- .onProject()
+ .on(module)
.withValue(3);
- assertThat(newMeasure.inputFile()).isNull();
+ assertThat(newMeasure.inputComponent()).isEqualTo(new DefaultInputModule("foo"));
assertThat(newMeasure.metric()).isEqualTo(CoreMetrics.LINES);
assertThat(newMeasure.value()).isEqualTo(3);
@@ -70,12 +72,12 @@ public class DefaultMeasureTest {
}
@Test
- public void not_allowed_to_call_onFile_and_onProject() {
+ public void not_allowed_to_call_on_twice() {
thrown.expect(IllegalStateException.class);
- thrown.expectMessage("onProject already called");
+ thrown.expectMessage("on() already called");
new DefaultMeasure<Integer>()
- .onProject()
- .onFile(new DefaultInputFile("foo", "src/Foo.php"))
+ .on(new DefaultInputModule("foo"))
+ .on(new DefaultInputFile("foo", "src/Foo.php"))
.withValue(3)
.save();
}