From: Julien HENRY
Date: Wed, 14 Jan 2015 16:14:00 +0000 (+0100)
Subject: SONAR-5931 Publish new measure API
X-Git-Tag: latest-silver-master-#65~211
X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=12c4a20acb61ff6f516c7e7bb8996db606b263ab;p=sonarqube.git
SONAR-5931 Publish new measure API
---
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 68275cb247a..fb1eb26c69d 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -52,7 +52,6 @@ import org.sonar.plugins.core.security.ApplyProjectRolesDecorator;
import org.sonar.plugins.core.sensors.BranchCoverageDecorator;
import org.sonar.plugins.core.sensors.CommentDensityDecorator;
import org.sonar.plugins.core.sensors.CoverageDecorator;
-import org.sonar.plugins.core.sensors.CoverageMeasurementFilter;
import org.sonar.plugins.core.sensors.DirectoriesDecorator;
import org.sonar.plugins.core.sensors.FileHashSensor;
import org.sonar.plugins.core.sensors.FilesDecorator;
@@ -369,7 +368,6 @@ public final class CorePlugin extends SonarPlugin {
OverallLineCoverageDecorator.class,
OverallCoverageDecorator.class,
OverallBranchCoverageDecorator.class,
- CoverageMeasurementFilter.class,
ApplyProjectRolesDecorator.class,
CommentDensityDecorator.class,
DirectoriesDecorator.class,
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java
index 951c1d383a1..529883fc749 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java
@@ -19,20 +19,19 @@
*/
package org.sonar.plugins.core.sensors;
-import com.google.common.collect.ImmutableList;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.MeasureUtils;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
-import java.util.List;
+import java.util.Collection;
public final class BranchCoverageDecorator extends AbstractCoverageDecorator {
@DependsUpon
- public List dependsUponMetrics() {
- return ImmutableList.of(CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_TO_COVER,
- CoreMetrics.NEW_UNCOVERED_CONDITIONS, CoreMetrics.NEW_CONDITIONS_TO_COVER);
+ public Collection dependsUponMetrics() {
+ return CoverageConstants.BRANCH_COVERAGE_METRICS;
}
@Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java
index 2d37d02dec9..46b02d4e0f8 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java
@@ -19,21 +19,19 @@
*/
package org.sonar.plugins.core.sensors;
-import com.google.common.collect.ImmutableList;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.MeasureUtils;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
import java.util.Collection;
public final class CoverageDecorator extends AbstractCoverageDecorator {
@DependsUpon
public Collection usedMetrics() {
- return ImmutableList.of(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
- CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
- CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+ return CoverageConstants.COVERAGE_METRICS;
}
@Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
deleted file mode 100644
index e236c6298ed..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.plugins.core.sensors;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.ImmutableSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.utils.WildcardPattern;
-import org.sonar.core.measure.MeasurementFilter;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-public class CoverageMeasurementFilter implements MeasurementFilter {
-
- private static final Logger LOG = LoggerFactory.getLogger(CoverageMeasurementFilter.class);
-
- private final Settings settings;
- private final ImmutableSet coverageMetrics;
- private Collection resourcePatterns;
-
- public CoverageMeasurementFilter(Settings settings,
- CoverageDecorator coverageDecorator,
- LineCoverageDecorator lineCoverageDecorator,
- BranchCoverageDecorator branchCoverageDecorator) {
- this.settings = settings;
- this.coverageMetrics = ImmutableSet.builder()
- .addAll(coverageDecorator.generatedMetrics())
- .addAll(coverageDecorator.usedMetrics())
- .addAll(lineCoverageDecorator.generatedMetrics())
- .addAll(lineCoverageDecorator.dependsUponMetrics())
- .addAll(branchCoverageDecorator.generatedMetrics())
- .addAll(branchCoverageDecorator.dependsUponMetrics())
- .build();
-
- initPatterns();
- }
-
- @Override
- public boolean accept(Resource resource, Measure measure) {
- if (isCoverageMetric(measure.getMetric())) {
- return !hasMatchingPattern(resource);
- } else {
- return true;
- }
- }
-
- private boolean isCoverageMetric(Metric metric) {
- return this.coverageMetrics.contains(metric);
- }
-
- private boolean hasMatchingPattern(Resource resource) {
- boolean found = false;
- Iterator iterator = resourcePatterns.iterator();
- while (!found && iterator.hasNext()) {
- found = resource.matchFilePattern(iterator.next().toString());
- }
- return found;
- }
-
- @VisibleForTesting
- final void initPatterns() {
- Builder builder = ImmutableList.builder();
- for (String pattern : settings.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY)) {
- builder.add(WildcardPattern.create(pattern));
- }
- resourcePatterns = builder.build();
- log("Excluded sources for coverage: ", resourcePatterns);
- }
-
- private void log(String title, Collection patterns) {
- if (!patterns.isEmpty()) {
- LOG.info(title);
- for (WildcardPattern pattern : patterns) {
- LOG.info(" " + pattern);
- }
- }
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java
index feaf04176cf..11ff93f0634 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java
@@ -19,20 +19,19 @@
*/
package org.sonar.plugins.core.sensors;
-import com.google.common.collect.ImmutableList;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.MeasureUtils;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.sensor.coverage.CoverageConstants;
-import java.util.List;
+import java.util.Collection;
public final class LineCoverageDecorator extends AbstractCoverageDecorator {
@DependsUpon
- public List dependsUponMetrics() {
- return ImmutableList.of(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
- CoreMetrics.NEW_LINES_TO_COVER);
+ public Collection dependsUponMetrics() {
+ return CoverageConstants.LINE_COVERAGE_METRICS;
}
@Override
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
deleted file mode 100644
index 85ca73d04bf..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.plugins.core.sensors;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Resource;
-import org.sonar.core.config.ExclusionProperties;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class CoverageMeasurementFilterTest {
-
- private Settings settings;
-
- private CoverageMeasurementFilter filter;
-
- @Before
- public void createFilter() {
- settings = new Settings(new PropertyDefinitions(ExclusionProperties.all()));
- filter = new CoverageMeasurementFilter(settings, new CoverageDecorator(), new LineCoverageDecorator(), new BranchCoverageDecorator());
- }
-
- @Test
- public void shouldNotFilterNonCoverageMetrics() {
- Measure otherMeasure = mock(Measure.class);
- when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES);
- assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue();
- }
-
- @Test
- public void shouldFilterFileBasedOnPattern() {
- Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
- Measure coverageMeasure = mock(Measure.class);
- when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
-
- settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
- filter.initPatterns();
- assertThat(filter.accept(resource, coverageMeasure)).isFalse();
- }
-
- @Test
- public void shouldNotFilterFileBasedOnPattern() {
- Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
- Measure coverageMeasure = mock(Measure.class);
- when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
-
- settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
- filter.initPatterns();
- assertThat(filter.accept(resource, coverageMeasure)).isTrue();
- }
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java
index 87dd7f9ae6d..e2956df1683 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java
@@ -24,15 +24,12 @@ import org.junit.Test;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Scopes;
-import java.util.List;
-
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.anyDouble;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -49,9 +46,8 @@ public class LineCoverageDecoratorTest {
@Test
public void should_depend_on_coverage_metrics() {
- List metrics = decorator.dependsUponMetrics();
-
- assertThat(metrics).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER);
+ assertThat(decorator.dependsUponMetrics()).containsOnly(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
+ CoreMetrics.NEW_LINES_TO_COVER);
}
@Test
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 471a5835639..a890b63ac9d 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
@@ -28,8 +28,7 @@ import org.sonar.api.batch.measure.MetricFinder;
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.measure.Measure;
-import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
import org.sonar.xoo.Xoo;
import java.io.File;
@@ -88,7 +87,7 @@ public class MeasureSensor implements Sensor {
if (metric == null) {
throw new IllegalStateException("Unknow metric with key: " + metricKey);
}
- Measure newMeasure = context.newMeasure()
+ NewMeasure newMeasure = context.newMeasure()
.forMetric(metric)
.onFile(xooFile);
if (Boolean.class.equals(metric.valueType())) {
@@ -111,9 +110,7 @@ public class MeasureSensor implements Sensor {
public void describe(SensorDescriptor descriptor) {
descriptor
.name("Xoo Measure Sensor")
- .provides(CoreMetrics.LINES)
- .onlyOnLanguages(Xoo.KEY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .onlyOnLanguages(Xoo.KEY);
}
@Override
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
index fbff5f75641..8d14771bab4 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java
@@ -87,8 +87,7 @@ public class SymbolReferencesSensor implements Sensor {
public void describe(SensorDescriptor descriptor) {
descriptor
.name("Xoo Symbol Reference Sensor")
- .onlyOnLanguages(Xoo.KEY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .onlyOnLanguages(Xoo.KEY);
}
@Override
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
index d72b50b4089..004c186b208 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SyntaxHighlightingSensor.java
@@ -85,8 +85,7 @@ public class SyntaxHighlightingSensor implements Sensor {
public void describe(SensorDescriptor descriptor) {
descriptor
.name("Xoo Highlighting Sensor")
- .onlyOnLanguages(Xoo.KEY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .onlyOnLanguages(Xoo.KEY);
}
@Override
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java
index 04dc7be446f..886104c14a0 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java
@@ -35,8 +35,7 @@ public class CreateIssueByInternalKeySensor implements Sensor {
descriptor
.name("CreateIssueByInternalKeySensor")
.onlyOnLanguages(Xoo.KEY)
- .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
}
@Override
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java
index 548b596c300..66a31686e03 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java
@@ -36,8 +36,7 @@ public class OneIssueOnDirPerFileSensor implements Sensor {
descriptor
.name("One Issue On Dir Per File")
.onlyOnLanguages(Xoo.KEY)
- .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
}
@Override
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java
index 081bb1a0a2b..3e0b9f48ee5 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java
@@ -24,7 +24,6 @@ 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.Issue.Severity;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rule.RuleKey;
import org.sonar.xoo.Xoo;
@@ -38,10 +37,8 @@ public class OneIssuePerLineSensor implements Sensor {
public void describe(SensorDescriptor descriptor) {
descriptor
.name("One Issue Per Line")
- .dependsOn(CoreMetrics.LINES)
.onlyOnLanguages(Xoo.KEY)
- .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY)
- .onOnFileType(InputFile.Type.MAIN, InputFile.Type.TEST);
+ .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
}
@Override
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
index 1fa2a1b6450..3d18e06c5a9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
@@ -40,7 +40,7 @@ import org.sonar.api.utils.SonarException;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.duplication.DuplicationUtils;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
import java.util.Arrays;
import java.util.Collection;
@@ -54,7 +54,6 @@ public class DefaultDecoratorContext implements DecoratorContext {
private static final String SAVE_MEASURE_METHOD = "saveMeasure";
private SonarIndex sonarIndex;
private Resource resource;
- private MeasurementFilters measurementFilters;
private boolean readOnly = false;
private List childrenContexts;
@@ -63,18 +62,19 @@ public class DefaultDecoratorContext implements DecoratorContext {
private MeasureCache measureCache;
private MetricFinder metricFinder;
private final DuplicationCache duplicationCache;
+ private final CoverageExclusions coverageFilter;
public DefaultDecoratorContext(Resource resource,
SonarIndex index,
List childrenContexts,
- MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder, DuplicationCache duplicationCache) {
+ MeasureCache measureCache, MetricFinder metricFinder, DuplicationCache duplicationCache, CoverageExclusions coverageFilter) {
this.sonarIndex = index;
this.resource = resource;
this.childrenContexts = childrenContexts;
- this.measurementFilters = measurementFilters;
this.measureCache = measureCache;
this.metricFinder = metricFinder;
this.duplicationCache = duplicationCache;
+ this.coverageFilter = coverageFilter;
}
public void init() {
@@ -178,7 +178,7 @@ public class DefaultDecoratorContext implements DecoratorContext {
throw new SonarException("Unknown metric: " + measure.getMetricKey());
}
measure.setMetric(metric);
- if (measurementFilters.accept(resource, measure)) {
+ if (coverageFilter.accept(resource, measure)) {
List metricMeasures = measuresByMetric.get(measure.getMetricKey());
boolean add = true;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
deleted file mode 100644
index eeecd48b8bd..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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;
-
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.Event;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.SonarIndex;
-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.design.Dependency;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectLink;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rules.Violation;
-import org.sonar.api.utils.SonarException;
-import org.sonar.core.measure.MeasurementFilters;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-public class DefaultSensorContext implements SensorContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorContext.class);
-
- private SonarIndex index;
- private Project project;
- private MeasurementFilters filters;
-
- public DefaultSensorContext(SonarIndex index, Project project, MeasurementFilters filters) {
- this.index = index;
- this.project = project;
- this.filters = filters;
- }
-
- public Project getProject() {
- return project;
- }
-
- @Override
- public boolean index(Resource resource) {
- // SONAR-5006
- if (indexedByCore(resource)) {
- logWarning();
- return true;
- }
- return index.index(resource);
- }
-
- private boolean indexedByCore(Resource resource) {
- return StringUtils.equals(Qualifiers.DIRECTORY, resource.getQualifier()) ||
- StringUtils.equals(Qualifiers.FILE, resource.getQualifier());
- }
-
- @Override
- public boolean index(Resource resource, Resource parentReference) {
- // SONAR-5006
- if (indexedByCore(resource)) {
- logWarning();
- return true;
- }
- return index.index(resource, parentReference);
- }
-
- private void logWarning() {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Plugins are no more responsible for indexing physical resources like directories and files. This is now handled by the platform.", new SonarException(
- "Plugin should not index physical resources"));
- }
- }
-
- @Override
- public boolean isExcluded(Resource reference) {
- return index.isExcluded(reference);
- }
-
- @Override
- public boolean isIndexed(Resource reference, boolean acceptExcluded) {
- return index.isIndexed(reference, acceptExcluded);
- }
-
- @Override
- public Resource getParent(Resource reference) {
- return index.getParent(reference);
- }
-
- @Override
- public Collection getChildren(Resource reference) {
- return index.getChildren(reference);
- }
-
- @Override
- public Measure getMeasure(Metric metric) {
- return index.getMeasure(project, metric);
- }
-
- @Override
- public M getMeasures(MeasuresFilter filter) {
- return index.getMeasures(project, filter);
- }
-
- @Override
- public Measure saveMeasure(Measure measure) {
- return index.addMeasure(project, measure);
- }
-
- @Override
- public Measure saveMeasure(Metric metric, Double value) {
- return index.addMeasure(project, new Measure(metric, value));
- }
-
- @Override
- public Measure getMeasure(Resource resource, Metric metric) {
- return index.getMeasure(resource, metric);
- }
-
- @Override
- public String saveResource(Resource resource) {
- Resource persistedResource = index.addResource(resource);
- if (persistedResource != null) {
- return persistedResource.getEffectiveKey();
- }
- return null;
- }
-
- public boolean saveResource(Resource resource, Resource parentReference) {
- return index.index(resource, parentReference);
- }
-
- @Override
- public Resource getResource(Resource resource) {
- return index.getResource(resource);
- }
-
- @Override
- public M getMeasures(Resource resource, MeasuresFilter filter) {
- return index.getMeasures(resource, filter);
- }
-
- @Override
- public Measure saveMeasure(Resource resource, Metric metric, Double value) {
- return saveMeasure(resource, new Measure(metric, value));
- }
-
- @Override
- public Measure saveMeasure(Resource resource, Measure measure) {
- if (filters.accept(resource, measure)) {
- return index.addMeasure(resourceOrProject(resource), measure);
- } else {
- return measure;
- }
- }
-
- @Override
- public void saveViolation(Violation violation, boolean force) {
- if (violation.getResource() == null) {
- violation.setResource(resourceOrProject(violation.getResource()));
- }
- index.addViolation(violation, force);
- }
-
- @Override
- public void saveViolation(Violation violation) {
- saveViolation(violation, false);
- }
-
- @Override
- public void saveViolations(Collection violations) {
- if (violations != null) {
- for (Violation violation : violations) {
- saveViolation(violation);
- }
- }
- }
-
- @Override
- public Dependency saveDependency(Dependency dependency) {
- return index.addDependency(dependency);
- }
-
- @Override
- public Set getDependencies() {
- return index.getDependencies();
- }
-
- @Override
- public Collection getIncomingDependencies(Resource to) {
- return index.getIncomingEdges(resourceOrProject(to));
- }
-
- @Override
- public Collection getOutgoingDependencies(Resource from) {
- return index.getOutgoingEdges(resourceOrProject(from));
- }
-
- @Override
- public void saveSource(Resource reference, String source) {
- // useless since 4.2.
- }
-
- @Override
- public void saveLink(ProjectLink link) {
- index.addLink(link);
- }
-
- @Override
- public void deleteLink(String key) {
- index.deleteLink(key);
- }
-
- @Override
- public List getEvents(Resource resource) {
- return index.getEvents(resource);
- }
-
- @Override
- public Event createEvent(Resource resource, String name, String description, String category, Date date) {
- return index.addEvent(resource, name, description, category, date);
- }
-
- @Override
- public void deleteEvent(Event event) {
- index.deleteEvent(event);
- }
-
- private Resource resourceOrProject(Resource resource) {
- if (resource == null) {
- return project;
- }
- Resource indexedResource = getResource(resource);
- return indexedResource != null ? indexedResource : resource;
- }
-
- @Override
- public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
- return saveMeasure(getResource(inputFile), metric, value);
- }
-
- @Override
- public Measure saveMeasure(InputFile inputFile, Measure measure) {
- return saveMeasure(getResource(inputFile), measure);
- }
-
- @Override
- public Resource getResource(InputPath inputPath) {
- Resource r;
- if (inputPath instanceof InputDir) {
- r = Directory.create(((InputDir) inputPath).relativePath());
- } else if (inputPath instanceof InputFile) {
- r = File.create(((InputFile) inputPath).relativePath());
- } else {
- throw new IllegalArgumentException("Unknow input path type: " + inputPath);
- }
- return getResource(r);
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java
new file mode 100644
index 00000000000..35d329627f3
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/DeprecatedSensorContext.java
@@ -0,0 +1,297 @@
+/*
+ * 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;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.Event;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
+import org.sonar.api.batch.fs.FileSystem;
+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.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.config.Settings;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasuresFilter;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectLink;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rules.Violation;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+public class DeprecatedSensorContext extends DefaultSensorContext implements SensorContext {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DeprecatedSensorContext.class);
+
+ private final SonarIndex index;
+ private final Project project;
+ private final CoverageExclusions coverageFilter;
+
+ public DeprecatedSensorContext(SonarIndex index, Project project, Settings settings, FileSystem fs, ActiveRules activeRules,
+ ComponentDataCache componentDataCache, CoverageExclusions coverageFilter,
+ BlockCache blockCache, DuplicationCache duplicationCache, SensorStorage sensorStorage) {
+ super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache, sensorStorage);
+ this.index = index;
+ this.project = project;
+ this.coverageFilter = coverageFilter;
+ }
+
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public boolean index(Resource resource) {
+ // SONAR-5006
+ if (indexedByCore(resource)) {
+ logWarning();
+ return true;
+ }
+ return index.index(resource);
+ }
+
+ private boolean indexedByCore(Resource resource) {
+ return StringUtils.equals(Qualifiers.DIRECTORY, resource.getQualifier()) ||
+ StringUtils.equals(Qualifiers.FILE, resource.getQualifier());
+ }
+
+ @Override
+ public boolean index(Resource resource, Resource parentReference) {
+ // SONAR-5006
+ if (indexedByCore(resource)) {
+ logWarning();
+ return true;
+ }
+ return index.index(resource, parentReference);
+ }
+
+ private void logWarning() {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Plugins are no more responsible for indexing physical resources like directories and files. This is now handled by the platform.", new SonarException(
+ "Plugin should not index physical resources"));
+ }
+ }
+
+ @Override
+ public boolean isExcluded(Resource reference) {
+ return index.isExcluded(reference);
+ }
+
+ @Override
+ public boolean isIndexed(Resource reference, boolean acceptExcluded) {
+ return index.isIndexed(reference, acceptExcluded);
+ }
+
+ @Override
+ public Resource getParent(Resource reference) {
+ return index.getParent(reference);
+ }
+
+ @Override
+ public Collection getChildren(Resource reference) {
+ return index.getChildren(reference);
+ }
+
+ @Override
+ public Measure getMeasure(Metric metric) {
+ return index.getMeasure(project, metric);
+ }
+
+ @Override
+ public M getMeasures(MeasuresFilter filter) {
+ return index.getMeasures(project, filter);
+ }
+
+ @Override
+ public Measure saveMeasure(Measure measure) {
+ return index.addMeasure(project, measure);
+ }
+
+ @Override
+ public Measure saveMeasure(Metric metric, Double value) {
+ return index.addMeasure(project, new Measure(metric, value));
+ }
+
+ @Override
+ public Measure getMeasure(Resource resource, Metric metric) {
+ return index.getMeasure(resource, metric);
+ }
+
+ @Override
+ public String saveResource(Resource resource) {
+ Resource persistedResource = index.addResource(resource);
+ if (persistedResource != null) {
+ return persistedResource.getEffectiveKey();
+ }
+ return null;
+ }
+
+ public boolean saveResource(Resource resource, Resource parentReference) {
+ return index.index(resource, parentReference);
+ }
+
+ @Override
+ public Resource getResource(Resource resource) {
+ return index.getResource(resource);
+ }
+
+ @Override
+ public M getMeasures(Resource resource, MeasuresFilter filter) {
+ return index.getMeasures(resource, filter);
+ }
+
+ @Override
+ public Measure saveMeasure(Resource resource, Metric metric, Double value) {
+ return saveMeasure(resource, new Measure(metric, value));
+ }
+
+ @Override
+ public Measure saveMeasure(Resource resource, Measure measure) {
+ Resource resourceOrProject = resourceOrProject(resource);
+ if (coverageFilter.accept(resourceOrProject, measure)) {
+ return index.addMeasure(resourceOrProject, measure);
+ } else {
+ return measure;
+ }
+ }
+
+ @Override
+ public void saveViolation(Violation violation, boolean force) {
+ if (violation.getResource() == null) {
+ violation.setResource(resourceOrProject(violation.getResource()));
+ }
+ index.addViolation(violation, force);
+ }
+
+ @Override
+ public void saveViolation(Violation violation) {
+ saveViolation(violation, false);
+ }
+
+ @Override
+ public void saveViolations(Collection violations) {
+ if (violations != null) {
+ for (Violation violation : violations) {
+ saveViolation(violation);
+ }
+ }
+ }
+
+ @Override
+ public Dependency saveDependency(Dependency dependency) {
+ return index.addDependency(dependency);
+ }
+
+ @Override
+ public Set getDependencies() {
+ return index.getDependencies();
+ }
+
+ @Override
+ public Collection getIncomingDependencies(Resource to) {
+ return index.getIncomingEdges(resourceOrProject(to));
+ }
+
+ @Override
+ public Collection getOutgoingDependencies(Resource from) {
+ return index.getOutgoingEdges(resourceOrProject(from));
+ }
+
+ @Override
+ public void saveSource(Resource reference, String source) {
+ // useless since 4.2.
+ }
+
+ @Override
+ public void saveLink(ProjectLink link) {
+ index.addLink(link);
+ }
+
+ @Override
+ public void deleteLink(String key) {
+ index.deleteLink(key);
+ }
+
+ @Override
+ public List getEvents(Resource resource) {
+ return index.getEvents(resource);
+ }
+
+ @Override
+ public Event createEvent(Resource resource, String name, String description, String category, Date date) {
+ return index.addEvent(resource, name, description, category, date);
+ }
+
+ @Override
+ public void deleteEvent(Event event) {
+ index.deleteEvent(event);
+ }
+
+ private Resource resourceOrProject(Resource resource) {
+ if (resource == null) {
+ return project;
+ }
+ Resource indexedResource = getResource(resource);
+ return indexedResource != null ? indexedResource : resource;
+ }
+
+ @Override
+ public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
+ return saveMeasure(getResource(inputFile), metric, value);
+ }
+
+ @Override
+ public Measure saveMeasure(InputFile inputFile, Measure measure) {
+ return saveMeasure(getResource(inputFile), measure);
+ }
+
+ @Override
+ public Resource getResource(InputPath inputPath) {
+ Resource r;
+ if (inputPath instanceof InputDir) {
+ r = Directory.create(((InputDir) inputPath).relativePath());
+ } else if (inputPath instanceof InputFile) {
+ r = File.create(((InputFile) inputPath).relativePath());
+ } else {
+ throw new IllegalArgumentException("Unknow input path type: " + inputPath);
+ }
+ return getResource(r);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
index 32bebf6182e..e0a0e348514 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
@@ -29,6 +29,7 @@ import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.batch.scan.SensorWrapper;
import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
import javax.annotation.Nullable;
@@ -43,7 +44,7 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio
private SensorContext context;
private AnalyzerOptimizer analyzerOptimizer;
- public BatchExtensionDictionnary(ComponentContainer componentContainer, SensorContext context, AnalyzerOptimizer analyzerOptimizer) {
+ public BatchExtensionDictionnary(ComponentContainer componentContainer, DefaultSensorContext context, AnalyzerOptimizer analyzerOptimizer) {
super(componentContainer);
this.context = context;
this.analyzerOptimizer = analyzerOptimizer;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index 9e3a3d1b133..64886cc1529 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -31,8 +31,10 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Event;
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.design.Dependency;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.MeasuresFilters;
@@ -51,7 +53,6 @@ import org.sonar.api.utils.SonarException;
import org.sonar.batch.ProjectTree;
import org.sonar.batch.issue.ModuleIssues;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.batch.scan2.DefaultSensorContext;
import org.sonar.core.component.ComponentKeys;
import javax.annotation.CheckForNull;
@@ -59,6 +60,7 @@ import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@@ -72,6 +74,31 @@ public class DefaultIndex extends SonarIndex {
private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);
+ private static final List INTERNAL_METRICS = Arrays.asList(
+ // Computed by DsmDecorator
+ CoreMetrics.DEPENDENCY_MATRIX,
+ CoreMetrics.DIRECTORY_CYCLES,
+ CoreMetrics.DIRECTORY_EDGES_WEIGHT,
+ CoreMetrics.DIRECTORY_FEEDBACK_EDGES,
+ CoreMetrics.DIRECTORY_TANGLE_INDEX,
+ CoreMetrics.DIRECTORY_TANGLES,
+ CoreMetrics.FILE_CYCLES,
+ CoreMetrics.FILE_EDGES_WEIGHT,
+ CoreMetrics.FILE_FEEDBACK_EDGES,
+ CoreMetrics.FILE_TANGLE_INDEX,
+ CoreMetrics.FILE_TANGLES,
+ // Computed by ScmActivitySensor
+ CoreMetrics.SCM_AUTHORS_BY_LINE,
+ CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
+ CoreMetrics.SCM_REVISIONS_BY_LINE,
+ // Computed by core duplication plugin
+ CoreMetrics.DUPLICATIONS_DATA,
+ CoreMetrics.DUPLICATION_LINES_DATA,
+ CoreMetrics.DUPLICATED_FILES,
+ CoreMetrics.DUPLICATED_LINES,
+ CoreMetrics.DUPLICATED_BLOCKS
+ );
+
private final ResourceCache resourceCache;
private final MetricFinder metricFinder;
@@ -228,7 +255,7 @@ public class DefaultIndex extends SonarIndex {
if (metric == null) {
throw new SonarException("Unknown metric: " + measure.getMetricKey());
}
- if (!isTechnicalProjectCopy(resource) && !measure.isFromCore() && DefaultSensorContext.INTERNAL_METRICS.contains(metric)) {
+ if (!isTechnicalProjectCopy(resource) && !measure.isFromCore() && INTERNAL_METRICS.contains(metric)) {
LOG.debug("Metric " + metric.key() + " is an internal metric computed by SonarQube. Please update your plugin.");
return measure;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
index b9216a859f7..7bc120b37d6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
@@ -19,6 +19,7 @@
*/
package org.sonar.batch.mediumtest;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.InputDir;
@@ -28,6 +29,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.dependency.Dependency;
import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.symbol.Symbol;
import org.sonar.api.batch.sensor.test.TestCaseCoverage;
import org.sonar.api.batch.sensor.test.TestCaseExecution;
@@ -51,6 +53,7 @@ import org.sonar.core.source.SnapshotDataTypes;
import javax.annotation.CheckForNull;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -64,7 +67,7 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
private static final Logger LOG = LoggerFactory.getLogger(TaskResult.class);
private List issues = new ArrayList<>();
- private List measures = new ArrayList<>();
+ private List measures = new ArrayList<>();
private Map> duplications = new HashMap<>();
private Map inputFiles = new HashMap<>();
private Map inputDirs = new HashMap<>();
@@ -81,11 +84,10 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
issues.add(issue);
}
- for (Measure measure : container.getComponentByType(MeasureCache.class).all()) {
- measures.add(measure);
- }
-
storeFs(container);
+
+ storeMeasures(container);
+
storeComponentData(container);
storeDuplication(container);
// storeTestCases(container);
@@ -94,6 +96,24 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
}
+ private void storeMeasures(ProjectScanContainer container) {
+ InputPathCache inputFileCache = container.getComponentByType(InputPathCache.class);
+ for (Entry measureEntry : container.getComponentByType(MeasureCache.class).entries()) {
+ String componentKey = measureEntry.key()[0].toString();
+ InputFile file = inputFileCache.getFile(StringUtils.substringBeforeLast(componentKey, ":"), StringUtils.substringAfterLast(componentKey, ":"));
+ Measure oldMeasure = measureEntry.value();
+ DefaultMeasure newMeasure = new DefaultMeasure<>()
+ .forMetric(oldMeasure.getMetric());
+ if (file != null) {
+ newMeasure.onFile(file);
+ } else {
+ newMeasure.onProject();
+ }
+ newMeasure.withValue(oldMeasure.value());
+ measures.add(newMeasure);
+ }
+ }
+
private void storeCoveragePerTest(ProjectScanContainer container) {
TestCaseCoverageCache testCaseCoverageCache = container.getComponentByType(TestCaseCoverageCache.class);
for (Entry entry : testCaseCoverageCache.entries()) {
@@ -170,7 +190,7 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
return issues;
}
- public List measures() {
+ public List measures() {
return measures;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
index b867e0fc010..01ae1e452d8 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
@@ -35,7 +35,7 @@ import org.sonar.batch.DefaultDecoratorContext;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
import java.util.Collection;
import java.util.List;
@@ -46,13 +46,13 @@ public class DecoratorsExecutor implements BatchComponent {
private SonarIndex index;
private EventBus eventBus;
private Project project;
- private MeasurementFilters measurementFilters;
+ private CoverageExclusions coverageFilter;
private MeasureCache measureCache;
private MetricFinder metricFinder;
private final DuplicationCache duplicationCache;
public DecoratorsExecutor(BatchExtensionDictionnary batchExtDictionnary,
- Project project, SonarIndex index, EventBus eventBus, MeasurementFilters measurementFilters, MeasureCache measureCache, MetricFinder metricFinder,
+ Project project, SonarIndex index, EventBus eventBus, CoverageExclusions coverageFilter, MeasureCache measureCache, MetricFinder metricFinder,
DuplicationCache duplicationCache) {
this.measureCache = measureCache;
this.metricFinder = metricFinder;
@@ -61,7 +61,7 @@ public class DecoratorsExecutor implements BatchComponent {
this.index = index;
this.eventBus = eventBus;
this.project = project;
- this.measurementFilters = measurementFilters;
+ this.coverageFilter = coverageFilter;
}
public void execute() {
@@ -79,7 +79,7 @@ public class DecoratorsExecutor implements BatchComponent {
childrenContexts.add(childContext.end());
}
- DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measurementFilters, measureCache, metricFinder, duplicationCache);
+ DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, measureCache, metricFinder, duplicationCache, coverageFilter);
context.init();
if (executeDecorators) {
for (Decorator decorator : decorators) {
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 af680789d80..98598f57f33 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
@@ -31,8 +31,8 @@ import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
import org.sonar.batch.DefaultProjectClasspath;
-import org.sonar.batch.DefaultSensorContext;
import org.sonar.batch.DefaultTimeMachine;
+import org.sonar.batch.DeprecatedSensorContext;
import org.sonar.batch.ProjectTree;
import org.sonar.batch.ResourceFilters;
import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
@@ -97,8 +97,10 @@ import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
import org.sonar.batch.scan.maven.MavenPluginsConfigurator;
import org.sonar.batch.scan.report.JsonReport;
import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
+import org.sonar.batch.sensor.DefaultSensorStorage;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
import org.sonar.core.component.ScanPerspectives;
-import org.sonar.core.measure.MeasurementFilters;
public class ModuleScanContainer extends ComponentContainer {
private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
@@ -174,11 +176,12 @@ public class ModuleScanContainer extends ComponentContainer {
AnalyzerOptimizer.class,
DefaultSensorContext.class,
- SensorContextAdapter.class,
+ DefaultSensorStorage.class,
+ DeprecatedSensorContext.class,
BatchExtensionDictionnary.class,
DefaultTimeMachine.class,
IssueFilters.class,
- MeasurementFilters.class,
+ CoverageExclusions.class,
ResourceFilters.class,
// rules
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java
deleted file mode 100644
index a8d57e8088f..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdapter.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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.scan;
-
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.batch.fs.FileSystem;
-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.measure.MetricFinder;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.Formula;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.measures.SumChildDistributionFormula;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.test.MutableTestCase;
-import org.sonar.api.test.MutableTestPlan;
-import org.sonar.api.test.MutableTestable;
-import org.sonar.api.test.Testable;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan2.BaseSensorContext;
-import org.sonar.core.component.ComponentKeys;
-
-/**
- * Implements {@link SensorContext} but forward everything to {@link org.sonar.api.batch.SensorContext} for backward compatibility.
- * Will be dropped once old {@link Sensor} API is dropped.
- *
- */
-public class SensorContextAdapter extends BaseSensorContext {
-
- private static final String USES = "USES";
- private final org.sonar.api.batch.SensorContext sensorContext;
- private final MetricFinder metricFinder;
- private final Project project;
- private final ResourcePerspectives perspectives;
- private final SonarIndex sonarIndex;
-
- public SensorContextAdapter(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project,
- ResourcePerspectives perspectives,
- Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
- DuplicationCache duplicationCache, SonarIndex sonarIndex) {
- super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
- this.sensorContext = sensorContext;
- this.metricFinder = metricFinder;
- this.project = project;
- this.perspectives = perspectives;
- this.sonarIndex = sonarIndex;
- }
-
- private Metric findMetricOrFail(String metricKey) {
- Metric m = (Metric) metricFinder.findByKey(metricKey);
- if (m == null) {
- throw new IllegalStateException("Unknow metric with key: " + metricKey);
- }
- return m;
- }
-
- @Override
- public void store(Measure newMeasure) {
- DefaultMeasure measure = (DefaultMeasure) newMeasure;
- org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
- org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
- setValueAccordingToMetricType(newMeasure, m, measureToSave);
- measureToSave.setFromCore(measure.isFromCore());
- if (newMeasure.inputFile() != null) {
- Formula formula = newMeasure.metric() instanceof org.sonar.api.measures.Metric ?
- ((org.sonar.api.measures.Metric) newMeasure.metric()).getFormula() : null;
- if (formula instanceof SumChildDistributionFormula
- && !Scopes.isHigherThanOrEquals(Scopes.FILE, ((SumChildDistributionFormula) formula).getMinimumScopeToPersist())) {
- measureToSave.setPersistenceMode(PersistenceMode.MEMORY);
- }
- sensorContext.saveMeasure(newMeasure.inputFile(), measureToSave);
- } else {
- sensorContext.saveMeasure(measureToSave);
- }
- }
-
- private void setValueAccordingToMetricType(Measure> measure, org.sonar.api.measures.Metric> m, org.sonar.api.measures.Measure measureToSave) {
- switch (m.getType()) {
- case BOOL:
- measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
- break;
- case INT:
- case MILLISEC:
- measureToSave.setValue(Double.valueOf((Integer) measure.value()));
- break;
- case FLOAT:
- case PERCENT:
- case RATING:
- measureToSave.setValue((Double) measure.value());
- break;
- case STRING:
- case LEVEL:
- case DATA:
- case DISTRIB:
- measureToSave.setData((String) measure.value());
- break;
- case WORK_DUR:
- measureToSave.setValue(Double.valueOf((Long) measure.value()));
- break;
- default:
- throw new UnsupportedOperationException("Unsupported type :" + m.getType());
- }
- }
-
- @Override
- public void store(Issue issue) {
- Resource r;
- InputPath inputPath = issue.inputPath();
- if (inputPath != null) {
- if (inputPath instanceof InputDir) {
- r = Directory.create(inputPath.relativePath());
- } else {
- r = File.create(inputPath.relativePath());
- }
- } else {
- r = project;
- }
- Issuable issuable = perspectives.as(Issuable.class, r);
- if (issuable == null) {
- return;
- }
- issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
- }
-
- public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
- Severity overridenSeverity = issue.overridenSeverity();
- return new org.sonar.core.issue.DefaultIssueBuilder()
- .componentKey(componentKey)
- .projectKey(projectKey)
- .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
- .effortToFix(issue.effortToFix())
- .line(issue.line())
- .message(issue.message())
- .severity(overridenSeverity != null ? overridenSeverity.name() : null)
- .build();
- }
-
- @Override
- public void store(TestCaseExecution testCase) {
- File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile());
- MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
- if (testPlan != null) {
- testPlan
- .addTestCase(testCase.name())
- .setDurationInMs(testCase.durationInMs())
- .setType(testCase.type().name())
- .setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name()))
- .setMessage(testCase.message())
- .setStackTrace(testCase.stackTrace());
- }
- }
-
- @Override
- public void store(TestCaseCoverage testCaseCoverage) {
- File testRes = getTestResource(testCaseCoverage.testFile());
- File mainRes = getMainResource(testCaseCoverage.coveredFile());
- Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes);
- if (testAbleFile != null) {
- MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
- if (testPlan != null) {
- for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) {
- mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines());
- }
- } else {
- throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes);
- }
- } else {
- throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes);
- }
- }
-
- private File getTestResource(InputFile testFile) {
- File testRes = File.create(testFile.relativePath());
- testRes.setQualifier(Qualifiers.UNIT_TEST_FILE);
- // Reload
- testRes = sensorContext.getResource(testRes);
- if (testRes == null) {
- throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile);
- }
- return testRes;
- }
-
- private File getMainResource(InputFile mainFile) {
- File mainRes = File.create(mainFile.relativePath());
- // Reload
- mainRes = sensorContext.getResource(mainRes);
- if (mainRes == null) {
- throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes);
- }
- return mainRes;
- }
-
- private File getFile(InputFile file) {
- if (file.type() == InputFile.Type.MAIN) {
- return getMainResource(file);
- } else {
- return getTestResource(file);
- }
- }
-
- @Override
- public void store(org.sonar.api.batch.sensor.dependency.Dependency dep) {
- File fromResource = getFile(dep.from());
- File toResource = getFile(dep.to());
- if (sonarIndex.getEdge(fromResource, toResource) != null) {
- throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
- }
- Directory fromParent = fromResource.getParent();
- Directory toParent = toResource.getParent();
- Dependency parentDep = null;
- if (!fromParent.equals(toParent)) {
- parentDep = sonarIndex.getEdge(fromParent, toParent);
- if (parentDep != null) {
- parentDep.setWeight(parentDep.getWeight() + 1);
- } else {
- parentDep = new Dependency(fromParent, toParent).setUsage(USES).setWeight(1);
- parentDep = sensorContext.saveDependency(parentDep);
- }
- }
- sensorContext.saveDependency(new Dependency(fromResource, toResource)
- .setUsage(USES)
- .setWeight(dep.weight())
- .setParent(parentDep));
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java
deleted file mode 100644
index 621668853d3..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalysisPublisher.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * 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.scan2;
-
-import org.apache.commons.io.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.FileSystem;
-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.Issue.Severity;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.api.utils.text.JsonWriter;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Properties;
-
-public final class AnalysisPublisher {
-
- private static final Logger LOG = LoggerFactory.getLogger(AnalysisPublisher.class);
- private final Settings settings;
- private final FileSystem fs;
- private final MeasureCache measureCache;
- private final ProjectDefinition def;
- private final IssueCache issueCache;
-
- public AnalysisPublisher(ProjectDefinition def, Settings settings, FileSystem fs,
- MeasureCache measureCache,
- IssueCache analyzerIssueCache) {
- this.def = def;
- this.settings = settings;
- this.fs = fs;
- this.measureCache = measureCache;
- this.issueCache = analyzerIssueCache;
- }
-
- public void execute() {
- if (settings.getBoolean("sonar.skipPublish")) {
- LOG.debug("Publishing of results is skipped");
- return;
- }
- File exportDir = prepareExportDir();
-
- exportAnalysisProperties(exportDir);
-
- exportSourceFiles(exportDir);
-
- exportMeasures(exportDir);
-
- exportIssues(exportDir);
-
- createZip(exportDir);
-
- }
-
- private void createZip(File exportDir) {
- File exportZip = new File(fs.workDir(), def.getKey() + "-export.zip");
- try {
- ZipUtils.zipDir(exportDir, exportZip);
- FileUtils.deleteDirectory(exportDir);
- } catch (IOException e) {
- throw unableToExport(e);
- }
- LOG.info("Results packaged in " + exportZip);
- }
-
- private IllegalStateException unableToExport(IOException e) {
- return new IllegalStateException("Unable to export result of analyzis", e);
- }
-
- private void exportIssues(File exportDir) {
- File issuesFile = new File(exportDir, "issues.json");
- try (Writer issueWriter = new OutputStreamWriter(new FileOutputStream(issuesFile), Charsets.UTF_8)) {
- JsonWriter jsonWriter = JsonWriter.of(issueWriter);
- jsonWriter
- .beginObject().name("issues")
- .beginArray();
- for (Issue issue : issueCache.byModule(def.getKey())) {
- jsonWriter.beginObject()
- .prop("repository", issue.ruleKey().repository())
- .prop("rule", issue.ruleKey().rule());
- InputPath inputPath = issue.inputPath();
- if (inputPath != null) {
- jsonWriter.prop("path", inputPath.relativePath());
- }
- jsonWriter.prop("message", issue.message())
- .prop("effortToFix", issue.effortToFix())
- .prop("line", issue.line());
- Severity overridenSeverity = issue.overridenSeverity();
- if (overridenSeverity != null) {
- jsonWriter.prop("severity", overridenSeverity.name());
- }
- jsonWriter.endObject();
- }
- jsonWriter.endArray()
- .endObject()
- .close();
- } catch (IOException e) {
- throw unableToExport(e);
- }
- }
-
- private void exportMeasures(File exportDir) {
- File measuresFile = new File(exportDir, "measures.json");
- try (Writer measureWriter = new OutputStreamWriter(new FileOutputStream(measuresFile), Charsets.UTF_8)) {
- JsonWriter jsonWriter = JsonWriter.of(measureWriter);
- jsonWriter
- .beginObject().name("measures")
- .beginArray();
- for (Measure> measure : measureCache.byModule(def.getKey())) {
- jsonWriter.beginObject()
- .prop("metricKey", measure.metric().key());
- InputFile inputFile = measure.inputFile();
- if (inputFile != null) {
- jsonWriter.prop("filePath", inputFile.relativePath());
- }
- jsonWriter.prop("value", String.valueOf(measure.value()))
- .endObject();
- }
- jsonWriter.endArray()
- .endObject()
- .close();
- } catch (IOException e) {
- throw unableToExport(e);
- }
- }
-
- private void exportSourceFiles(File exportDir) {
- File sourceDir = new File(exportDir, "sources");
- for (InputFile inputFile : fs.inputFiles(fs.predicates().all())) {
- File dest = new File(sourceDir, inputFile.relativePath());
- try {
- FileUtils.copyFile(inputFile.file(), dest);
- } catch (IOException e) {
- throw unableToExport(e);
- }
- }
- }
-
- private void exportAnalysisProperties(File exportDir) {
- File propsFile = new File(exportDir, "analysis.properties");
- Properties props = new Properties();
- props.putAll(settings.getProperties());
- try (Writer writer = new OutputStreamWriter(new FileOutputStream(propsFile), Charsets.UTF_8)) {
- props.store(writer, "SonarQube batch");
- } catch (IOException e) {
- throw unableToExport(e);
- }
- }
-
- private File prepareExportDir() {
- File exportDir = new File(fs.workDir(), "export");
- try {
- if (exportDir.exists()) {
- FileUtils.forceDelete(exportDir);
- }
- FileUtils.forceMkdir(exportDir);
- } catch (IOException e) {
- throw unableToExport(e);
- }
- return exportDir;
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java
deleted file mode 100644
index 09b9e5b5f3e..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/BaseSensorContext.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.scan2;
-
-import com.google.common.base.Preconditions;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorStorage;
-import org.sonar.api.batch.sensor.dependency.Dependency;
-import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
-import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
-import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
-import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
-import org.sonar.api.batch.sensor.test.Coverage;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultCoverage;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.config.Settings;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DefaultTokenBuilder;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.scan.SensorContextAdapter;
-import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
-import org.sonar.duplications.internal.pmd.PmdBlockChunker;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Common bits between {@link DefaultSensorContext} and {@link SensorContextAdapter}
- * @author julien
- *
- */
-public abstract class BaseSensorContext implements SensorContext, SensorStorage {
-
- private final Settings settings;
- private final FileSystem fs;
- private final ActiveRules activeRules;
- private final ComponentDataCache componentDataCache;
- private final BlockCache blockCache;
- private final DuplicationCache duplicationCache;
-
- protected BaseSensorContext(Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache,
- BlockCache blockCache, DuplicationCache duplicationCache) {
- this.settings = settings;
- this.fs = fs;
- this.activeRules = activeRules;
- this.componentDataCache = componentDataCache;
- this.blockCache = blockCache;
- this.duplicationCache = duplicationCache;
- }
-
- @Override
- public Settings settings() {
- return settings;
- }
-
- @Override
- public FileSystem fileSystem() {
- return fs;
- }
-
- @Override
- public ActiveRules activeRules() {
- return activeRules;
- }
-
- @Override
- public Measure newMeasure() {
- return (Measure) new DefaultMeasure(this);
- }
-
- @Override
- public Issue newIssue() {
- return new DefaultIssue(this);
- }
-
- @Override
- public HighlightingBuilder highlightingBuilder(InputFile inputFile) {
- return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
- }
-
- @Override
- public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) {
- return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
- }
-
- @Override
- public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) {
- PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
-
- return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
- }
-
- @Override
- public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
- return new DefaultDuplicationBuilder(inputFile);
- }
-
- @Override
- public void saveDuplications(InputFile inputFile, List duplications) {
- Preconditions.checkState(!duplications.isEmpty(), "Empty duplications");
- String effectiveKey = ((DefaultInputFile) inputFile).key();
- for (DuplicationGroup duplicationGroup : duplications) {
- Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group");
- }
- duplicationCache.put(effectiveKey, duplications);
- }
-
- private int getBlockSize(String languageKey) {
- int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
- if (blockSize == 0) {
- blockSize = getDefaultBlockSize(languageKey);
- }
- return blockSize;
- }
-
- private static int getDefaultBlockSize(String languageKey) {
- if ("cobol".equals(languageKey)) {
- return 30;
- } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
- return 20;
- } else {
- return 10;
- }
- }
-
- @Override
- public Coverage newCoverage() {
- return new DefaultCoverage(this);
- }
-
- @Override
- public TestCaseExecution newTestCaseExecution() {
- return new DefaultTestCaseExecution(this);
- }
-
- @Override
- public TestCaseCoverage newTestCaseCoverage() {
- return new DefaultTestCaseCoverage(this);
- }
-
- @Override
- public Dependency newDependency() {
- return new DefaultDependency(this);
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
deleted file mode 100644
index cb70fa25b6a..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.scan2;
-
-import com.google.common.base.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.measure.Metric;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.DefaultActiveRule;
-import org.sonar.api.batch.sensor.dependency.Dependency;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.test.TestCaseCoverage;
-import org.sonar.api.batch.sensor.test.TestCaseExecution;
-import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.MessageException;
-import org.sonar.batch.dependency.DependencyCache;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.issue.IssueFilters;
-import org.sonar.batch.scan.SensorContextAdapter;
-import org.sonar.batch.test.TestCaseCoverageCache;
-import org.sonar.batch.test.TestCaseExecutionCache;
-import org.sonar.core.component.ComponentKeys;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
-
-public class DefaultSensorContext extends BaseSensorContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultSensorContext.class);
-
- public static final List INTERNAL_METRICS = Arrays.asList(
- // Computed by DsmDecorator
- CoreMetrics.DEPENDENCY_MATRIX,
- CoreMetrics.DIRECTORY_CYCLES,
- CoreMetrics.DIRECTORY_EDGES_WEIGHT,
- CoreMetrics.DIRECTORY_FEEDBACK_EDGES,
- CoreMetrics.DIRECTORY_TANGLE_INDEX,
- CoreMetrics.DIRECTORY_TANGLES,
- CoreMetrics.FILE_CYCLES,
- CoreMetrics.FILE_EDGES_WEIGHT,
- CoreMetrics.FILE_FEEDBACK_EDGES,
- CoreMetrics.FILE_TANGLE_INDEX,
- CoreMetrics.FILE_TANGLES,
- // Computed by ScmActivitySensor
- CoreMetrics.SCM_AUTHORS_BY_LINE,
- CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
- CoreMetrics.SCM_REVISIONS_BY_LINE,
- // Computed by core duplication plugin
- CoreMetrics.DUPLICATIONS_DATA,
- CoreMetrics.DUPLICATION_LINES_DATA,
- CoreMetrics.DUPLICATED_FILES,
- CoreMetrics.DUPLICATED_LINES,
- CoreMetrics.DUPLICATED_BLOCKS
- );
- private final MeasureCache measureCache;
- private final IssueCache issueCache;
- private final ProjectDefinition def;
- private final ActiveRules activeRules;
- private final IssueFilters issueFilters;
- private final TestCaseExecutionCache testCaseExecutionCache;
- private final TestCaseCoverageCache coveragePerTestCache;
- private final DependencyCache dependencyCache;
-
- public DefaultSensorContext(ProjectDefinition def, MeasureCache measureCache, IssueCache issueCache,
- Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache,
- BlockCache blockCache, DuplicationCache duplicationCache, TestCaseExecutionCache testCaseCache, TestCaseCoverageCache coveragePerTestCache, DependencyCache dependencyCache) {
- super(settings, fs, activeRules, componentDataCache, blockCache, duplicationCache);
- this.def = def;
- this.measureCache = measureCache;
- this.issueCache = issueCache;
- this.activeRules = activeRules;
- this.issueFilters = issueFilters;
- this.testCaseExecutionCache = testCaseCache;
- this.coveragePerTestCache = coveragePerTestCache;
- this.dependencyCache = dependencyCache;
- }
-
- @Override
- public void store(Measure newMeasure) {
- DefaultMeasure measure = (DefaultMeasure) newMeasure;
- if (!measure.isFromCore() && INTERNAL_METRICS.contains(measure.metric())) {
- throw new IllegalArgumentException("Metric " + measure.metric().key() + " is an internal metric computed by SonarQube. Please remove or update offending plugin.");
- }
- InputFile inputFile = measure.inputFile();
- if (inputFile != null) {
- measureCache.put(def.getKey(), ComponentKeys.createEffectiveKey(def.getKey(), inputFile), measure);
- } else {
- measureCache.put(def.getKey(), def.getKey(), measure);
- }
- }
-
- @Override
- public void store(Issue issue) {
- String resourceKey;
- InputPath inputPath = issue.inputPath();
- if (inputPath != null) {
- resourceKey = ComponentKeys.createEffectiveKey(def.getKey(), inputPath);
- } else {
- resourceKey = def.getKey();
- }
- RuleKey ruleKey = issue.ruleKey();
- DefaultActiveRule activeRule = (DefaultActiveRule) activeRules.find(ruleKey);
- if (activeRule == null) {
- // rule does not exist or is not enabled -> ignore the issue
- LOG.debug("Rule {} does not exists or is not enabled. Issue {} is ignored.", issue.ruleKey(), issue);
- return;
- }
- if (Strings.isNullOrEmpty(activeRule.name()) && Strings.isNullOrEmpty(issue.message())) {
- throw MessageException.of(String.format("The rule '%s' has no name and the related issue has no message.", ruleKey));
- }
-
- updateIssue((DefaultIssue) issue, activeRule);
-
- if (!issueFilters.accept(SensorContextAdapter.toDefaultIssue(def.getKey(), resourceKey, issue))) {
- LOG.debug("Issue {} was excluded by some filters.", issue);
- return;
- }
- issueCache.put(def.getKey(), resourceKey, (DefaultIssue) issue);
- }
-
- private void updateIssue(DefaultIssue issue, DefaultActiveRule activeRule) {
- if (Strings.isNullOrEmpty(issue.message())) {
- issue.message(activeRule.name());
- }
- }
-
- @Override
- public void store(TestCaseExecution testCaseExecution) {
- if (testCaseExecutionCache.contains(((DefaultTestCaseExecution) testCaseExecution).testFile(), testCaseExecution.name())) {
- throw new IllegalArgumentException("There is already a test case with the same name: " + testCaseExecution.name());
- }
- testCaseExecutionCache.put(((DefaultTestCaseExecution) testCaseExecution).testFile(), testCaseExecution);
- }
-
- @Override
- public void store(TestCaseCoverage testCaseCoverage) {
- if (coveragePerTestCache.getCoverage(testCaseCoverage.testFile(), testCaseCoverage.testName(), testCaseCoverage.coveredFile()) != null) {
- throw new IllegalArgumentException("Test coverage already registered for this combination of test file, test name and main file: " + testCaseCoverage);
- }
- coveragePerTestCache.put(testCaseCoverage);
- }
-
- @Override
- public void store(Dependency dep) {
- if (dependencyCache.get(def.getKey(), dep.from(), dep.to()) != null) {
- throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
- }
- dependencyCache.put(def.getKey(), dep);
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java
deleted file mode 100644
index e0c9d5a6db5..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/MeasureCache.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.scan2;
-
-import com.google.common.base.Preconditions;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.batch.index.Cache;
-import org.sonar.batch.index.Cache.Entry;
-import org.sonar.batch.index.Caches;
-import org.sonar.batch.scan.filesystem.InputPathCache;
-
-/**
- * Cache of all measures. This cache is shared amongst all project modules.
- */
-public class MeasureCache implements BatchComponent {
-
- // project key -> component key -> metric key -> measure
- private final Cache cache;
-
- public MeasureCache(Caches caches, MetricFinder metricFinder, InputPathCache inputPathCache) {
- caches.registerValueCoder(DefaultMeasure.class, new DefaultMeasureValueCoder(metricFinder, inputPathCache));
- cache = caches.createCache("measures");
- }
-
- public Iterable> entries() {
- return cache.entries();
- }
-
- public Iterable byModule(String projectKey) {
- return cache.values(projectKey);
- }
-
- public DefaultMeasure byMetric(String projectKey, String resourceKey, String metricKey) {
- return cache.get(projectKey, resourceKey, metricKey);
- }
-
- public MeasureCache put(String projectKey, String resourceKey, DefaultMeasure> measure) {
- Preconditions.checkNotNull(projectKey);
- Preconditions.checkNotNull(resourceKey);
- Preconditions.checkNotNull(measure);
- cache.put(projectKey, resourceKey, measure.metric().key(), measure);
- return this;
- }
-
- public boolean contains(String projectKey, String resourceKey, DefaultMeasure> measure) {
- Preconditions.checkNotNull(projectKey);
- Preconditions.checkNotNull(resourceKey);
- Preconditions.checkNotNull(measure);
- return cache.containsKey(projectKey, resourceKey, measure.metric().key());
- }
-
- public Iterable all() {
- return cache.values();
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
deleted file mode 100644
index 5d3cb485f47..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanContainer.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.scan2;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.InstantiationStrategy;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.rule.CheckFactory;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
-import org.sonar.batch.bootstrap.ExtensionInstaller;
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.events.EventBus;
-import org.sonar.batch.issue.IssuableFactory;
-import org.sonar.batch.issue.IssueFilters;
-import org.sonar.batch.issue.ModuleIssues;
-import org.sonar.batch.issue.ignore.EnforceIssuesFilter;
-import org.sonar.batch.issue.ignore.IgnoreIssuesFilter;
-import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
-import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
-import org.sonar.batch.rule.ActiveRulesProvider;
-import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileVerifier;
-import org.sonar.batch.scan.LanguageVerifier;
-import org.sonar.batch.scan.ModuleSettings;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
-import org.sonar.batch.scan.filesystem.ExclusionFilters;
-import org.sonar.batch.scan.filesystem.FileIndexer;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.filesystem.InputFileBuilderFactory;
-import org.sonar.batch.scan.filesystem.LanguageDetectionFactory;
-import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
-import org.sonar.batch.scan.filesystem.ModuleInputFileCache;
-import org.sonar.batch.scan.filesystem.StatusDetectionFactory;
-
-public class ModuleScanContainer extends ComponentContainer {
- private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
- private final ProjectDefinition moduleDefinition;
-
- public ModuleScanContainer(ProjectScanContainer parent, ProjectDefinition moduleDefinition) {
- super(parent);
- this.moduleDefinition = moduleDefinition;
- }
-
- @Override
- protected void doBeforeStart() {
- LOG.info("------------- Scan {}", moduleDefinition.getName());
- addCoreComponents();
- addExtensions();
- }
-
- private void addCoreComponents() {
- add(
- moduleDefinition,
- ModuleSettings.class,
-
- EventBus.class,
- ModuleScanExecutor.class,
- ModuleScanExecutor.getPhaseClasses(),
- moduleDefinition.getContainerExtensions(),
-
- // file system
- ModuleInputFileCache.class,
- FileExclusions.class,
- ExclusionFilters.class,
- DeprecatedFileFilters.class,
- InputFileBuilderFactory.class,
- StatusDetectionFactory.class,
- LanguageDetectionFactory.class,
- FileIndexer.class,
- LanguageVerifier.class,
- FileSystemLogger.class,
- DefaultModuleFileSystem.class,
- ModuleFileSystemInitializer.class,
- QProfileVerifier.class,
-
- AnalyzerOptimizer.class,
-
- DefaultSensorContext.class,
- BatchExtensionDictionnary.class,
- IssueFilters.class,
-
- // rules
- ModuleQProfiles.class,
- new ActiveRulesProvider(),
- CheckFactory.class,
-
- // issues
- IssuableFactory.class,
- ModuleIssues.class,
-
- // Measures
- DefaultFileLinesContextFactory.class,
-
- // issue exclusions
- IssueInclusionPatternInitializer.class,
- IssueExclusionPatternInitializer.class,
- IssueExclusionsRegexpScanner.class,
- IssueExclusionsLoader.class,
- EnforceIssuesFilter.class,
- IgnoreIssuesFilter.class,
-
- AnalysisPublisher.class);
- }
-
- private void addExtensions() {
- ExtensionInstaller installer = getComponentByType(ExtensionInstaller.class);
- installer.install(this, new ExtensionMatcher() {
- @Override
- public boolean accept(Object extension) {
- return ExtensionUtils.isType(extension, BatchComponent.class)
- && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_PROJECT);
- }
- });
- }
-
- @Override
- protected void doAfterStart() {
- getComponentByType(ModuleScanExecutor.class).execute();
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanExecutor.java
index 088125818df..943f93e1db0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ModuleScanExecutor.java
@@ -37,19 +37,16 @@ public final class ModuleScanExecutor {
private final QProfileVerifier profileVerifier;
private final IssueExclusionsLoader issueExclusionsLoader;
- private AnalysisPublisher analyzisPublisher;
-
public ModuleScanExecutor(SensorsExecutor analyzersExecutor,
SensorContext analyzerContext,
FileSystemLogger fsLogger, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
- IssueExclusionsLoader issueExclusionsLoader, AnalysisPublisher analyzisPublisher) {
+ IssueExclusionsLoader issueExclusionsLoader) {
this.analyzersExecutor = analyzersExecutor;
this.analyzerContext = analyzerContext;
this.fsLogger = fsLogger;
this.fs = fs;
this.profileVerifier = profileVerifier;
this.issueExclusionsLoader = issueExclusionsLoader;
- this.analyzisPublisher = analyzisPublisher;
}
public static Collection getPhaseClasses() {
@@ -73,8 +70,5 @@ public final class ModuleScanExecutor {
analyzersExecutor.execute(analyzerContext);
- // Export results
- analyzisPublisher.execute();
-
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
deleted file mode 100644
index 5f796661473..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.scan2;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.InstantiationStrategy;
-import org.sonar.api.batch.bootstrap.ProjectBootstrapper;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.scan.filesystem.PathResolver;
-import org.sonar.batch.bootstrap.ExtensionInstaller;
-import org.sonar.batch.bootstrap.ExtensionMatcher;
-import org.sonar.batch.bootstrap.ExtensionUtils;
-import org.sonar.batch.dependency.DependencyCache;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.Caches;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.languages.DefaultLanguagesReferential;
-import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
-import org.sonar.batch.referential.DefaultProjectReferentialsLoader;
-import org.sonar.batch.referential.ProjectReferentialsLoader;
-import org.sonar.batch.referential.ProjectReferentialsProvider;
-import org.sonar.batch.scan.ProjectReactorBuilder;
-import org.sonar.batch.scan.ProjectSettings;
-import org.sonar.batch.scan.filesystem.InputPathCache;
-import org.sonar.batch.scan.maven.FakeMavenPluginExecutor;
-import org.sonar.batch.scan.maven.MavenPluginExecutor;
-import org.sonar.batch.test.TestCaseCoverageCache;
-import org.sonar.batch.test.TestCaseExecutionCache;
-
-public class ProjectScanContainer extends ComponentContainer {
- public ProjectScanContainer(ComponentContainer taskContainer) {
- super(taskContainer);
- }
-
- @Override
- protected void doBeforeStart() {
- projectBootstrap();
- addBatchComponents();
- fixMavenExecutor();
- addBatchExtensions();
- Settings settings = getComponentByType(Settings.class);
- if (settings != null && settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
- add(PhasesSumUpTimeProfiler.class);
- }
- }
-
- private void projectBootstrap() {
- ProjectReactor reactor;
- ProjectBootstrapper bootstrapper = getComponentByType(ProjectBootstrapper.class);
- Settings settings = getComponentByType(Settings.class);
- if (bootstrapper == null
- // Starting from Maven plugin 2.3 then only DefaultProjectBootstrapper should be used.
- || "true".equals(settings.getString("sonar.mojoUseRunner"))) {
- // Use default SonarRunner project bootstrapper
- ProjectReactorBuilder builder = getComponentByType(ProjectReactorBuilder.class);
- reactor = builder.execute();
- } else {
- reactor = bootstrapper.bootstrap();
- }
- if (reactor == null) {
- throw new IllegalStateException(bootstrapper + " has returned null as ProjectReactor");
- }
- add(reactor);
- if (getComponentByType(ProjectReferentialsLoader.class) == null) {
- add(DefaultProjectReferentialsLoader.class);
- }
- }
-
- private void addBatchComponents() {
- add(
- new ProjectReferentialsProvider(),
- ProjectSettings.class,
- Caches.class,
- ResourceCache.class,
-
- // lang
- Languages.class,
- DefaultLanguagesReferential.class,
-
- // Measures
- MeasureCache.class,
-
- // file system
- InputPathCache.class,
- PathResolver.class,
-
- // issues
- IssueCache.class,
-
- // Syntax highlighting and symbols
- ComponentDataCache.class,
-
- // Duplications
- BlockCache.class,
- DuplicationCache.class,
-
- // Tests
- TestCaseExecutionCache.class,
- TestCaseCoverageCache.class,
-
- // Dependencies
- DependencyCache.class,
-
- ScanTaskObservers.class);
- }
-
- private void fixMavenExecutor() {
- if (getComponentByType(MavenPluginExecutor.class) == null) {
- add(FakeMavenPluginExecutor.class);
- }
- }
-
- private void addBatchExtensions() {
- getComponentByType(ExtensionInstaller.class).install(this, new BatchExtensionFilter());
- }
-
- @Override
- protected void doAfterStart() {
- ProjectReactor tree = getComponentByType(ProjectReactor.class);
- scanRecursively(tree.getRoot());
-
- getComponentByType(ScanTaskObservers.class).notifyEndOfScanTask();
- }
-
- private void scanRecursively(ProjectDefinition module) {
- for (ProjectDefinition subModules : module.getSubProjects()) {
- scanRecursively(subModules);
- }
- scan(module);
- }
-
- @VisibleForTesting
- void scan(ProjectDefinition module) {
- new ModuleScanContainer(this, module).execute();
- }
-
- static class BatchExtensionFilter implements ExtensionMatcher {
- @Override
- public boolean accept(Object extension) {
- return ExtensionUtils.isType(extension, BatchComponent.class)
- && ExtensionUtils.isInstantiationStrategy(extension, InstantiationStrategy.PER_BATCH);
- }
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java
deleted file mode 100644
index 636ed9f34ed..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObserver.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.scan2;
-
-import org.sonar.api.BatchExtension;
-
-public interface ScanTaskObserver extends BatchExtension {
-
- void scanTaskCompleted(ProjectScanContainer container);
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java
deleted file mode 100644
index 6dc8fa6fd40..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ScanTaskObservers.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.scan2;
-
-public class ScanTaskObservers {
-
- private ScanTaskObserver[] observers;
- private ProjectScanContainer projectScanContainer;
-
- public ScanTaskObservers(ProjectScanContainer projectScanContainer, ScanTaskObserver... observers) {
- this.projectScanContainer = projectScanContainer;
- this.observers = observers;
- }
-
- public ScanTaskObservers(ProjectScanContainer projectScanContainer) {
- this(projectScanContainer, new ScanTaskObserver[0]);
- }
-
- public void notifyEndOfScanTask() {
- for (ScanTaskObserver scanTaskObserver : observers) {
- scanTaskObserver.scanTaskCompleted(projectScanContainer);
- }
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java
new file mode 100644
index 00000000000..e02fe9e1f90
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java
@@ -0,0 +1,180 @@
+/*
+ * 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.sensor;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.batch.sensor.dependency.Dependency;
+import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
+import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
+import org.sonar.api.batch.sensor.duplication.DuplicationGroup;
+import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
+import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder;
+import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
+import org.sonar.api.batch.sensor.test.Coverage;
+import org.sonar.api.batch.sensor.test.TestCaseCoverage;
+import org.sonar.api.batch.sensor.test.TestCaseExecution;
+import org.sonar.api.batch.sensor.test.internal.DefaultCoverage;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseCoverage;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
+import org.sonar.api.config.Settings;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DefaultTokenBuilder;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
+import org.sonar.duplications.internal.pmd.PmdBlockChunker;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * Common bits between {@link ExperimentalSensorStorage} and {@link SensorContextAdapter}
+ * @author julien
+ *
+ */
+public class DefaultSensorContext implements SensorContext {
+
+ private final Settings settings;
+ private final FileSystem fs;
+ private final ActiveRules activeRules;
+ private final ComponentDataCache componentDataCache;
+ private final BlockCache blockCache;
+ private final DuplicationCache duplicationCache;
+ private final SensorStorage sensorStorage;
+
+ public DefaultSensorContext(Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache,
+ BlockCache blockCache, DuplicationCache duplicationCache, SensorStorage sensorStorage) {
+ this.settings = settings;
+ this.fs = fs;
+ this.activeRules = activeRules;
+ this.componentDataCache = componentDataCache;
+ this.blockCache = blockCache;
+ this.duplicationCache = duplicationCache;
+ this.sensorStorage = sensorStorage;
+ }
+
+ @Override
+ public Settings settings() {
+ return settings;
+ }
+
+ @Override
+ public FileSystem fileSystem() {
+ return fs;
+ }
+
+ @Override
+ public ActiveRules activeRules() {
+ return activeRules;
+ }
+
+ @Override
+ public NewMeasure newMeasure() {
+ return new DefaultMeasure(sensorStorage);
+ }
+
+ @Override
+ public Issue newIssue() {
+ return new DefaultIssue(sensorStorage);
+ }
+
+ @Override
+ public HighlightingBuilder highlightingBuilder(InputFile inputFile) {
+ return new DefaultHighlightingBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
+ }
+
+ @Override
+ public SymbolTableBuilder symbolTableBuilder(InputFile inputFile) {
+ return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
+ }
+
+ @Override
+ public DuplicationTokenBuilder duplicationTokenBuilder(InputFile inputFile) {
+ PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
+
+ return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
+ }
+
+ @Override
+ public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
+ return new DefaultDuplicationBuilder(inputFile);
+ }
+
+ @Override
+ public void saveDuplications(InputFile inputFile, List duplications) {
+ Preconditions.checkState(!duplications.isEmpty(), "Empty duplications");
+ String effectiveKey = ((DefaultInputFile) inputFile).key();
+ for (DuplicationGroup duplicationGroup : duplications) {
+ Preconditions.checkState(effectiveKey.equals(duplicationGroup.originBlock().resourceKey()), "Invalid duplication group");
+ }
+ duplicationCache.put(effectiveKey, duplications);
+ }
+
+ private int getBlockSize(String languageKey) {
+ int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
+ if (blockSize == 0) {
+ blockSize = getDefaultBlockSize(languageKey);
+ }
+ return blockSize;
+ }
+
+ private static int getDefaultBlockSize(String languageKey) {
+ if ("cobol".equals(languageKey)) {
+ return 30;
+ } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
+ return 20;
+ } else {
+ return 10;
+ }
+ }
+
+ @Override
+ public Coverage newCoverage() {
+ return new DefaultCoverage(sensorStorage);
+ }
+
+ @Override
+ public TestCaseExecution newTestCaseExecution() {
+ return new DefaultTestCaseExecution(sensorStorage);
+ }
+
+ @Override
+ public TestCaseCoverage newTestCaseCoverage() {
+ return new DefaultTestCaseCoverage(sensorStorage);
+ }
+
+ @Override
+ public Dependency newDependency() {
+ return new DefaultDependency(sensorStorage);
+ }
+
+}
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
new file mode 100644
index 00000000000..c1c3e2ba384
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
@@ -0,0 +1,262 @@
+/*
+ * 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.sensor;
+
+import org.sonar.api.batch.fs.FileSystem;
+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.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.Issue.Severity;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.test.TestCaseCoverage;
+import org.sonar.api.batch.sensor.test.TestCaseExecution;
+import org.sonar.api.batch.sensor.test.internal.DefaultTestCaseExecution;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.measures.Formula;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.measures.SumChildDistributionFormula;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.test.MutableTestCase;
+import org.sonar.api.test.MutableTestPlan;
+import org.sonar.api.test.MutableTestable;
+import org.sonar.api.test.Testable;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.DefaultIndex;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+import org.sonar.core.component.ComponentKeys;
+
+public class DefaultSensorStorage implements SensorStorage {
+
+ private static final String USES = "USES";
+ private final MetricFinder metricFinder;
+ private final Project project;
+ private final ResourcePerspectives perspectives;
+ private final DefaultIndex sonarIndex;
+ private final CoverageExclusions coverageExclusions;
+
+ public DefaultSensorStorage(MetricFinder metricFinder, Project project,
+ ResourcePerspectives perspectives,
+ Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
+ DuplicationCache duplicationCache, DefaultIndex sonarIndex, CoverageExclusions coverageExclusions) {
+ this.metricFinder = metricFinder;
+ this.project = project;
+ this.perspectives = perspectives;
+ this.sonarIndex = sonarIndex;
+ this.coverageExclusions = coverageExclusions;
+ }
+
+ private Metric findMetricOrFail(String metricKey) {
+ Metric m = (Metric) metricFinder.findByKey(metricKey);
+ if (m == null) {
+ throw new IllegalStateException("Unknow metric with key: " + metricKey);
+ }
+ return m;
+ }
+
+ @Override
+ public void store(Measure newMeasure) {
+ DefaultMeasure measure = (DefaultMeasure) newMeasure;
+ org.sonar.api.measures.Metric m = findMetricOrFail(measure.metric().key());
+ org.sonar.api.measures.Measure measureToSave = new org.sonar.api.measures.Measure(m);
+ setValueAccordingToMetricType(newMeasure, m, measureToSave);
+ measureToSave.setFromCore(measure.isFromCore());
+ if (newMeasure.inputFile() != null) {
+ Formula formula = newMeasure.metric() instanceof org.sonar.api.measures.Metric ?
+ ((org.sonar.api.measures.Metric) newMeasure.metric()).getFormula() : null;
+ if (formula instanceof SumChildDistributionFormula
+ && !Scopes.isHigherThanOrEquals(Scopes.FILE, ((SumChildDistributionFormula) formula).getMinimumScopeToPersist())) {
+ measureToSave.setPersistenceMode(PersistenceMode.MEMORY);
+ }
+ File sonarFile = getFile(newMeasure.inputFile());
+ if (coverageExclusions.accept(sonarFile, measureToSave)) {
+ sonarIndex.addMeasure(sonarFile, measureToSave);
+ }
+ } else {
+ sonarIndex.addMeasure(project, measureToSave);
+ }
+ }
+
+ private void setValueAccordingToMetricType(Measure> measure, org.sonar.api.measures.Metric> m, org.sonar.api.measures.Measure measureToSave) {
+ switch (m.getType()) {
+ case BOOL:
+ measureToSave.setValue(Boolean.TRUE.equals(measure.value()) ? 1.0 : 0.0);
+ break;
+ case INT:
+ case MILLISEC:
+ measureToSave.setValue(Double.valueOf((Integer) measure.value()));
+ break;
+ case FLOAT:
+ case PERCENT:
+ case RATING:
+ measureToSave.setValue((Double) measure.value());
+ break;
+ case STRING:
+ case LEVEL:
+ case DATA:
+ case DISTRIB:
+ measureToSave.setData((String) measure.value());
+ break;
+ case WORK_DUR:
+ measureToSave.setValue(Double.valueOf((Long) measure.value()));
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported type :" + m.getType());
+ }
+ }
+
+ @Override
+ public void store(Issue issue) {
+ Resource r;
+ InputPath inputPath = issue.inputPath();
+ if (inputPath != null) {
+ if (inputPath instanceof InputDir) {
+ r = Directory.create(inputPath.relativePath());
+ } else {
+ r = File.create(inputPath.relativePath());
+ }
+ } else {
+ r = project;
+ }
+ Issuable issuable = perspectives.as(Issuable.class, r);
+ if (issuable == null) {
+ return;
+ }
+ issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
+ }
+
+ public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
+ Severity overridenSeverity = issue.overridenSeverity();
+ return new org.sonar.core.issue.DefaultIssueBuilder()
+ .componentKey(componentKey)
+ .projectKey(projectKey)
+ .ruleKey(RuleKey.of(issue.ruleKey().repository(), issue.ruleKey().rule()))
+ .effortToFix(issue.effortToFix())
+ .line(issue.line())
+ .message(issue.message())
+ .severity(overridenSeverity != null ? overridenSeverity.name() : null)
+ .build();
+ }
+
+ @Override
+ public void store(TestCaseExecution testCase) {
+ File testRes = getTestResource(((DefaultTestCaseExecution) testCase).testFile());
+ MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
+ if (testPlan != null) {
+ testPlan
+ .addTestCase(testCase.name())
+ .setDurationInMs(testCase.durationInMs())
+ .setType(testCase.type().name())
+ .setStatus(org.sonar.api.test.TestCase.Status.valueOf(testCase.status().name()))
+ .setMessage(testCase.message())
+ .setStackTrace(testCase.stackTrace());
+ }
+ }
+
+ @Override
+ public void store(TestCaseCoverage testCaseCoverage) {
+ File testRes = getTestResource(testCaseCoverage.testFile());
+ File mainRes = getMainResource(testCaseCoverage.coveredFile());
+ Testable testAbleFile = perspectives.as(MutableTestable.class, mainRes);
+ if (testAbleFile != null) {
+ MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testRes);
+ if (testPlan != null) {
+ for (MutableTestCase mutableTestCase : testPlan.testCasesByName(testCaseCoverage.testName())) {
+ mutableTestCase.setCoverageBlock(testAbleFile, testCaseCoverage.coveredLines());
+ }
+ } else {
+ throw new IllegalStateException("Unable to get MutableTestPlan perspective from " + testRes);
+ }
+ } else {
+ throw new IllegalStateException("Unable to get MutableTestable perspective from " + mainRes);
+ }
+ }
+
+ private File getTestResource(InputFile testFile) {
+ File testRes = File.create(testFile.relativePath());
+ testRes.setQualifier(Qualifiers.UNIT_TEST_FILE);
+ // Reload
+ testRes = sonarIndex.getResource(testRes);
+ if (testRes == null) {
+ throw new IllegalArgumentException("Provided input file is not indexed or not a test file: " + testFile);
+ }
+ return testRes;
+ }
+
+ private File getMainResource(InputFile mainFile) {
+ File mainRes = File.create(mainFile.relativePath());
+ // Reload
+ mainRes = sonarIndex.getResource(mainRes);
+ if (mainRes == null) {
+ throw new IllegalArgumentException("Provided input file is not indexed or not a main file: " + mainRes);
+ }
+ return mainRes;
+ }
+
+ private File getFile(InputFile file) {
+ if (file.type() == InputFile.Type.MAIN) {
+ return getMainResource(file);
+ } else {
+ return getTestResource(file);
+ }
+ }
+
+ @Override
+ public void store(org.sonar.api.batch.sensor.dependency.Dependency dep) {
+ File fromResource = getFile(dep.from());
+ File toResource = getFile(dep.to());
+ if (sonarIndex.getEdge(fromResource, toResource) != null) {
+ throw new IllegalStateException("Dependency between " + dep.from() + " and " + dep.to() + " was already saved.");
+ }
+ Directory fromParent = fromResource.getParent();
+ Directory toParent = toResource.getParent();
+ Dependency parentDep = null;
+ if (!fromParent.equals(toParent)) {
+ parentDep = sonarIndex.getEdge(fromParent, toParent);
+ if (parentDep != null) {
+ parentDep.setWeight(parentDep.getWeight() + 1);
+ } else {
+ parentDep = new Dependency(fromParent, toParent).setUsage(USES).setWeight(1);
+ parentDep = sonarIndex.addDependency(parentDep);
+ }
+ }
+ sonarIndex.addDependency(new Dependency(fromResource, toResource)
+ .setUsage(USES)
+ .setWeight(dep.weight())
+ .setParent(parentDep));
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java
new file mode 100644
index 00000000000..46aa7173716
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageConstants.java
@@ -0,0 +1,39 @@
+/*
+ * 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.sensor.coverage;
+
+import com.google.common.collect.ImmutableList;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+
+import java.util.Collection;
+
+public class CoverageConstants {
+
+ public static final Collection COVERAGE_METRICS = ImmutableList.of(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
+ CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
+ CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+
+ public static final Collection LINE_COVERAGE_METRICS = ImmutableList.of(CoreMetrics.UNCOVERED_LINES, CoreMetrics.LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
+ CoreMetrics.NEW_LINES_TO_COVER);
+
+ public static final Collection BRANCH_COVERAGE_METRICS = ImmutableList.of(CoreMetrics.UNCOVERED_CONDITIONS, CoreMetrics.CONDITIONS_TO_COVER,
+ CoreMetrics.NEW_UNCOVERED_CONDITIONS, CoreMetrics.NEW_CONDITIONS_TO_COVER);
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java
new file mode 100644
index 00000000000..1545c060d07
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/coverage/CoverageExclusions.java
@@ -0,0 +1,100 @@
+/*
+ * 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.sensor.coverage;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.ImmutableSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.utils.WildcardPattern;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+public class CoverageExclusions {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CoverageExclusions.class);
+
+ private final Settings settings;
+ private final ImmutableSet coverageMetrics;
+ private Collection resourcePatterns;
+
+ public CoverageExclusions(Settings settings) {
+ this.settings = settings;
+ this.coverageMetrics = ImmutableSet.builder()
+ .add(CoreMetrics.COVERAGE)
+ .addAll(CoverageConstants.COVERAGE_METRICS)
+ .add(CoreMetrics.LINE_COVERAGE)
+ .addAll(CoverageConstants.LINE_COVERAGE_METRICS)
+ .add(CoreMetrics.BRANCH_COVERAGE)
+ .addAll(CoverageConstants.BRANCH_COVERAGE_METRICS)
+ .build();
+
+ initPatterns();
+ }
+
+ public boolean accept(Resource resource, Measure measure) {
+ if (isCoverageMetric(measure.getMetric())) {
+ return !hasMatchingPattern(resource);
+ } else {
+ return true;
+ }
+ }
+
+ private boolean isCoverageMetric(Metric metric) {
+ return this.coverageMetrics.contains(metric);
+ }
+
+ private boolean hasMatchingPattern(Resource resource) {
+ boolean found = false;
+ Iterator iterator = resourcePatterns.iterator();
+ while (!found && iterator.hasNext()) {
+ found = resource.matchFilePattern(iterator.next().toString());
+ }
+ return found;
+ }
+
+ @VisibleForTesting
+ final void initPatterns() {
+ Builder builder = ImmutableList.builder();
+ for (String pattern : settings.getStringArray(CoreProperties.PROJECT_COVERAGE_EXCLUSIONS_PROPERTY)) {
+ builder.add(WildcardPattern.create(pattern));
+ }
+ resourcePatterns = builder.build();
+ log("Excluded sources for coverage: ", resourcePatterns);
+ }
+
+ private void log(String title, Collection patterns) {
+ if (!patterns.isEmpty()) {
+ LOG.info(title);
+ for (WildcardPattern pattern : patterns) {
+ LOG.info(" " + pattern);
+ }
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java
new file mode 100644
index 00000000000..de8138fcecd
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+@javax.annotation.ParametersAreNonnullByDefault
+package org.sonar.batch.sensor;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
index b0c2e3076d6..1509a65ffea 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
@@ -22,10 +22,10 @@ package org.sonar.batch.bootstrap;
import org.junit.Test;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.batch.scan2.AnalyzerOptimizer;
+import org.sonar.batch.sensor.DefaultSensorContext;
import java.util.Collection;
@@ -41,7 +41,7 @@ public class BatchExtensionDictionnaryTest {
for (BatchExtension extension : extensions) {
iocContainer.addSingleton(extension);
}
- return new BatchExtensionDictionnary(iocContainer, mock(SensorContext.class), mock(AnalyzerOptimizer.class));
+ return new BatchExtensionDictionnary(iocContainer, mock(DefaultSensorContext.class), mock(AnalyzerOptimizer.class));
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
index 6787ae5710f..f11c843c541 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
@@ -25,6 +25,9 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.TaskResult;
import org.sonar.xoo.XooPlugin;
@@ -92,10 +95,10 @@ public class MeasuresMediumTest {
assertThat(result.measures()).hasSize(2);
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.LINES)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue(20));
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.LINES)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue(20));
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
index b7aacbcd2d1..4a6e1a79cef 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
@@ -27,6 +27,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.TaskResult;
import org.sonar.xoo.XooPlugin;
@@ -80,15 +83,15 @@ public class ScmMediumTest {
assertThat(result.measures()).hasSize(5);
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.LINES)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue(5));
- //
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.LINES)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue(5));
+
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
}
@Test
@@ -136,15 +139,15 @@ public class ScmMediumTest {
assertThat(result.measures()).hasSize(5);
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.LINES)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue(5));
- //
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.LINES)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue(5));
+
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
}
@Test
@@ -167,15 +170,15 @@ public class ScmMediumTest {
assertThat(result.measures()).hasSize(5);
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.LINES)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue(5));
- //
- // assertThat(result.measures()).contains(new DefaultMeasure()
- // .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- // .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- // .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.LINES)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue(5));
+
+ assertThat(result.measures()).contains(new DefaultMeasure()
+ .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
+ .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
+ .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
}
private File prepareProject() throws IOException {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
index 1fd1c4e081c..3f471711146 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/phases/DecoratorsExecutorTest.java
@@ -33,7 +33,7 @@ import org.sonar.batch.DefaultDecoratorContext;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.measure.MeasurementFilters;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
@@ -67,7 +67,7 @@ public class DecoratorsExecutorTest {
doThrow(new SonarException()).when(decorator).decorate(any(Resource.class), any(DecoratorContext.class));
DecoratorsExecutor executor = new DecoratorsExecutor(mock(BatchExtensionDictionnary.class), new Project("key"), mock(SonarIndex.class),
- mock(EventBus.class), mock(MeasurementFilters.class), mock(MeasureCache.class), mock(MetricFinder.class), mock(DuplicationCache.class));
+ mock(EventBus.class), mock(CoverageExclusions.class), mock(MeasureCache.class), mock(MetricFinder.class), mock(DuplicationCache.class));
try {
executor.executeDecorator(decorator, mock(DefaultDecoratorContext.class), File.create("src/org/foo/Bar.java", "org/foo/Bar.java", null, false));
fail("Exception has not been thrown");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
deleted file mode 100644
index a5610c66aa2..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * 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.scan;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.SonarIndex;
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFile.Type;
-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.measure.MetricFinder;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
-import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
-import org.sonar.api.batch.sensor.issue.Issue.Severity;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.batch.duplication.BlockCache;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class SensorContextAdapterTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private ActiveRules activeRules;
- private DefaultFileSystem fs;
- private SensorContextAdapter adaptor;
- private SensorContext sensorContext;
- private Settings settings;
- private ResourcePerspectives resourcePerspectives;
- private Project project;
- private SonarIndex sonarIndex;
-
- @Before
- public void prepare() {
- activeRules = new ActiveRulesBuilder().build();
- fs = new DefaultFileSystem();
- MetricFinder metricFinder = mock(MetricFinder.class);
- when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
- when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
- sensorContext = mock(SensorContext.class);
- settings = new Settings();
- resourcePerspectives = mock(ResourcePerspectives.class);
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- BlockCache blockCache = mock(BlockCache.class);
- project = new Project("myProject");
- sonarIndex = mock(SonarIndex.class);
- adaptor = new SensorContextAdapter(sensorContext, metricFinder, project,
- resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sonarIndex);
- }
-
- @Test
- public void shouldProvideComponents() {
- assertThat(adaptor.activeRules()).isEqualTo(activeRules);
- assertThat(adaptor.fileSystem()).isEqualTo(fs);
- assertThat(adaptor.settings()).isEqualTo(settings);
-
- assertThat(adaptor.newIssue()).isNotNull();
- assertThat(adaptor.newMeasure()).isNotNull();
- }
-
- @Test
- public void shouldFailIfUnknowMetric() {
- InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Unknow metric with key: lines");
-
- adaptor.store(new DefaultMeasure()
- .onFile(file)
- .forMetric(CoreMetrics.LINES)
- .withValue(10));
- }
-
- @Test
- public void shouldSaveFileMeasureToSensorContext() {
- InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
- when(sensorContext.saveMeasure(eq(file), argumentCaptor.capture())).thenReturn(null);
-
- adaptor.store(new DefaultMeasure()
- .onFile(file)
- .forMetric(CoreMetrics.NCLOC)
- .withValue(10));
-
- org.sonar.api.measures.Measure m = argumentCaptor.getValue();
- assertThat(m.getValue()).isEqualTo(10.0);
- assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
- }
-
- @Test
- public void shouldSetAppropriatePersistenceMode() {
- // Metric FUNCTION_COMPLEXITY_DISTRIBUTION is only persisted on directories.
-
- InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
- when(sensorContext.saveMeasure(eq(file), argumentCaptor.capture())).thenReturn(null);
-
- adaptor.store(new DefaultMeasure()
- .onFile(file)
- .forMetric(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION)
- .withValue("foo"));
-
- org.sonar.api.measures.Measure m = argumentCaptor.getValue();
- assertThat(m.getData()).isEqualTo("foo");
- assertThat(m.getMetric()).isEqualTo(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
- assertThat(m.getPersistenceMode()).isEqualTo(PersistenceMode.MEMORY);
-
- }
-
- @Test
- public void shouldSaveProjectMeasureToSensorContext() {
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
- when(sensorContext.saveMeasure(argumentCaptor.capture())).thenReturn(null);
-
- adaptor.store(new DefaultMeasure()
- .onProject()
- .forMetric(CoreMetrics.NCLOC)
- .withValue(10));
-
- org.sonar.api.measures.Measure m = argumentCaptor.getValue();
- assertThat(m.getValue()).isEqualTo(10.0);
- assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
- }
-
- @Test
- public void shouldAddIssueOnFile() {
- InputFile file = new DefaultInputFile("foo", "src/Foo.php");
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, File.create("src/Foo.php"))).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
- adaptor.store(new DefaultIssue()
- .onFile(file)
- .ruleKey(RuleKey.of("foo", "bar"))
- .message("Foo")
- .atLine(3)
- .effortToFix(10.0));
-
- Issue issue = argumentCaptor.getValue();
- assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
- assertThat(issue.message()).isEqualTo("Foo");
- assertThat(issue.line()).isEqualTo(3);
- assertThat(issue.severity()).isNull();
- assertThat(issue.effortToFix()).isEqualTo(10.0);
- }
-
- @Test
- public void shouldAddIssueOnDirectory() {
- InputDir dir = new DefaultInputDir("foo", "src");
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, Directory.create("src"))).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
- adaptor.store(new DefaultIssue()
- .onDir(dir)
- .ruleKey(RuleKey.of("foo", "bar"))
- .message("Foo")
- .effortToFix(10.0));
-
- Issue issue = argumentCaptor.getValue();
- assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
- assertThat(issue.message()).isEqualTo("Foo");
- assertThat(issue.line()).isNull();
- assertThat(issue.severity()).isNull();
- assertThat(issue.effortToFix()).isEqualTo(10.0);
- }
-
- @Test
- public void shouldAddIssueOnProject() {
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, (Resource) project)).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
-
- adaptor.store(new DefaultIssue()
- .onProject()
- .ruleKey(RuleKey.of("foo", "bar"))
- .message("Foo")
- .overrideSeverity(Severity.BLOCKER)
- .effortToFix(10.0));
-
- Issue issue = argumentCaptor.getValue();
- assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
- assertThat(issue.message()).isEqualTo("Foo");
- assertThat(issue.line()).isNull();
- assertThat(issue.severity()).isEqualTo("BLOCKER");
- assertThat(issue.effortToFix()).isEqualTo(10.0);
- }
-
- @Test
- public void shouldStoreDependencyInSameFolder() {
-
- File foo = File.create("src/Foo.java");
- File bar = File.create("src/Bar.java");
- when(sensorContext.getResource(foo)).thenReturn(foo);
- when(sensorContext.getResource(bar)).thenReturn(bar);
-
- adaptor.store(new DefaultDependency()
- .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
- .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
- .weight(3));
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
- verify(sensorContext).saveDependency(argumentCaptor.capture());
- assertThat(argumentCaptor.getValue().getFrom()).isEqualTo(foo);
- assertThat(argumentCaptor.getValue().getTo()).isEqualTo(bar);
- assertThat(argumentCaptor.getValue().getWeight()).isEqualTo(3);
- assertThat(argumentCaptor.getValue().getUsage()).isEqualTo("USES");
- }
-
- @Test
- public void throw_if_attempt_to_save_same_dep_twice() {
-
- File foo = File.create("src/Foo.java");
- File bar = File.create("src/Bar.java");
- when(sensorContext.getResource(foo)).thenReturn(foo);
- when(sensorContext.getResource(bar)).thenReturn(bar);
- when(sonarIndex.getEdge(foo, bar)).thenReturn(new Dependency(foo, bar));
-
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Dependency between [moduleKey=foo, relative=src/Foo.java, abs=null] and [moduleKey=foo, relative=src/Bar.java, abs=null] was already saved.");
-
- adaptor.store(new DefaultDependency()
- .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
- .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
- .weight(3));
- }
-
- @Test
- public void shouldStoreDependencyInDifferentFolder() {
-
- File foo = File.create("src1/Foo.java");
- File bar = File.create("src2/Bar.java");
- when(sensorContext.getResource(foo)).thenReturn(foo);
- when(sensorContext.getResource(bar)).thenReturn(bar);
-
- adaptor.store(new DefaultDependency()
- .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
- .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
- .weight(3));
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
- verify(sensorContext, times(2)).saveDependency(argumentCaptor.capture());
- assertThat(argumentCaptor.getAllValues()).hasSize(2);
- Dependency value1 = argumentCaptor.getAllValues().get(0);
- assertThat(value1.getFrom()).isEqualTo(Directory.create("src1"));
- assertThat(value1.getTo()).isEqualTo(Directory.create("src2"));
- assertThat(value1.getWeight()).isEqualTo(1);
- assertThat(value1.getUsage()).isEqualTo("USES");
-
- Dependency value2 = argumentCaptor.getAllValues().get(1);
- assertThat(value2.getFrom()).isEqualTo(foo);
- assertThat(value2.getTo()).isEqualTo(bar);
- assertThat(value2.getWeight()).isEqualTo(3);
- assertThat(value2.getUsage()).isEqualTo("USES");
- }
-
- @Test
- public void shouldIncrementParentWeight() {
-
- File foo = File.create("src1/Foo.java");
- File bar = File.create("src2/Bar.java");
- Directory src1 = Directory.create("src1");
- Directory src2 = Directory.create("src2");
- when(sensorContext.getResource(foo)).thenReturn(foo);
- when(sensorContext.getResource(bar)).thenReturn(bar);
- Dependency parentDep = new Dependency(src1, src2).setWeight(4);
- when(sonarIndex.getEdge(src1, src2)).thenReturn(parentDep);
-
- adaptor.store(new DefaultDependency()
- .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
- .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
- .weight(3));
-
- ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
-
- verify(sensorContext).saveDependency(argumentCaptor.capture());
-
- assertThat(parentDep.getWeight()).isEqualTo(5);
-
- Dependency value = argumentCaptor.getValue();
- assertThat(value.getFrom()).isEqualTo(foo);
- assertThat(value.getTo()).isEqualTo(bar);
- assertThat(value.getWeight()).isEqualTo(3);
- assertThat(value.getUsage()).isEqualTo("USES");
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java
new file mode 100644
index 00000000000..b51dccd8f05
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorContextTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.internal.DefaultFileSystem;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.SensorStorage;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultSensorContextTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private ActiveRules activeRules;
+ private DefaultFileSystem fs;
+ private DefaultSensorContext adaptor;
+ private Settings settings;
+ private SensorStorage sensorStorage;
+
+ @Before
+ public void prepare() {
+ activeRules = new ActiveRulesBuilder().build();
+ fs = new DefaultFileSystem();
+ MetricFinder metricFinder = mock(MetricFinder.class);
+ when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
+ when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+ settings = new Settings();
+ ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ BlockCache blockCache = mock(BlockCache.class);
+ sensorStorage = mock(SensorStorage.class);
+ adaptor = new DefaultSensorContext(settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sensorStorage);
+ }
+
+ @Test
+ public void shouldProvideComponents() {
+ assertThat(adaptor.activeRules()).isEqualTo(activeRules);
+ assertThat(adaptor.fileSystem()).isEqualTo(fs);
+ assertThat(adaptor.settings()).isEqualTo(settings);
+
+ assertThat(adaptor.newIssue()).isNotNull();
+ assertThat(adaptor.newMeasure()).isNotNull();
+ }
+
+}
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
new file mode 100644
index 00000000000..c977124e861
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
@@ -0,0 +1,345 @@
+/*
+ * 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.sensor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
+import org.sonar.api.batch.fs.InputDir;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+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.measure.MetricFinder;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
+import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
+import org.sonar.api.batch.sensor.issue.Issue.Severity;
+import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.config.Settings;
+import org.sonar.api.design.Dependency;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.PersistenceMode;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.DefaultIndex;
+import org.sonar.batch.sensor.coverage.CoverageExclusions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DefaultSensorStorageTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private ActiveRules activeRules;
+ private DefaultFileSystem fs;
+ private DefaultSensorStorage sensorStorage;
+ private Settings settings;
+ private ResourcePerspectives resourcePerspectives;
+ private Project project;
+ private DefaultIndex sonarIndex;
+
+ @Before
+ public void prepare() {
+ activeRules = new ActiveRulesBuilder().build();
+ fs = new DefaultFileSystem();
+ MetricFinder metricFinder = mock(MetricFinder.class);
+ when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
+ when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+ settings = new Settings();
+ resourcePerspectives = mock(ResourcePerspectives.class);
+ ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ BlockCache blockCache = mock(BlockCache.class);
+ project = new Project("myProject");
+ sonarIndex = mock(DefaultIndex.class);
+ CoverageExclusions coverageExclusions = mock(CoverageExclusions.class);
+ when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true);
+ sensorStorage = new DefaultSensorStorage(metricFinder, project,
+ resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class), sonarIndex, coverageExclusions);
+ }
+
+ @Test
+ public void shouldFailIfUnknowMetric() {
+ InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("Unknow metric with key: lines");
+
+ sensorStorage.store(new DefaultMeasure()
+ .onFile(file)
+ .forMetric(CoreMetrics.LINES)
+ .withValue(10));
+ }
+
+ @Test
+ public void shouldSaveFileMeasureToSensorContext() {
+ InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+ File sonarFile = File.create("src/Foo.php");
+ when(sonarIndex.addMeasure(eq(sonarFile), argumentCaptor.capture())).thenReturn(null);
+ when(sonarIndex.getResource(sonarFile)).thenReturn(sonarFile);
+ sensorStorage.store(new DefaultMeasure()
+ .onFile(file)
+ .forMetric(CoreMetrics.NCLOC)
+ .withValue(10));
+
+ org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+ assertThat(m.getValue()).isEqualTo(10.0);
+ assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+ }
+
+ @Test
+ public void shouldSetAppropriatePersistenceMode() {
+ // Metric FUNCTION_COMPLEXITY_DISTRIBUTION is only persisted on directories.
+
+ InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+ File sonarFile = File.create("src/Foo.php");
+
+ when(sonarIndex.addMeasure(eq(sonarFile), argumentCaptor.capture())).thenReturn(null);
+
+ when(sonarIndex.getResource(sonarFile)).thenReturn(sonarFile);
+
+ sensorStorage.store(new DefaultMeasure()
+ .onFile(file)
+ .forMetric(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION)
+ .withValue("foo"));
+
+ org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+ assertThat(m.getData()).isEqualTo("foo");
+ assertThat(m.getMetric()).isEqualTo(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+ assertThat(m.getPersistenceMode()).isEqualTo(PersistenceMode.MEMORY);
+
+ }
+
+ @Test
+ public void shouldSaveProjectMeasureToSensorContext() {
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.measures.Measure.class);
+ when(sonarIndex.addMeasure(eq(project), argumentCaptor.capture())).thenReturn(null);
+
+ sensorStorage.store(new DefaultMeasure()
+ .onProject()
+ .forMetric(CoreMetrics.NCLOC)
+ .withValue(10));
+
+ org.sonar.api.measures.Measure m = argumentCaptor.getValue();
+ assertThat(m.getValue()).isEqualTo(10.0);
+ assertThat(m.getMetric()).isEqualTo(CoreMetrics.NCLOC);
+ }
+
+ @Test
+ public void shouldAddIssueOnFile() {
+ InputFile file = new DefaultInputFile("foo", "src/Foo.php");
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+ Issuable issuable = mock(Issuable.class);
+ when(resourcePerspectives.as(Issuable.class, File.create("src/Foo.php"))).thenReturn(issuable);
+
+ when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+ sensorStorage.store(new DefaultIssue()
+ .onFile(file)
+ .ruleKey(RuleKey.of("foo", "bar"))
+ .message("Foo")
+ .atLine(3)
+ .effortToFix(10.0));
+
+ Issue issue = argumentCaptor.getValue();
+ assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+ assertThat(issue.message()).isEqualTo("Foo");
+ assertThat(issue.line()).isEqualTo(3);
+ assertThat(issue.severity()).isNull();
+ assertThat(issue.effortToFix()).isEqualTo(10.0);
+ }
+
+ @Test
+ public void shouldAddIssueOnDirectory() {
+ InputDir dir = new DefaultInputDir("foo", "src");
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+ Issuable issuable = mock(Issuable.class);
+ when(resourcePerspectives.as(Issuable.class, Directory.create("src"))).thenReturn(issuable);
+
+ when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+ sensorStorage.store(new DefaultIssue()
+ .onDir(dir)
+ .ruleKey(RuleKey.of("foo", "bar"))
+ .message("Foo")
+ .effortToFix(10.0));
+
+ Issue issue = argumentCaptor.getValue();
+ assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+ assertThat(issue.message()).isEqualTo("Foo");
+ assertThat(issue.line()).isNull();
+ assertThat(issue.severity()).isNull();
+ assertThat(issue.effortToFix()).isEqualTo(10.0);
+ }
+
+ @Test
+ public void shouldAddIssueOnProject() {
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Issue.class);
+
+ Issuable issuable = mock(Issuable.class);
+ when(resourcePerspectives.as(Issuable.class, (Resource) project)).thenReturn(issuable);
+
+ when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+
+ sensorStorage.store(new DefaultIssue()
+ .onProject()
+ .ruleKey(RuleKey.of("foo", "bar"))
+ .message("Foo")
+ .overrideSeverity(Severity.BLOCKER)
+ .effortToFix(10.0));
+
+ Issue issue = argumentCaptor.getValue();
+ assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
+ assertThat(issue.message()).isEqualTo("Foo");
+ assertThat(issue.line()).isNull();
+ assertThat(issue.severity()).isEqualTo("BLOCKER");
+ assertThat(issue.effortToFix()).isEqualTo(10.0);
+ }
+
+ @Test
+ public void shouldStoreDependencyInSameFolder() {
+
+ File foo = File.create("src/Foo.java");
+ File bar = File.create("src/Bar.java");
+ when(sonarIndex.getResource(foo)).thenReturn(foo);
+ when(sonarIndex.getResource(bar)).thenReturn(bar);
+
+ sensorStorage.store(new DefaultDependency()
+ .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
+ .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
+ .weight(3));
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+ verify(sonarIndex).addDependency(argumentCaptor.capture());
+ assertThat(argumentCaptor.getValue().getFrom()).isEqualTo(foo);
+ assertThat(argumentCaptor.getValue().getTo()).isEqualTo(bar);
+ assertThat(argumentCaptor.getValue().getWeight()).isEqualTo(3);
+ assertThat(argumentCaptor.getValue().getUsage()).isEqualTo("USES");
+ }
+
+ @Test
+ public void throw_if_attempt_to_save_same_dep_twice() {
+
+ File foo = File.create("src/Foo.java");
+ File bar = File.create("src/Bar.java");
+ when(sonarIndex.getResource(foo)).thenReturn(foo);
+ when(sonarIndex.getResource(bar)).thenReturn(bar);
+ when(sonarIndex.getEdge(foo, bar)).thenReturn(new Dependency(foo, bar));
+
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("Dependency between [moduleKey=foo, relative=src/Foo.java, abs=null] and [moduleKey=foo, relative=src/Bar.java, abs=null] was already saved.");
+
+ sensorStorage.store(new DefaultDependency()
+ .from(new DefaultInputFile("foo", "src/Foo.java").setType(Type.MAIN))
+ .to(new DefaultInputFile("foo", "src/Bar.java").setType(Type.MAIN))
+ .weight(3));
+ }
+
+ @Test
+ public void shouldStoreDependencyInDifferentFolder() {
+
+ File foo = File.create("src1/Foo.java");
+ File bar = File.create("src2/Bar.java");
+ when(sonarIndex.getResource(foo)).thenReturn(foo);
+ when(sonarIndex.getResource(bar)).thenReturn(bar);
+
+ sensorStorage.store(new DefaultDependency()
+ .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
+ .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
+ .weight(3));
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+ verify(sonarIndex, times(2)).addDependency(argumentCaptor.capture());
+ assertThat(argumentCaptor.getAllValues()).hasSize(2);
+ Dependency value1 = argumentCaptor.getAllValues().get(0);
+ assertThat(value1.getFrom()).isEqualTo(Directory.create("src1"));
+ assertThat(value1.getTo()).isEqualTo(Directory.create("src2"));
+ assertThat(value1.getWeight()).isEqualTo(1);
+ assertThat(value1.getUsage()).isEqualTo("USES");
+
+ Dependency value2 = argumentCaptor.getAllValues().get(1);
+ assertThat(value2.getFrom()).isEqualTo(foo);
+ assertThat(value2.getTo()).isEqualTo(bar);
+ assertThat(value2.getWeight()).isEqualTo(3);
+ assertThat(value2.getUsage()).isEqualTo("USES");
+ }
+
+ @Test
+ public void shouldIncrementParentWeight() {
+
+ File foo = File.create("src1/Foo.java");
+ File bar = File.create("src2/Bar.java");
+ Directory src1 = Directory.create("src1");
+ Directory src2 = Directory.create("src2");
+ when(sonarIndex.getResource(foo)).thenReturn(foo);
+ when(sonarIndex.getResource(bar)).thenReturn(bar);
+ Dependency parentDep = new Dependency(src1, src2).setWeight(4);
+ when(sonarIndex.getEdge(src1, src2)).thenReturn(parentDep);
+
+ sensorStorage.store(new DefaultDependency()
+ .from(new DefaultInputFile("foo", "src1/Foo.java").setType(Type.MAIN))
+ .to(new DefaultInputFile("foo", "src2/Bar.java").setType(Type.MAIN))
+ .weight(3));
+
+ ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Dependency.class);
+
+ verify(sonarIndex).addDependency(argumentCaptor.capture());
+
+ assertThat(parentDep.getWeight()).isEqualTo(5);
+
+ Dependency value = argumentCaptor.getValue();
+ assertThat(value.getFrom()).isEqualTo(foo);
+ assertThat(value.getTo()).isEqualTo(bar);
+ assertThat(value.getWeight()).isEqualTo(3);
+ assertThat(value.getUsage()).isEqualTo("USES");
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java
new file mode 100644
index 00000000000..ec592a7962e
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/coverage/CoverageExclusionsTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.sensor.coverage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Resource;
+import org.sonar.core.config.ExclusionProperties;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CoverageExclusionsTest {
+
+ private Settings settings;
+
+ private CoverageExclusions filter;
+
+ @Before
+ public void createFilter() {
+ settings = new Settings(new PropertyDefinitions(ExclusionProperties.all()));
+ filter = new CoverageExclusions(settings);
+ }
+
+ @Test
+ public void shouldNotFilterNonCoverageMetrics() {
+ Measure otherMeasure = mock(Measure.class);
+ when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES);
+ assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue();
+ }
+
+ @Test
+ public void shouldFilterFileBasedOnPattern() {
+ Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
+ Measure coverageMeasure = mock(Measure.class);
+ when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
+
+ settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
+ filter.initPatterns();
+ assertThat(filter.accept(resource, coverageMeasure)).isFalse();
+ }
+
+ @Test
+ public void shouldNotFilterFileBasedOnPattern() {
+ Resource resource = File.create("src/org/polop/File.php", "org/polop/File.php", null, false);
+ Measure coverageMeasure = mock(Measure.class);
+ when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
+
+ settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
+ filter.initPatterns();
+ assertThat(filter.accept(resource, coverageMeasure)).isTrue();
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java
deleted file mode 100644
index 324c7e4c1ca..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.core.measure;
-
-import org.sonar.api.BatchExtension;
-
-import org.sonar.api.resources.Resource;
-import org.sonar.api.measures.Measure;
-
-/**
- * Allows to define filter {@link Measure}s when they are saved on {@link Resource}s
- * @since 4.0
- *
- */
-public interface MeasurementFilter extends BatchExtension {
-
- /**
- *
- * @param resource
- * @param measure
- * @return true
if the given measure can be saved for the given resource
- */
- boolean accept(Resource resource, Measure measure);
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java
deleted file mode 100644
index fa69974571d..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasurementFilters.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.core.measure;
-
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.BatchExtension;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Resource;
-
-import java.util.Iterator;
-import java.util.List;
-
-/**
- *
- * @since 4.0
- *
- */
-public class MeasurementFilters implements BatchExtension {
-
- private List filters;
-
- public MeasurementFilters() {
- this.filters = ImmutableList.of();
- }
-
- public MeasurementFilters(MeasurementFilter[] filters) {
- this.filters = ImmutableList.copyOf(filters);
- }
-
- public boolean accept(Resource resource, Measure measure) {
- boolean accept = true;
- Iterator iteratorFilter = filters.iterator();
- while(accept && iteratorFilter.hasNext()) {
- accept &= iteratorFilter.next().accept(resource, measure);
- }
- return accept;
- }
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/package-info.java b/sonar-core/src/main/java/org/sonar/core/measure/package-info.java
deleted file mode 100644
index 036a513e710..00000000000
--- a/sonar-core/src/main/java/org/sonar/core/measure/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.core.measure;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java
deleted file mode 100644
index cc0f1022f84..00000000000
--- a/sonar-core/src/test/java/org/sonar/core/measure/MeasurementFiltersTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.core.measure;
-
-import org.assertj.core.util.Arrays;
-import org.junit.Test;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Resource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-public class MeasurementFiltersTest {
-
- private MeasurementFilters filters;
-
- @Test
- public void shouldAcceptEverythingWithEmptyFilters() {
- filters = new MeasurementFilters();
- Resource resource = mock(Resource.class);
- Measure measure = mock(Measure.class);
- assertThat(filters.accept(resource, measure)).isTrue();
- }
-
- @Test
- public void shouldAcceptIfAllFiltersAccept() {
- Resource resource = mock(Resource.class);
- Measure measure = mock(Measure.class);
- MeasurementFilter filter1 = mock(MeasurementFilter.class);
- when(filter1.accept(resource, measure)).thenReturn(true);
- MeasurementFilter filter2 = mock(MeasurementFilter.class);
- when(filter2.accept(resource, measure)).thenReturn(true);
-
- filters = new MeasurementFilters(Arrays.array(filter1, filter2));
- assertThat(filters.accept(resource, measure)).isTrue();
- }
-
- @Test
- public void shouldNnotAcceptIfOneFilterDoesntAccept() {
- Resource resource = mock(Resource.class);
- Measure measure = mock(Measure.class);
- MeasurementFilter filter1 = mock(MeasurementFilter.class);
- when(filter1.accept(resource, measure)).thenReturn(false);
- MeasurementFilter filter2 = mock(MeasurementFilter.class);
-
- filters = new MeasurementFilters(Arrays.array(filter1, filter2));
- assertThat(filters.accept(resource, measure)).isFalse();
- verifyZeroInteractions(filter2);
- }
-}
diff --git a/sonar-deprecated/src/main/java/org/sonar/api/checks/NoSonarFilter.java b/sonar-deprecated/src/main/java/org/sonar/api/checks/NoSonarFilter.java
index 7626ce1e018..16aa183e3a5 100644
--- a/sonar-deprecated/src/main/java/org/sonar/api/checks/NoSonarFilter.java
+++ b/sonar-deprecated/src/main/java/org/sonar/api/checks/NoSonarFilter.java
@@ -21,7 +21,7 @@ package org.sonar.api.checks;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.batch.IssueFilterChain;
import org.sonar.api.resources.Resource;
@@ -37,16 +37,16 @@ import java.util.Set;
public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter {
private final Map> noSonarLinesByKey = Maps.newHashMap();
- private SensorContext context;
+ private SonarIndex sonarIndex;
- public NoSonarFilter(SensorContext context) {
- this.context = context;
+ public NoSonarFilter(SonarIndex sonarIndex) {
+ this.sonarIndex = sonarIndex;
}
public void addResource(Resource model, Set noSonarLines) {
if (model != null && noSonarLines != null) {
// Reload resource to handle backward compatibility of resource keys
- Resource resource = context.getResource(model);
+ Resource resource = sonarIndex.getResource(model);
if (resource != null) {
noSonarLinesByKey.put(resource.getEffectiveKey(), noSonarLines);
}
diff --git a/sonar-deprecated/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java b/sonar-deprecated/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java
index 5be33366643..1521ca67b52 100644
--- a/sonar-deprecated/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java
+++ b/sonar-deprecated/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java
@@ -21,7 +21,7 @@ package org.sonar.api.checks;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.SonarIndex;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.batch.IssueFilterChain;
import org.sonar.api.resources.File;
@@ -37,8 +37,8 @@ import static org.mockito.Mockito.when;
public class NoSonarFilterTest {
- private SensorContext sensorContext = mock(SensorContext.class);
- NoSonarFilter filter = new NoSonarFilter(sensorContext);
+ private SonarIndex sonarIndex = mock(SonarIndex.class);
+ NoSonarFilter filter = new NoSonarFilter(sonarIndex);
private File javaFile;
IssueFilterChain chain = mock(IssueFilterChain.class);
@@ -47,7 +47,7 @@ public class NoSonarFilterTest {
when(chain.accept(isA(Issue.class))).thenReturn(true);
javaFile = new File("org.foo.Bar");
javaFile.setEffectiveKey("struts:org.apache.Action");
- when(sensorContext.getResource(javaFile)).thenReturn(javaFile);
+ when(sonarIndex.getResource(javaFile)).thenReturn(javaFile);
}
@Test
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index a21d421e6ac..b75209e1538 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -40,7 +40,7 @@ import java.util.Set;
/**
* @since 1.10
*/
-public interface SensorContext {
+public interface SensorContext extends org.sonar.api.batch.sensor.SensorContext {
/**
* Indexes a resource as a direct child of project. This method does nothing and returns true if the resource already indexed.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/maven/DependsUponMavenPlugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/maven/DependsUponMavenPlugin.java
index 0e590c84593..e83df0c84e6 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/maven/DependsUponMavenPlugin.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/maven/DependsUponMavenPlugin.java
@@ -33,7 +33,9 @@ import org.sonar.api.resources.Project;
*
*
* @since 1.10
+ * @deprecated since 5.1 SQ platform don't want any dependency on Maven
*/
+@Deprecated
@SupportedEnvironment("maven")
public interface DependsUponMavenPlugin extends BatchExtension {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java
index a0be6e447ab..01f0e109e53 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/Sensor.java
@@ -31,7 +31,7 @@ import org.sonar.api.BatchExtension;
* For example the Cobertura Sensor parses Cobertura report and saves the first-level of measures on files.
*
*
- * @since 5.0
+ * @since 5.1
*/
public interface Sensor extends BatchExtension {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
index 805d9db2417..b32be9c7ab0 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java
@@ -29,6 +29,7 @@ import org.sonar.api.batch.sensor.duplication.DuplicationTokenBuilder;
import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
import org.sonar.api.batch.sensor.test.Coverage;
import org.sonar.api.batch.sensor.test.TestCaseCoverage;
@@ -40,7 +41,7 @@ import java.util.List;
/**
* See {@link Sensor#execute(SensorContext)}
- * @since 5.0
+ * @since 5.1
*/
public interface SensorContext {
@@ -62,9 +63,9 @@ public interface SensorContext {
// ----------- MEASURES --------------
/**
- * Fluent builder to create a new {@link Measure}. Don't forget to call {@link Measure#save()} once all parameters are provided.
+ * Fluent builder to create a new {@link Measure}. Don't forget to call {@link NewMeasure#save()} once all parameters are provided.
*/
- Measure newMeasure();
+ NewMeasure newMeasure();
// ----------- ISSUES --------------
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 86a0abdffad..c59f7a7be76 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
@@ -27,21 +27,12 @@ import javax.annotation.CheckForNull;
import java.io.Serializable;
/**
- * Builder to create new Measure.
- * @since 5.0
+ * Measure on File, Directory or Project.
+ * Should not be implemented by client.
+ * @since 5.1
*/
public interface Measure {
- /**
- * The file the measure belongs to.
- */
- Measure onFile(InputFile file);
-
- /**
- * Tell that the measure is global to the project.
- */
- Measure onProject();
-
/**
* The file the measure belong to.
* @return null if measure is on project
@@ -49,29 +40,14 @@ public interface Measure {
@CheckForNull
InputFile inputFile();
- /**
- * Set the metric this measure belong to.
- */
- Measure forMetric(Metric metric);
-
/**
* The metric this measure belong to.
*/
Metric metric();
- /**
- * Value of the measure.
- */
- Measure withValue(G value);
-
/**
* Value of the measure.
*/
G value();
- /**
- * Save the measure. It is not permitted so save several measures of the same metric on the same file/project.
- */
- void save();
-
}
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
new file mode 100644
index 00000000000..cf8bccba48b
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/measure/NewMeasure.java
@@ -0,0 +1,59 @@
+/*
+ * 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.api.batch.sensor.measure;
+
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.Metric;
+
+import java.io.Serializable;
+
+/**
+ * Builder to create new Measure.
+ * Should not be implemented by client.
+ * @since 5.1
+ */
+public interface NewMeasure {
+
+ /**
+ * The file the measure belongs to.
+ */
+ NewMeasure onFile(InputFile file);
+
+ /**
+ * Tell that the measure is global to the project.
+ */
+ NewMeasure onProject();
+
+ /**
+ * Set the metric this measure belong to.
+ */
+ NewMeasure forMetric(Metric metric);
+
+ /**
+ * Value of the measure.
+ */
+ NewMeasure withValue(G value);
+
+ /**
+ * Save the measure. It is not permitted so save several measures of the same metric on the same file/project.
+ */
+ void save();
+
+}
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 167f9e6af98..a6e4a0021fa 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
@@ -27,13 +27,14 @@ import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.sensor.SensorStorage;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
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 {
+public class DefaultMeasure extends DefaultStorable implements Measure, NewMeasure {
private boolean onProject = false;
private InputFile file;
@@ -102,7 +103,7 @@ public class DefaultMeasure extends DefaultStorable impl
Preconditions.checkNotNull(this.value, "Measure value can't be null");
Preconditions.checkNotNull(this.metric, "Measure metric can't be null");
Preconditions.checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type " + this.metric.valueType());
- storage.store((Measure) this);
+ storage.store(this);
}
@Override
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java
index c6f68aaedce..bb89c172a07 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java
@@ -29,7 +29,9 @@ import java.util.List;
/**
* @since 2.5
+ * @deprecated since 5.1 use {@link org.sonar.api.batch.measure.MetricFinder} on batch side
*/
+@Deprecated
public interface MetricFinder extends TaskComponent, ServerComponent {
@CheckForNull