aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2015-03-25 10:59:50 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-03-25 15:20:10 +0100
commite157c182fb9f71f1a1bd16d48d4d09ac7b4fe92a (patch)
tree9119eb95b9e5b73e1914ba8a0f4639d8f1d14570 /sonar-batch/src
parentac44823d701c7ae3ea30ea8060c8fe28ca8ee6af (diff)
downloadsonarqube-e157c182fb9f71f1a1bd16d48d4d09ac7b4fe92a.tar.gz
sonarqube-e157c182fb9f71f1a1bd16d48d4d09ac7b4fe92a.zip
SONAR-6280 Feed duplications in compute report
Diffstat (limited to 'sonar-batch/src')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java90
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java27
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java122
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java40
5 files changed, 218 insertions, 67 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java
new file mode 100644
index 00000000000..3648f47cc12
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.report;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import org.sonar.api.batch.sensor.duplication.Duplication.Block;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.Duplication;
+import org.sonar.batch.protocol.output.BatchReport.DuplicationBlock;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+
+public class DuplicationsPublisher implements ReportPublisher {
+
+ private final ResourceCache resourceCache;
+ private final DuplicationCache duplicationCache;
+
+ public DuplicationsPublisher(ResourceCache resourceCache, DuplicationCache duplicationCache) {
+ this.resourceCache = resourceCache;
+ this.duplicationCache = duplicationCache;
+ }
+
+ @Override
+ public void publish(BatchReportWriter writer) {
+ for (final BatchResource resource : resourceCache.all()) {
+ Iterable<DefaultDuplication> dups = duplicationCache.byComponent(resource.resource().getEffectiveKey());
+ if (dups.iterator().hasNext()) {
+ Iterable<org.sonar.batch.protocol.output.BatchReport.Duplication> reportDuplications = Iterables.transform(dups,
+ new Function<DefaultDuplication, BatchReport.Duplication>() {
+ private final BatchReport.Duplication.Builder dupBuilder = BatchReport.Duplication.newBuilder();
+ private final BatchReport.DuplicationBlock.Builder blockBuilder = BatchReport.DuplicationBlock.newBuilder();
+
+ @Override
+ public BatchReport.Duplication apply(DefaultDuplication input) {
+ return toReportDuplication(resource.key(), dupBuilder, blockBuilder, input);
+ }
+
+ });
+ writer.writeComponentDuplications(resource.batchId(), reportDuplications);
+ }
+ }
+ }
+
+ private Duplication toReportDuplication(String currentComponentKey, Duplication.Builder dupBuilder, DuplicationBlock.Builder blockBuilder, DefaultDuplication input) {
+ dupBuilder.clear();
+ Block originBlock = input.originBlock();
+ blockBuilder.clear();
+ dupBuilder.setOriginBlock(blockBuilder
+ .setStartLine(originBlock.startLine())
+ .setEndLine(originBlock.startLine() + originBlock.length() - 1).build());
+ for (Block duplicate : input.duplicates()) {
+ blockBuilder.clear();
+ String componentKey = duplicate.resourceKey();
+ if (!currentComponentKey.equals(componentKey)) {
+ BatchResource sameProjectComponent = resourceCache.get(componentKey);
+ if (sameProjectComponent != null) {
+ blockBuilder.setOtherComponentRef(sameProjectComponent.batchId());
+ } else {
+ blockBuilder.setComponentKey(componentKey);
+ }
+ }
+ dupBuilder.addDuplicatedBy(blockBuilder
+ .setStartLine(duplicate.startLine())
+ .setEndLine(duplicate.startLine() + duplicate.length() - 1).build());
+ }
+ return dupBuilder.build();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
index e7c524ff52d..8aadc2180ee 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
@@ -23,7 +23,6 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
import org.sonar.api.measures.*;
import org.sonar.api.measures.Metric.Level;
import org.sonar.api.measures.Metric.ValueType;
@@ -32,8 +31,6 @@ import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.duplication.DuplicationUtils;
import org.sonar.batch.index.BatchResource;
import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.Constants;
@@ -45,19 +42,16 @@ import org.sonar.batch.scan.measure.MeasureCache;
import javax.annotation.Nullable;
import java.io.Serializable;
-import java.util.Arrays;
public class MeasuresPublisher implements ReportPublisher {
private final ResourceCache resourceCache;
private final MeasureCache measureCache;
- private final DuplicationCache duplicationCache;
private final MetricFinder metricFinder;
- public MeasuresPublisher(ResourceCache resourceCache, MeasureCache measureCache, DuplicationCache duplicationCache, MetricFinder metricFinder) {
+ public MeasuresPublisher(ResourceCache resourceCache, MeasureCache measureCache, MetricFinder metricFinder) {
this.resourceCache = resourceCache;
this.measureCache = measureCache;
- this.duplicationCache = duplicationCache;
this.metricFinder = metricFinder;
}
@@ -75,20 +69,14 @@ public class MeasuresPublisher implements ReportPublisher {
});
Iterable<org.sonar.batch.protocol.output.BatchReport.Measure> reportMeasures = Iterables.transform(batchMeasures, new Function<Measure, BatchReport.Measure>() {
- private BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder();
+ private final BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder();
@Override
public BatchReport.Measure apply(Measure input) {
return toReportMeasure(builder, input);
}
});
- Iterable<DefaultDuplication> dups = duplicationCache.byComponent(resource.resource().getEffectiveKey());
- if (dups.iterator().hasNext()) {
- org.sonar.batch.protocol.output.BatchReport.Measure dupMeasure = toReportMeasure(BatchReport.Measure.newBuilder(), dups);
- writer.writeComponentMeasures(resource.batchId(), Iterables.concat(Arrays.asList(dupMeasure), reportMeasures));
- } else {
- writer.writeComponentMeasures(resource.batchId(), reportMeasures);
- }
+ writer.writeComponentMeasures(resource.batchId(), reportMeasures);
}
}
@@ -109,15 +97,6 @@ public class MeasuresPublisher implements ReportPublisher {
return measure.getValue() != null || measure.getData() != null || isNotEmpty;
}
- private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Iterable<DefaultDuplication> dups) {
- builder.clear();
-
- builder.setValueType(MeasureValueType.STRING);
- builder.setStringValue(DuplicationUtils.toXml(dups));
- builder.setMetricKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
- return builder.build();
- }
-
private BatchReport.Measure toReportMeasure(BatchReport.Measure.Builder builder, Measure measure) {
builder.clear();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index aa35effd389..5df7f4c665d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -55,10 +55,7 @@ import org.sonar.batch.language.LanguageDistributionDecorator;
import org.sonar.batch.phases.*;
import org.sonar.batch.qualitygate.GenerateQualityGateEvents;
import org.sonar.batch.qualitygate.QualityGateVerifier;
-import org.sonar.batch.report.ComponentsPublisher;
-import org.sonar.batch.report.IssuesPublisher;
-import org.sonar.batch.report.MeasuresPublisher;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.*;
import org.sonar.batch.rule.*;
import org.sonar.batch.scan.filesystem.*;
import org.sonar.batch.scan.report.IssuesReports;
@@ -118,6 +115,7 @@ public class ModuleScanContainer extends ComponentContainer {
ComponentsPublisher.class,
IssuesPublisher.class,
MeasuresPublisher.class,
+ DuplicationsPublisher.class,
moduleDefinition.getContainerExtensions(),
// file system
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java
new file mode 100644
index 00000000000..b75efb3f275
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java
@@ -0,0 +1,122 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.report;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.sensor.duplication.Duplication;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
+import org.sonar.api.resources.Project;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DuplicationsPublisherTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private DuplicationCache duplicationCache;
+ private DuplicationsPublisher publisher;
+
+ @Before
+ public void prepare() {
+ ResourceCache resourceCache = new ResourceCache();
+ Project p = new Project("foo");
+ resourceCache.add(p, null);
+ org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
+ resourceCache.add(sampleFile, null);
+ org.sonar.api.resources.Resource sampleFile2 = org.sonar.api.resources.File.create("src/Foo2.php").setEffectiveKey("foo:src/Foo2.php");
+ resourceCache.add(sampleFile2, null);
+ duplicationCache = mock(DuplicationCache.class);
+ when(duplicationCache.byComponent(anyString())).thenReturn(Collections.<DefaultDuplication>emptyList());
+ publisher = new DuplicationsPublisher(resourceCache, duplicationCache);
+ }
+
+ @Test
+ public void publishDuplications() throws Exception {
+
+ DefaultDuplication dup1 = new DefaultDuplication()
+ .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10))
+ .isDuplicatedBy("foo:src/Foo.php", 20, 50);
+ DefaultDuplication dup2 = new DefaultDuplication()
+ .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10))
+ .isDuplicatedBy("another", 20, 50);
+ DefaultDuplication dup3 = new DefaultDuplication()
+ .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10))
+ .isDuplicatedBy("foo:src/Foo2.php", 20, 50);
+ when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2, dup3));
+
+ File outputDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+ publisher.publish(writer);
+
+ BatchReportReader reader = new BatchReportReader(outputDir);
+
+ assertThat(reader.readComponentDuplications(1)).hasSize(0);
+ List<org.sonar.batch.protocol.output.BatchReport.Duplication> componentDuplications = reader.readComponentDuplications(2);
+ assertThat(componentDuplications).hasSize(3);
+ org.sonar.batch.protocol.output.BatchReport.Duplication savedDup1 = componentDuplications.get(0);
+ assertThat(savedDup1.getOriginBlock().hasComponentKey()).isFalse();
+ assertThat(savedDup1.getOriginBlock().hasOtherComponentRef()).isFalse();
+ assertThat(savedDup1.getOriginBlock().getStartLine()).isEqualTo(1);
+ assertThat(savedDup1.getOriginBlock().getEndLine()).isEqualTo(10);
+ assertThat(savedDup1.getDuplicatedBy(0).hasComponentKey()).isFalse();
+ assertThat(savedDup1.getDuplicatedBy(0).hasOtherComponentRef()).isFalse();
+ assertThat(savedDup1.getDuplicatedBy(0).getStartLine()).isEqualTo(20);
+ assertThat(savedDup1.getDuplicatedBy(0).getEndLine()).isEqualTo(50);
+
+ org.sonar.batch.protocol.output.BatchReport.Duplication savedDup2 = componentDuplications.get(1);
+ assertThat(savedDup2.getOriginBlock().hasComponentKey()).isFalse();
+ assertThat(savedDup2.getOriginBlock().hasOtherComponentRef()).isFalse();
+ assertThat(savedDup2.getOriginBlock().getStartLine()).isEqualTo(11);
+ assertThat(savedDup2.getOriginBlock().getEndLine()).isEqualTo(20);
+ assertThat(savedDup2.getDuplicatedBy(0).getComponentKey()).isEqualTo("another");
+ assertThat(savedDup2.getDuplicatedBy(0).hasOtherComponentRef()).isFalse();
+ assertThat(savedDup2.getDuplicatedBy(0).getStartLine()).isEqualTo(20);
+ assertThat(savedDup2.getDuplicatedBy(0).getEndLine()).isEqualTo(50);
+
+ org.sonar.batch.protocol.output.BatchReport.Duplication savedDup3 = componentDuplications.get(2);
+ assertThat(savedDup3.getOriginBlock().hasComponentKey()).isFalse();
+ assertThat(savedDup3.getOriginBlock().hasOtherComponentRef()).isFalse();
+ assertThat(savedDup3.getOriginBlock().getStartLine()).isEqualTo(11);
+ assertThat(savedDup3.getOriginBlock().getEndLine()).isEqualTo(20);
+ assertThat(savedDup3.getDuplicatedBy(0).hasComponentKey()).isFalse();
+ assertThat(savedDup3.getDuplicatedBy(0).getOtherComponentRef()).isEqualTo(3);
+ assertThat(savedDup3.getDuplicatedBy(0).getStartLine()).isEqualTo(20);
+ assertThat(savedDup3.getDuplicatedBy(0).getEndLine()).isEqualTo(50);
+
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
index 29a75622c8f..3089a67cbee 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java
@@ -23,8 +23,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.sensor.duplication.Duplication;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.*;
import org.sonar.api.measures.Metric.Level;
@@ -34,7 +32,6 @@ import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.protocol.output.BatchReportWriter;
@@ -48,7 +45,6 @@ import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -58,7 +54,6 @@ public class MeasuresPublisherTest {
public TemporaryFolder temp = new TemporaryFolder();
private MeasureCache measureCache;
- private DuplicationCache duplicationCache;
private MeasuresPublisher publisher;
private org.sonar.api.resources.File aFile = org.sonar.api.resources.File.create("org/foo/Bar.java");
@@ -72,9 +67,7 @@ public class MeasuresPublisherTest {
resourceCache.add(p, null).setSnapshot(new Snapshot().setId(2));
resourceCache.add(sampleFile, null);
measureCache = mock(MeasureCache.class);
- duplicationCache = mock(DuplicationCache.class);
when(measureCache.byResource(any(Resource.class))).thenReturn(Collections.<Measure>emptyList());
- when(duplicationCache.byComponent(anyString())).thenReturn(Collections.<DefaultDuplication>emptyList());
MetricFinder metricFinder = mock(MetricFinder.class);
when(metricFinder.findByKey(CoreMetrics.COVERAGE_KEY)).thenReturn(CoreMetrics.COVERAGE);
when(metricFinder.findByKey(CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY)).thenReturn(CoreMetrics.NEW_BLOCKER_VIOLATIONS);
@@ -83,7 +76,7 @@ public class MeasuresPublisherTest {
when(metricFinder.findByKey(CoreMetrics.SQALE_RATING_KEY)).thenReturn(CoreMetrics.SQALE_RATING);
when(metricFinder.findByKey(CoreMetrics.TECHNICAL_DEBT_KEY)).thenReturn(CoreMetrics.TECHNICAL_DEBT);
when(metricFinder.findByKey(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION);
- publisher = new MeasuresPublisher(resourceCache, measureCache, duplicationCache, metricFinder);
+ publisher = new MeasuresPublisher(resourceCache, measureCache, metricFinder);
}
@Test
@@ -141,37 +134,6 @@ public class MeasuresPublisherTest {
}
@Test
- public void publishMeasureAndDuplication() throws Exception {
-
- Measure measure1 = new Measure<>(CoreMetrics.COVERAGE)
- .setValue(2.0);
-
- when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1));
- DefaultDuplication dup1 = new DefaultDuplication()
- .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10))
- .isDuplicatedBy("foo:src/Foo.php", 20, 50);
- DefaultDuplication dup2 = new DefaultDuplication()
- .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10))
- .isDuplicatedBy("another", 20, 50);
- when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2));
-
- File outputDir = temp.newFolder();
- BatchReportWriter writer = new BatchReportWriter(outputDir);
-
- publisher.publish(writer);
-
- BatchReportReader reader = new BatchReportReader(outputDir);
-
- assertThat(reader.readComponentMeasures(1)).hasSize(0);
- List<org.sonar.batch.protocol.output.BatchReport.Measure> componentMeasures = reader.readComponentMeasures(2);
- assertThat(componentMeasures).hasSize(2);
- assertThat(componentMeasures.get(0).getStringValue())
- .isEqualTo(
- "<duplications><g><b s=\"1\" l=\"10\" r=\"foo:src/Foo.php\"/><b s=\"20\" l=\"31\" r=\"foo:src/Foo.php\"/></g><g><b s=\"1\" l=\"10\" r=\"foo:src/Foo.php\"/><b s=\"20\" l=\"31\" r=\"another\"/></g></duplications>");
-
- }
-
- @Test
public void should_not_save_some_file_measures_with_best_value() {
assertThat(MeasuresPublisher.shouldPersistMeasure(aFile, new Measure(CoreMetrics.LINES, 200.0))).isTrue();
assertThat(MeasuresPublisher.shouldPersistMeasure(aFile, new Measure(CoreMetrics.DUPLICATED_LINES_DENSITY, 3.0))).isTrue();