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;
// sensors
HasTagSensor.class,
MeasureSensor.class,
+ LineMeasureSensor.class,
SyntaxHighlightingSensor.class,
SymbolReferencesSensor.class,
ChecksSensor.class,
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
*/
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);
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;
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);
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);
}
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);
}
}
* 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;
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 {
@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);
}
.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();
}
}
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;
}
}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
.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"));
+ }
+
}