From: Julien HENRY Date: Wed, 28 Nov 2018 11:10:44 +0000 (+0100) Subject: SONAR-11509 Ignore module and folder level measures in Sensor API X-Git-Tag: 7.6~94 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7be847605deb32e28afadd8dd53397ff4b5842c8;p=sonarqube.git SONAR-11509 Ignore module and folder level measures in Sensor API --- diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/MeasureSensor.java index 18d801397c4..0a839a7692d 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 @@ -26,6 +26,7 @@ import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.fs.InputComponent; +import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.sensor.Sensor; @@ -119,6 +120,11 @@ public class MeasureSensor implements Sensor { File ioFile = file.file(); File measureFile = new File(ioFile.getParentFile(), ioFile.getName() + MEASURES_EXTENSION); processFileMeasures(file, measureFile, context); + + InputDir inputDir = context.fileSystem().inputDir(ioFile.getParentFile()); + if (inputDir != null) { + processFileMeasures(inputDir, new File(ioFile.getParentFile(), "folder" + MEASURES_EXTENSION), context); + } } processFileMeasures(context.module(), new File(context.fileSystem().baseDir(), "module" + MEASURES_EXTENSION), context); } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java index 4415a058c23..7ed38d42e0e 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/MeasureSensorTest.java @@ -21,6 +21,7 @@ package org.sonar.xoo.lang; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.apache.commons.io.FileUtils; import org.junit.Before; import org.junit.Rule; @@ -76,7 +77,7 @@ public class MeasureSensorTest { @Test public void testExecution() throws IOException { File measures = new File(baseDir, "src/foo.xoo.measures"); - FileUtils.write(measures, "ncloc:12\nbranch_coverage:5.3\nsqale_index:300\nbool:true\n\n#comment"); + FileUtils.write(measures, "ncloc:12\nbranch_coverage:5.3\nsqale_index:300\nbool:true\n\n#comment", StandardCharsets.UTF_8); InputFile inputFile = new TestInputFileBuilder("foo", "src/foo.xoo").setLanguage("xoo").setModuleBaseDir(baseDir.toPath()).build(); context.fileSystem().add(inputFile); @@ -96,6 +97,26 @@ public class MeasureSensorTest { assertThat(context.measure("foo:src/foo.xoo", booleanMetric).value()).isTrue(); } + @Test + public void testExecutionForFoldersMeasures_no_measures() throws IOException { + File measures = new File(baseDir, "src/folder.measures"); + FileUtils.write(measures, "ncloc:12\nbranch_coverage:5.3\nsqale_index:300\nbool:true\n\n#comment", StandardCharsets.UTF_8); + InputFile inputFile = new TestInputFileBuilder("foo", "src/foo.xoo").setLanguage("xoo").setModuleBaseDir(baseDir.toPath()).build(); + context.fileSystem().add(inputFile); + + Metric booleanMetric = new Metric.Builder("bool", "Bool", Metric.ValueType.BOOL) + .create(); + + when(metricFinder.findByKey("ncloc")).thenReturn(CoreMetrics.NCLOC); + when(metricFinder.findByKey("branch_coverage")).thenReturn(CoreMetrics.BRANCH_COVERAGE); + when(metricFinder.findByKey("sqale_index")).thenReturn(CoreMetrics.TECHNICAL_DEBT); + when(metricFinder.findByKey("bool")).thenReturn(booleanMetric); + + sensor.execute(context); + + assertThat(context.measure("foo:src", CoreMetrics.NCLOC)).isNull(); + } + @Test public void failIfMetricNotFound() throws IOException { File measures = new File(baseDir, "src/foo.xoo.measures"); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java index 86acd4cb64b..db4deac109a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/AbstractProjectOrModule.java @@ -32,14 +32,10 @@ import javax.annotation.concurrent.Immutable; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; @Immutable public abstract class AbstractProjectOrModule extends DefaultInputComponent { - private static final Logger LOG = Loggers.get(AbstractProjectOrModule.class); - private final Path baseDir; private final Path workDir; private final String name; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java index 3fe625798c4..06213be6abb 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputModule.java @@ -27,15 +27,12 @@ import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv; @Immutable public class DefaultInputModule extends AbstractProjectOrModule implements InputModule { - private static final Logger LOG = Loggers.get(DefaultInputModule.class); private final List sourceDirsOrFiles; private final List testDirsOrFiles; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java index e4f447fffd8..bda3121b6ca 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java @@ -31,9 +31,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.annotation.Nullable; import org.sonar.api.batch.fs.InputComponent; +import org.sonar.api.batch.fs.InputDir; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.measure.Metric; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.sensor.code.internal.DefaultSignificantCode; @@ -231,10 +233,6 @@ public class DefaultSensorStorage implements SensorStorage { @Override public void store(Measure newMeasure) { - if (newMeasure.inputComponent() instanceof DefaultInputFile) { - DefaultInputFile defaultInputFile = (DefaultInputFile) newMeasure.inputComponent(); - defaultInputFile.setPublished(true); - } saveMeasure(newMeasure.inputComponent(), (DefaultMeasure) newMeasure); } @@ -250,6 +248,11 @@ public class DefaultSensorStorage implements SensorStorage { defaultInputFile.setPublished(true); } + if (component instanceof InputDir || (component instanceof DefaultInputModule && ((DefaultInputModule) component).definition().getParent() != null)) { + logOnce(measure.metric().key(), "Storing measures on folders or modules is deprecated. Provided value of metric '{}' is ignored.", measure.metric().key()); + return; + } + if (DEPRECATED_METRICS_KEYS.contains(measure.metric().key())) { logOnce(measure.metric().key(), "Metric '{}' is deprecated. Provided value is ignored.", measure.metric().key()); return; @@ -261,7 +264,7 @@ public class DefaultSensorStorage implements SensorStorage { } if (!measure.isFromCore() && NEWLY_CORE_METRICS_KEYS.contains(measure.metric().key())) { - logOnce(measure.metric().key(), "Metric '{}' is an internal metric computed by SonarQube. Provided value is ignored.", measure.metric().key()); + logOnce(measure.metric().key(), "Metric '{}' is an internal metric computed by SonarQube/SonarCloud. Provided value is ignored.", measure.metric().key()); return; } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java index 657abfc7534..395dff17b10 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumTest.java @@ -22,6 +22,7 @@ package org.sonar.scanner.mediumtest.measures; import com.google.common.collect.ImmutableMap; import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import org.apache.commons.io.FileUtils; @@ -66,19 +67,15 @@ public class MeasuresMediumTest { @Test public void applyExclusionsOnCoverageMeasures() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\ncontent"); + FileUtils.write(xooFile, "Sample xoo\n\ncontent", StandardCharsets.UTF_8); File measures = new File(srcDir, "sample.xoo.measures"); - FileUtils.write(measures, "lines_to_cover:2"); + FileUtils.write(measures, "lines_to_cover:2", StandardCharsets.UTF_8); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .build()) .execute(); @@ -90,12 +87,8 @@ public class MeasuresMediumTest { result = tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .put("sonar.coverage.exclusions", "src/sample.xoo") .build()) @@ -109,19 +102,15 @@ public class MeasuresMediumTest { @Test public void deprecatedCoverageMeasuresAreConverted() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\ncontent"); + FileUtils.write(xooFile, "Sample xoo\n\ncontent", StandardCharsets.UTF_8); File measures = new File(srcDir, "sample.xoo.measures"); - FileUtils.write(measures, "it_lines_to_cover:2"); + FileUtils.write(measures, "it_lines_to_cover:2", StandardCharsets.UTF_8); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .build()) .execute(); @@ -138,20 +127,16 @@ public class MeasuresMediumTest { @Test public void failIfTryingToSaveServerSideMeasure() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\ncontent"); + FileUtils.write(xooFile, "Sample xoo\n\ncontent", StandardCharsets.UTF_8); File measures = new File(srcDir, "sample.xoo.measures"); - FileUtils.write(measures, "new_lines:2"); + FileUtils.write(measures, "new_lines:2", StandardCharsets.UTF_8); try { tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .build()) .execute(); @@ -166,19 +151,15 @@ public class MeasuresMediumTest { @Test public void lineMeasures() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\n\ncontent"); + FileUtils.write(xooFile, "Sample xoo\n\n\ncontent", StandardCharsets.UTF_8); File lineMeasures = new File(srcDir, "sample.xoo.linemeasures"); - FileUtils.write(lineMeasures, "ncloc_data:1=1;2=0;4=1"); + FileUtils.write(lineMeasures, "ncloc_data:1=1;2=0;4=1", StandardCharsets.UTF_8); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .build()) .execute(); @@ -192,19 +173,15 @@ public class MeasuresMediumTest { @Test public void projectLevelMeasures() throws IOException { File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\n\n\ncontent"); + FileUtils.write(xooFile, "Sample xoo\n\n\ncontent", StandardCharsets.UTF_8); File projectMeasures = new File(baseDir, "module.measures"); - FileUtils.write(projectMeasures, "tests:10"); + FileUtils.write(projectMeasures, "tests:10", StandardCharsets.UTF_8); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() - .put("sonar.task", "scan") .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) .put("sonar.projectKey", "com.foo.project") - .put("sonar.projectName", "Foo Project") - .put("sonar.projectVersion", "1.0-SNAPSHOT") - .put("sonar.projectDescription", "Description of Foo Project") .put("sonar.sources", "src") .build()) .execute(); @@ -216,4 +193,50 @@ public class MeasuresMediumTest { .containsExactly(tuple("tests", 10, "")); } + @Test + public void warnWhenSavingFolderMeasure() throws IOException { + File xooFile = new File(srcDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\n\n\ncontent", StandardCharsets.UTF_8); + + File folderMeasures = new File(srcDir, "folder.measures"); + FileUtils.write(folderMeasures, "tests:10", StandardCharsets.UTF_8); + + AnalysisResult result = tester.newAnalysis() + .properties(ImmutableMap.builder() + .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) + .put("sonar.projectKey", "com.foo.project") + .put("sonar.sources", "src") + .build()) + .execute(); + + + assertThat(logTester.logs(LoggerLevel.WARN)).contains("Storing measures on folders or modules is deprecated. Provided value of metric 'tests' is ignored."); + } + + @Test + public void warnWhenSavingModuleMeasure() throws IOException { + File moduleDir = new File(baseDir, "moduleA"); + moduleDir.mkdirs(); + + srcDir = new File(moduleDir, "src"); + + File xooFile = new File(srcDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\n\n\ncontent", StandardCharsets.UTF_8); + + File moduleMeasures = new File(moduleDir, "module.measures"); + FileUtils.write(moduleMeasures, "tests:10", StandardCharsets.UTF_8); + + AnalysisResult result = tester.newAnalysis() + .properties(ImmutableMap.builder() + .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) + .put("sonar.projectKey", "com.foo.project") + .put("sonar.modules", "moduleA") + .put("sonar.sources", "src") + .build()) + .execute(); + + + assertThat(logTester.logs(LoggerLevel.WARN)).contains("Storing measures on folders or modules is deprecated. Provided value of metric 'tests' is ignored."); + } + } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java index 16a2911245a..9da8aaa3535 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java @@ -30,6 +30,7 @@ import org.junit.rules.TemporaryFolder; import org.mockito.ArgumentCaptor; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputDir; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.fs.internal.DefaultInputProject; @@ -63,6 +64,7 @@ import static org.assertj.core.data.MapEntry.entry; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -123,6 +125,29 @@ public class DefaultSensorStorageTest { .withValue(10)); } + @Test + public void shouldIgnoreMeasuresOnFolders() { + underTest.store(new DefaultMeasure() + .on(new DefaultInputDir("foo", "bar")) + .forMetric(CoreMetrics.LINES) + .withValue(10)); + + verifyNoMoreInteractions(measureCache); + } + + @Test + public void shouldIgnoreMeasuresOnModules() throws IOException { + ProjectDefinition module = ProjectDefinition.create().setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()); + ProjectDefinition root = ProjectDefinition.create().addSubProject(module); + + underTest.store(new DefaultMeasure() + .on(new DefaultInputModule(module)) + .forMetric(CoreMetrics.LINES) + .withValue(10)); + + verifyNoMoreInteractions(measureCache); + } + @Test public void should_save_issue() { InputFile file = new TestInputFileBuilder("foo", "src/Foo.php").build();