diff options
11 files changed, 317 insertions, 34 deletions
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index 74699697e87..38127ef52a3 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -26,6 +26,7 @@ import org.sonar.xoo.coverage.UtCoverageSensor; import org.sonar.xoo.extensions.XooPostJob; import org.sonar.xoo.extensions.XooProjectBuilder; import org.sonar.xoo.lang.CpdTokenizerSensor; +import org.sonar.xoo.lang.LineMeasureSensor; import org.sonar.xoo.lang.MeasureSensor; import org.sonar.xoo.lang.SymbolReferencesSensor; import org.sonar.xoo.lang.SyntaxHighlightingSensor; @@ -90,6 +91,7 @@ public class XooPlugin implements Plugin { // sensors HasTagSensor.class, MeasureSensor.class, + LineMeasureSensor.class, SyntaxHighlightingSensor.class, SymbolReferencesSensor.class, ChecksSensor.class, diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java new file mode 100644 index 00000000000..f0f92240949 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/LineMeasureSensor.java @@ -0,0 +1,111 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.xoo.lang; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.batch.fs.InputFile; +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.measures.FileLinesContext; +import org.sonar.api.measures.FileLinesContextFactory; +import org.sonar.api.utils.KeyValueFormat; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.xoo.Xoo; + +/** + * Parse files *.xoo.measures + */ +public class LineMeasureSensor implements Sensor { + + private static final Logger LOG = Loggers.get(LineMeasureSensor.class); + + private static final String MEASURES_EXTENSION = ".linemeasures"; + + private MetricFinder metricFinder; + + private FileLinesContextFactory contextFactory; + + public LineMeasureSensor(FileLinesContextFactory contextFactory) { + this.contextFactory = contextFactory; + this.metricFinder = metricFinder; + } + + private void processFileMeasures(InputFile inputFile, SensorContext context) { + File ioFile = inputFile.file(); + File measureFile = new File(ioFile.getParentFile(), ioFile.getName() + MEASURES_EXTENSION); + if (measureFile.exists()) { + LOG.debug("Processing " + measureFile.getAbsolutePath()); + try { + FileLinesContext linesContext = contextFactory.createFor(inputFile); + List<String> lines = FileUtils.readLines(measureFile, context.fileSystem().encoding().name()); + int lineNumber = 0; + for (String line : lines) { + lineNumber++; + if (StringUtils.isBlank(line) || line.startsWith("#")) { + continue; + } + processMeasure(inputFile, linesContext, measureFile, lineNumber, line); + } + linesContext.save(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + private void processMeasure(InputFile inputFile, FileLinesContext context, File measureFile, int lineNumber, String line) { + try { + String metricKey = StringUtils.substringBefore(line, ":"); + String value = line.substring(metricKey.length() + 1); + saveMeasure(context, inputFile, metricKey, KeyValueFormat.parseIntInt(value)); + } catch (Exception e) { + LOG.error("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e); + throw new IllegalStateException("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e); + } + } + + private void saveMeasure(FileLinesContext context, InputFile xooFile, String metricKey, Map<Integer, Integer> values) { + for (Map.Entry<Integer, Integer> entry : values.entrySet()) { + context.setIntValue(metricKey, entry.getKey(), entry.getValue()); + } + } + + @Override + public void describe(SensorDescriptor descriptor) { + descriptor + .name("Xoo Line Measure Sensor") + .onlyOnLanguages(Xoo.KEY); + } + + @Override + public void execute(SensorContext context) { + for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) { + processFileMeasures(file, context); + } + } +} 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 7eb71225771..a3c4cb9de46 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 @@ -42,16 +42,16 @@ import org.sonar.xoo.Xoo; */ public class SymbolReferencesSensor implements Sensor { + private static final Logger LOG = Loggers.get(SymbolReferencesSensor.class); + + private static final String SYMBOL_EXTENSION = ".symbol"; + private ResourcePerspectives perspectives; public SymbolReferencesSensor(ResourcePerspectives perspectives) { this.perspectives = perspectives; } - private static final Logger LOG = Loggers.get(SymbolReferencesSensor.class); - - private static final String SYMBOL_EXTENSION = ".symbol"; - private void processFileSymbol(InputFile inputFile, SensorContext context) { File ioFile = inputFile.file(); File symbolFile = new File(ioFile.getParentFile(), ioFile.getName() + SYMBOL_EXTENSION); 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 e0d28328382..f8cad18eefe 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 @@ -30,8 +30,9 @@ import org.sonar.api.batch.fs.InputFile; 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.highlighting.NewHighlighting; -import org.sonar.api.batch.sensor.highlighting.TypeOfText; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.source.Highlightable; +import org.sonar.api.source.Highlightable.HighlightingBuilder; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.xoo.Xoo; @@ -45,6 +46,12 @@ public class SyntaxHighlightingSensor implements Sensor { private static final String HIGHLIGHTING_EXTENSION = ".highlighting"; + private final ResourcePerspectives perspectives; + + public SyntaxHighlightingSensor(ResourcePerspectives perspectives) { + this.perspectives = perspectives; + } + private void processFileHighlighting(InputFile inputFile, SensorContext context) { File ioFile = inputFile.file(); File highlightingFile = new File(ioFile.getParentFile(), ioFile.getName() + HIGHLIGHTING_EXTENSION); @@ -53,28 +60,30 @@ public class SyntaxHighlightingSensor implements Sensor { try { List<String> lines = FileUtils.readLines(highlightingFile, context.fileSystem().encoding().name()); int lineNumber = 0; - NewHighlighting highlightingBuilder = context.newHighlighting().onFile(inputFile); - for (String line : lines) { - lineNumber++; - if (StringUtils.isBlank(line) || line.startsWith("#")) { - continue; + Highlightable highlightable = perspectives.as(Highlightable.class, inputFile); + if (highlightable != null) { + HighlightingBuilder highlightingBuilder = highlightable.newHighlighting(); + for (String line : lines) { + lineNumber++; + if (StringUtils.isBlank(line) || line.startsWith("#")) { + continue; + } + processLine(highlightingFile, lineNumber, highlightingBuilder, line); } - processLine(highlightingFile, lineNumber, highlightingBuilder, line); + highlightingBuilder.done(); } - highlightingBuilder.save(); } catch (IOException e) { throw new IllegalStateException(e); } } } - private static void processLine(File highlightingFile, int lineNumber, NewHighlighting highlightingBuilder, String line) { + private static void processLine(File highlightingFile, int lineNumber, HighlightingBuilder highlightingBuilder, String line) { try { Iterator<String> split = Splitter.on(":").split(line).iterator(); int startOffset = Integer.parseInt(split.next()); int endOffset = Integer.parseInt(split.next()); - TypeOfText type = TypeOfText.forCssClass(split.next()); - highlightingBuilder.highlight(startOffset, endOffset, type); + highlightingBuilder.highlight(startOffset, endOffset, split.next()); } catch (Exception e) { throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e); } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index 76198a3ac70..8c83a20bd32 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -33,10 +33,10 @@ public class XooPluginTest { public void provide_extensions_for_5_5() { Plugin.Context context = new Plugin.Context(V5_5); new XooPlugin().define(context); - assertThat(context.getExtensions()).hasSize(39).contains(CpdTokenizerSensor.class); + assertThat(context.getExtensions()).hasSize(40).contains(CpdTokenizerSensor.class); context = new Plugin.Context(Version.parse("5.4")); new XooPlugin().define(context); - assertThat(context.getExtensions()).hasSize(38).doesNotContain(CpdTokenizerSensor.class); + assertThat(context.getExtensions()).hasSize(39).doesNotContain(CpdTokenizerSensor.class); } } 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 7ce2dc972ff..cfd8be118eb 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 @@ -17,6 +17,25 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* +builder * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.xoo.lang; import java.io.File; diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java index 0a2b80da414..f46573a9534 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java @@ -27,11 +27,15 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; import org.sonar.api.batch.sensor.internal.SensorContextTester; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.source.Highlightable; +import org.sonar.api.source.Highlightable.HighlightingBuilder; -import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class SyntaxHighlightingSensorTest { @@ -41,11 +45,13 @@ public class SyntaxHighlightingSensorTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); private File baseDir; + private ResourcePerspectives perspectives; @Before public void prepare() throws IOException { baseDir = temp.newFolder(); - sensor = new SyntaxHighlightingSensor(); + perspectives = mock(ResourcePerspectives.class); + sensor = new SyntaxHighlightingSensor(perspectives); context = SensorContextTester.create(baseDir); } @@ -69,9 +75,15 @@ public class SyntaxHighlightingSensorTest { .initMetadata(" xoo\nazertyazer\nfoo"); context.fileSystem().add(inputFile); + Highlightable highlightable = mock(Highlightable.class); + when(perspectives.as(Highlightable.class, inputFile)).thenReturn(highlightable); + HighlightingBuilder builder = mock(Highlightable.HighlightingBuilder.class); + when(highlightable.newHighlighting()).thenReturn(builder); + sensor.execute(context); - assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 1, 2)).containsOnly(TypeOfText.KEYWORD); - assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 2, 8)).containsOnly(TypeOfText.CPP_DOC); + verify(builder).highlight(1, 4, "k"); + verify(builder).highlight(12, 15, "cppd"); + verify(builder).done(); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/MockAnalysisMode.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/MockAnalysisMode.java index 84980207ca3..9fe6895b334 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/MockAnalysisMode.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/MockAnalysisMode.java @@ -22,29 +22,24 @@ package org.sonar.api.batch.sensor.internal; import org.sonar.api.batch.AnalysisMode; public class MockAnalysisMode implements AnalysisMode { - private boolean isPreview = false; - private boolean isIssues = false; + private boolean previewOrIssue = false; @Override public boolean isPreview() { - return isPreview; + return previewOrIssue; } - public void setPreview(boolean value) { - this.isPreview = value; + public void setPreviewOrIssue(boolean value) { + this.previewOrIssue = value; } @Override public boolean isIssues() { - return this.isIssues; - } - - public void setIssues(boolean issues) { - this.isIssues = issues; + return this.previewOrIssue; } @Override public boolean isPublish() { - return !isPreview && !isIssues; + return !previewOrIssue; } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java new file mode 100644 index 00000000000..bd982d4695c --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/MockAnalysisModeTest.java @@ -0,0 +1,40 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.internal; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MockAnalysisModeTest { + + @Test + public void sanityCheck() { + MockAnalysisMode mode = new MockAnalysisMode(); + assertThat(mode.isIssues()).isFalse(); + assertThat(mode.isPreview()).isFalse(); + assertThat(mode.isPublish()).isTrue(); + mode.setPreviewOrIssue(true); + assertThat(mode.isIssues()).isTrue(); + assertThat(mode.isPreview()).isTrue(); + assertThat(mode.isPublish()).isFalse(); + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java new file mode 100644 index 00000000000..ee7ba4c0b20 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/symbol/internal/DefaultSymbolTableTest.java @@ -0,0 +1,69 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.symbol.internal; + +import java.util.Map; +import java.util.Set; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.batch.fs.TextRange; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.sensor.internal.SensorStorage; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +public class DefaultSymbolTableTest { + + private static final DefaultInputFile INPUT_FILE = new DefaultInputFile("foo", "src/Foo.java") + .setLines(2) + .setOriginalLineOffsets(new int[] {0, 50}) + .setLastValidOffset(100); + + private Map<TextRange, Set<TextRange>> referencesPerSymbol; + + @Rule + public ExpectedException throwable = ExpectedException.none(); + + @Before + public void setUpSampleSymbols() { + + DefaultSymbolTable symbolTableBuilder = new DefaultSymbolTable(mock(SensorStorage.class)) + .onFile(INPUT_FILE); + symbolTableBuilder + .newSymbol(0, 10) + .newReference(12, 15) + .newReference(2, 10, 2, 15); + + symbolTableBuilder.newSymbol(1, 12, 1, 15).newReference(52, 55); + + symbolTableBuilder.save(); + + referencesPerSymbol = symbolTableBuilder.getReferencesBySymbol(); + } + + @Test + public void should_register_symbols() { + assertThat(referencesPerSymbol).hasSize(2); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java index 0affd4dad8e..00e7ee34ab5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java @@ -125,4 +125,30 @@ public class MeasuresMediumTest { .contains(tuple("lines", 3), tuple("ncloc", 2)); } + @Test + public void lineMeasures() throws IOException { + File xooFile = new File(srcDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\n\n\ncontent"); + + File lineMeasures = new File(srcDir, "sample.xoo.linemeasures"); + FileUtils.write(lineMeasures, "ncloc_data:1=1;2=0;4=1"); + + TaskResult result = tester.newTask() + .properties(ImmutableMap.<String, String>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()) + .start(); + + Map<String, List<Measure>> allMeasures = result.allMeasures(); + + assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue.value", "stringValue.value") + .containsExactly(tuple("lines", 4, ""), tuple("ncloc_data", 0, "1=1;4=1")); + } + } |