From: Julien HENRY Date: Tue, 4 Aug 2015 08:23:52 +0000 (+0200) Subject: Rework new measure API X-Git-Tag: 5.2-RC1~856 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F457%2Fhead;p=sonarqube.git Rework new measure API --- diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java index ca06e245d68..7b6506cb334 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java @@ -19,6 +19,10 @@ */ package org.sonar.xoo.lang; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.sonar.api.batch.fs.InputFile; @@ -31,11 +35,6 @@ import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.xoo.Xoo; -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.List; - /** * Parse files *.xoo.measures */ @@ -89,7 +88,7 @@ public class MeasureSensor implements Sensor { } NewMeasure newMeasure = context.newMeasure() .forMetric(metric) - .onFile(xooFile); + .on(xooFile); if (Boolean.class.equals(metric.valueType())) { newMeasure.withValue(Boolean.parseBoolean(value)); } else if (Integer.class.equals(metric.valueType())) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java index f705f249e6e..97059241af5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java @@ -207,19 +207,19 @@ public class JavaCpdEngine extends CpdEngine { // Save ((DefaultMeasure) context.newMeasure() .forMetric(CoreMetrics.DUPLICATED_FILES) - .onFile(inputFile) + .on(inputFile) .withValue(1)) .setFromCore() .save(); ((DefaultMeasure) context.newMeasure() .forMetric(CoreMetrics.DUPLICATED_LINES) - .onFile(inputFile) + .on(inputFile) .withValue(duplicatedLines)) .setFromCore() .save(); ((DefaultMeasure) context.newMeasure() .forMetric(CoreMetrics.DUPLICATED_BLOCKS) - .onFile(inputFile) + .on(inputFile) .withValue(duplicatedBlocks)) .setFromCore() .save(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/BatchComponentCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/BatchComponentCache.java index 67c7b28c38e..f1370167fbb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/BatchComponentCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/BatchComponentCache.java @@ -27,9 +27,7 @@ import java.util.Map; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.batch.BatchSide; -import org.sonar.api.batch.fs.InputPath; -import org.sonar.api.batch.fs.internal.DefaultInputDir; -import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.resources.Resource; @BatchSide @@ -48,11 +46,8 @@ public class BatchComponentCache { return components.get(resource.getEffectiveKey()); } - public BatchComponent get(InputPath inputPath) { - if (inputPath instanceof DefaultInputFile) { - return components.get(((DefaultInputFile) inputPath).key()); - } - return components.get(((DefaultInputDir) inputPath).key()); + public BatchComponent get(InputComponent inputComponent) { + return components.get(inputComponent.key()); } public BatchComponent add(Resource resource, @Nullable Resource parentResource) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java index adacbb99546..8cef84ace5b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java +++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java @@ -29,6 +29,7 @@ import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultInputFile; @@ -48,7 +49,6 @@ import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.resources.File; -import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.source.Symbol; import org.sonar.api.utils.KeyValueFormat; @@ -92,7 +92,6 @@ public class DefaultSensorStorage implements SensorStorage { CoreMetrics.DUPLICATIONS_DATA_KEY); private final MetricFinder metricFinder; - private final Project project; private final ModuleIssues moduleIssues; private final CoverageExclusions coverageExclusions; private final DuplicationCache duplicationCache; @@ -100,11 +99,10 @@ public class DefaultSensorStorage implements SensorStorage { private final ReportPublisher reportPublisher; private final MeasureCache measureCache; - public DefaultSensorStorage(MetricFinder metricFinder, Project project, ModuleIssues moduleIssues, + public DefaultSensorStorage(MetricFinder metricFinder, ModuleIssues moduleIssues, Settings settings, FileSystem fs, ActiveRules activeRules, DuplicationCache duplicationCache, CoverageExclusions coverageExclusions, BatchComponentCache resourceCache, ReportPublisher reportPublisher, MeasureCache measureCache) { this.metricFinder = metricFinder; - this.project = project; this.moduleIssues = moduleIssues; this.coverageExclusions = coverageExclusions; this.duplicationCache = duplicationCache; @@ -128,14 +126,10 @@ public class DefaultSensorStorage implements SensorStorage { org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m); setValueAccordingToMetricType(newMeasure, m, measureToSave); measureToSave.setFromCore(measure.isFromCore()); - InputFile inputFile = newMeasure.inputFile(); - if (inputFile != null) { - File sonarFile = getFile(inputFile); - if (coverageExclusions.accept(sonarFile, measureToSave)) { - saveMeasure(sonarFile, measureToSave); - } - } else { - saveMeasure(project, measureToSave); + InputComponent inputComponent = newMeasure.inputComponent(); + Resource resource = resourceCache.get(inputComponent).resource(); + if (coverageExclusions.accept(resource, measureToSave)) { + saveMeasure(resource, measureToSave); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java b/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java index a38d5c2df4f..cce62e7fcfb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java @@ -43,24 +43,24 @@ public final class LinesSensor implements Sensor { FileSystem fs = context.fileSystem(); for (InputFile f : fs.inputFiles(fs.predicates().hasType(Type.MAIN))) { ((DefaultMeasure) context.newMeasure() - .onFile(f) + .on(f) .forMetric(CoreMetrics.LINES) .withValue(f.lines())) - .setFromCore() - .save(); + .setFromCore() + .save(); if (f.language() == null) { // As an approximation for files with no language plugin we consider every non blank line as ncloc ((DefaultMeasure) context.newMeasure() - .onFile(f) + .on(f) .forMetric(CoreMetrics.NCLOC) .withValue(((DefaultInputFile) f).nonBlankLines())) - .save(); + .save(); // No test and no coverage on those files ((DefaultMeasure) context.newMeasure() - .onFile(f) + .on(f) .forMetric(CoreMetrics.LINES_TO_COVER) .withValue(0)) - .save(); + .save(); } } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java index 71d80a37c5b..f3b802da8e6 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java @@ -19,6 +19,10 @@ */ package org.sonar.batch.cpd; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -36,11 +40,6 @@ import org.sonar.api.measures.CoreMetrics; import org.sonar.duplications.index.CloneGroup; import org.sonar.duplications.index.ClonePart; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -88,9 +87,9 @@ public class JavaCpdEngineTest { List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 2, 4), new ClonePart("key2", 0, 15, 17))); JavaCpdEngine.save(context, inputFile, groups); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(3)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).on(inputFile).withValue(3)); verify(storage).store(new DefaultDuplication() .originBlock(inputFile, 2, 4) @@ -102,9 +101,9 @@ public class JavaCpdEngineTest { List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key1", 0, 215, 414))); JavaCpdEngine.save(context, inputFile, groups); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(400)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).on(inputFile).withValue(2)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).on(inputFile).withValue(400)); verify(storage).store(new DefaultDuplication() .originBlock(inputFile, 5, 204) @@ -116,9 +115,9 @@ public class JavaCpdEngineTest { List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214), new ClonePart("key3", 0, 25, 224))); JavaCpdEngine.save(context, inputFile, groups); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(200)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).on(inputFile).withValue(200)); verify(storage).store(new DefaultDuplication() .originBlock(inputFile, 5, 204) @@ -133,9 +132,9 @@ public class JavaCpdEngineTest { newCloneGroup(new ClonePart("key1", 0, 15, 214), new ClonePart("key3", 0, 15, 214))); JavaCpdEngine.save(context, inputFile, groups); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2)); - verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(210)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).on(inputFile).withValue(1)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).on(inputFile).withValue(2)); + verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).on(inputFile).withValue(210)); verify(storage).store(new DefaultDuplication() .originBlock(inputFile, 5, 204) diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java index 3ad99b57f31..85ccba5628b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java @@ -28,6 +28,7 @@ import org.mockito.ArgumentCaptor; import org.sonar.api.batch.fs.InputFile; 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.measure.MetricFinder; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; @@ -83,7 +84,7 @@ public class DefaultSensorStorageTest { CoverageExclusions coverageExclusions = mock(CoverageExclusions.class); when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true); resourceCache = new BatchComponentCache(); - sensorStorage = new DefaultSensorStorage(metricFinder, project, + sensorStorage = new DefaultSensorStorage(metricFinder, moduleIssues, settings, fs, activeRules, mock(DuplicationCache.class), coverageExclusions, resourceCache, mock(ReportPublisher.class), measureCache); } @@ -95,7 +96,7 @@ public class DefaultSensorStorageTest { thrown.expectMessage("Unknow metric with key: lines"); sensorStorage.store(new DefaultMeasure() - .onFile(file) + .on(file) .forMetric(CoreMetrics.LINES) .withValue(10)); } @@ -109,7 +110,7 @@ public class DefaultSensorStorageTest { resourceCache.add(sonarFile, null).setInputComponent(file); when(measureCache.put(eq(sonarFile), argumentCaptor.capture())).thenReturn(null); sensorStorage.store(new DefaultMeasure() - .onFile(file) + .on(file) .forMetric(CoreMetrics.NCLOC) .withValue(10)); @@ -120,12 +121,14 @@ public class DefaultSensorStorageTest { @Test public void shouldSaveProjectMeasureToSensorContext() { + DefaultInputModule module = new DefaultInputModule(project.getEffectiveKey()); + resourceCache.add(project, null).setInputComponent(module); ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class); when(measureCache.put(eq(project), argumentCaptor.capture())).thenReturn(null); sensorStorage.store(new DefaultMeasure() - .onProject() + .on(module) .forMetric(CoreMetrics.NCLOC) .withValue(10)); 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 @@ -28,6 +28,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} */ 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 measures(@Nullable String componetKey) { - if (componetKey == null) { - return sensorStorage.projectMeasuresByMetric.values(); - } - Map measures = sensorStorage.measuresByComponentAndMetric.get(componetKey); - return measures != null ? measures.values() : Collections.emptyList(); + public Collection measures(String componentKey) { + return sensorStorage.measuresByComponentAndMetric.row(componentKey).values(); } public Measure measure(String componetKey, Metric metric) { return measure(componetKey, metric.key()); } - public Measure measure(String componetKey, String metricKey) { - if (componetKey == null) { - return sensorStorage.projectMeasuresByMetric.get(metricKey); - } - Map measures = sensorStorage.measuresByComponentAndMetric.get(componetKey); - return measures != null ? measures.get(metricKey) : null; + public Measure 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 projectMeasuresByMetric = new HashMap<>(); - private Map> measuresByComponentAndMetric = new HashMap<>(); + private Table measuresByComponentAndMetric = HashBasedTable.create(); private Collection 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()); - } - 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.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 { /** - * 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 { /** - * The file the measure belongs to. - */ - NewMeasure onFile(InputFile file); - - /** - * Tell that the measure is global to the project. + * The {@link InputComponent} the measure belongs to. Mandatory. */ - NewMeasure onProject(); + NewMeasure 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 extends DefaultStorable implements Measure, NewMeasure { - private boolean onProject = false; - private InputFile file; + private InputComponent component; private Metric metric; private G value; private boolean fromCore = false; @@ -52,19 +47,10 @@ public class DefaultMeasure extends DefaultStorable impl } @Override - public DefaultMeasure 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 onProject() { - Preconditions.checkState(!this.onProject, "onProject already called"); - Preconditions.checkState(this.file == null, "onFile already called"); - this.onProject = true; + public DefaultMeasure 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 extends DefaultStorable impl } @Override - @CheckForNull - public InputFile inputFile() { - return file; + public InputComponent inputComponent() { + return component; } @Override @@ -138,7 +123,7 @@ public class DefaultMeasure 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 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.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.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.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 newMeasure = new DefaultMeasure(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 newMeasure = new DefaultMeasure(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() - .onProject() - .onFile(new DefaultInputFile("foo", "src/Foo.php")) + .on(new DefaultInputModule("foo")) + .on(new DefaultInputFile("foo", "src/Foo.php")) .withValue(3) .save(); }