aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2015-06-08 16:40:48 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2015-07-23 13:56:46 +0200
commit056b4bdc63c2ef126d9f9d2e0526f60be930cb81 (patch)
tree197ba8a832ab132a2e95c86bebdb1e61576c5e98 /plugins
parentdb4af09e8b2c1f44f25a689c3165f5f6d8c01126 (diff)
downloadsonarqube-056b4bdc63c2ef126d9f9d2e0526f60be930cb81.tar.gz
sonarqube-056b4bdc63c2ef126d9f9d2e0526f60be930cb81.zip
SONAR-4865, SONAR-6052 Improved issue locations
Diffstat (limited to 'plugins')
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java2
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/checks/TemplateRuleCheck.java9
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java9
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/DeprecatedResourceApiSensor.java3
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/MultilineIssuesSensor.java112
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssueOnDirPerFileSensor.java9
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java12
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java16
-rw-r--r--plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java15
9 files changed, 159 insertions, 28 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 f76fde9b90a..a0f9cfdb4e8 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
@@ -33,6 +33,7 @@ import org.sonar.xoo.lang.XooTokenizer;
import org.sonar.xoo.rule.ChecksSensor;
import org.sonar.xoo.rule.CreateIssueByInternalKeySensor;
import org.sonar.xoo.rule.DeprecatedResourceApiSensor;
+import org.sonar.xoo.rule.MultilineIssuesSensor;
import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor;
import org.sonar.xoo.rule.OneIssuePerLineSensor;
import org.sonar.xoo.rule.RandomAccessSensor;
@@ -89,6 +90,7 @@ public class XooPlugin extends SonarPlugin {
OneIssuePerLineSensor.class,
OneIssueOnDirPerFileSensor.class,
CreateIssueByInternalKeySensor.class,
+ MultilineIssuesSensor.class,
// Coverage
UtCoverageSensor.class,
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/checks/TemplateRuleCheck.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/checks/TemplateRuleCheck.java
index 9e58a410526..c6fe84360c3 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/checks/TemplateRuleCheck.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/checks/TemplateRuleCheck.java
@@ -21,6 +21,7 @@ package org.sonar.xoo.checks;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.issue.NewIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.check.Cardinality;
import org.sonar.check.Rule;
@@ -36,10 +37,12 @@ public class TemplateRuleCheck implements Check {
@Override
public void execute(SensorContext sensorContext, InputFile file, RuleKey ruleKey) {
- sensorContext.newIssue()
- .onFile(file)
+ NewIssue newIssue = sensorContext.newIssue();
+ newIssue
.forRule(ruleKey)
- .atLine(line)
+ .addLocation(newIssue.newLocation()
+ .onFile(file)
+ .at(file.selectLine(line)))
.save();
}
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 5a1cefcab8e..47e8a16794d 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
@@ -27,6 +27,7 @@ import org.sonar.api.batch.rule.ActiveRule;
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.NewIssue;
import org.sonar.xoo.Xoo;
public class CreateIssueByInternalKeySensor implements Sensor {
@@ -54,10 +55,12 @@ public class CreateIssueByInternalKeySensor implements Sensor {
ActiveRule rule = context.activeRules().findByInternalKey(XooRulesDefinition.XOO_REPOSITORY,
context.settings().getString(INTERNAL_KEY_PROPERTY));
if (rule != null) {
- context.newIssue()
+ NewIssue newIssue = context.newIssue();
+ newIssue
.forRule(rule.ruleKey())
- .onFile(file)
- .message("This issue is generated on each file")
+ .addLocation(newIssue.newLocation()
+ .onFile(file)
+ .message("This issue is generated on each file"))
.save();
}
}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/DeprecatedResourceApiSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/DeprecatedResourceApiSensor.java
index 7cb80fbf541..99a6e39fe1a 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/DeprecatedResourceApiSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/DeprecatedResourceApiSensor.java
@@ -19,6 +19,7 @@
*/
package org.sonar.xoo.rule;
+import java.io.File;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.component.ResourcePerspectives;
@@ -31,8 +32,6 @@ import org.sonar.api.scan.filesystem.ModuleFileSystem;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.xoo.Xoo;
-import java.io.File;
-
public class DeprecatedResourceApiSensor implements Sensor {
public static final String RULE_KEY = "DeprecatedResourceApi";
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/MultilineIssuesSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/MultilineIssuesSensor.java
new file mode 100644
index 00000000000..a4bcca64eab
--- /dev/null
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/MultilineIssuesSensor.java
@@ -0,0 +1,112 @@
+/*
+ * 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.xoo.rule;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.sonar.api.batch.fs.FilePredicates;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.TextPointer;
+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.NewIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.xoo.Xoo;
+
+public class MultilineIssuesSensor implements Sensor {
+
+ public static final String RULE_KEY = "MultilineIssue";
+ private static final String START_ISSUE_PATTERN = "\\{xoo-start-issue:([0-9]+):([0-9]+)\\}";
+ private static final String END_ISSUE_PATTERN = "\\{xoo-end-issue:([0-9]+):([0-9]+)\\}";
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor
+ .name("Multiline Issues")
+ .onlyOnLanguages(Xoo.KEY)
+ .createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY);
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ FileSystem fs = context.fileSystem();
+ FilePredicates p = fs.predicates();
+ for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(Type.MAIN)))) {
+ createIssues(file, context);
+ }
+ }
+
+ private void createIssues(InputFile file, SensorContext context) {
+ Pattern startPattern = Pattern.compile(START_ISSUE_PATTERN);
+ Pattern endPattern = Pattern.compile(END_ISSUE_PATTERN);
+ Map<Integer, Map<Integer, TextPointer>> startPositions = new HashMap<>();
+ Map<Integer, Map<Integer, TextPointer>> endPositions = new HashMap<>();
+
+ RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY);
+ int currentLine = 0;
+ try {
+ for (String lineStr : Files.readAllLines(file.path(), context.fileSystem().encoding())) {
+ currentLine++;
+
+ Matcher m = startPattern.matcher(lineStr);
+ while (m.find()) {
+ Integer issueId = Integer.parseInt(m.group(1));
+ Integer issueLocationId = Integer.parseInt(m.group(2));
+ TextPointer newPointer = file.newPointer(currentLine, m.start());
+ if (!startPositions.containsKey(issueId)) {
+ startPositions.put(issueId, new HashMap<Integer, TextPointer>());
+ }
+ startPositions.get(issueId).put(issueLocationId, newPointer);
+ }
+
+ m = endPattern.matcher(lineStr);
+ while (m.find()) {
+ Integer issueId = Integer.parseInt(m.group(1));
+ Integer issueLocationId = Integer.parseInt(m.group(2));
+ TextPointer newPointer = file.newPointer(currentLine, m.start());
+ if (!endPositions.containsKey(issueId)) {
+ endPositions.put(issueId, new HashMap<Integer, TextPointer>());
+ }
+ endPositions.get(issueId).put(issueLocationId, newPointer);
+ }
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to read file", e);
+ }
+ for (Map.Entry<Integer, Map<Integer, TextPointer>> entry : startPositions.entrySet()) {
+ NewIssue newIssue = context.newIssue().forRule(ruleKey);
+ for (Map.Entry<Integer, TextPointer> location : entry.getValue().entrySet()) {
+ newIssue.addLocation(newIssue.newLocation()
+ .onFile(file)
+ .at(file.newRange(location.getValue(), endPositions.get(entry.getKey()).get(location.getKey())))
+ .message("Multiline issue"));
+ }
+ newIssue.save();
+ }
+ }
+
+}
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 6dbda2f741a..e53f0b17ccc 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
@@ -24,6 +24,7 @@ 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.issue.NewIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.xoo.Xoo;
@@ -50,10 +51,12 @@ public class OneIssueOnDirPerFileSensor implements Sensor {
RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY);
InputDir inputDir = context.fileSystem().inputDir(file.file().getParentFile());
if (inputDir != null) {
- context.newIssue()
+ NewIssue newIssue = context.newIssue();
+ newIssue
.forRule(ruleKey)
- .onDir(inputDir)
- .message("This issue is generated for file " + file.relativePath())
+ .addLocation(newIssue.newLocation()
+ .onDir(inputDir)
+ .message("This issue is generated for file " + file.relativePath()))
.save();
}
}
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 fc0a564c69c..e8aed769087 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
@@ -27,6 +27,7 @@ import org.sonar.api.batch.rule.Severity;
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.NewIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.xoo.Xoo;
@@ -57,14 +58,17 @@ public class OneIssuePerLineSensor implements Sensor {
RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY);
String severity = context.settings().getString(FORCE_SEVERITY_PROPERTY);
for (int line = 1; line <= file.lines(); line++) {
- context.newIssue()
+ NewIssue newIssue = context.newIssue();
+ newIssue
.forRule(ruleKey)
- .onFile(file)
- .atLine(line)
+ .addLocation(newIssue.newLocation()
+ .onFile(file)
+ .at(file.selectLine(line))
+ .message("This issue is generated on each line"))
.effortToFix(context.settings().getDouble(EFFORT_TO_FIX_PROPERTY))
.overrideSeverity(severity != null ? Severity.valueOf(severity) : null)
- .message("This issue is generated on each line")
.save();
}
}
+
}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java
index 0541d917552..69bf700b50b 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/RandomAccessSensor.java
@@ -19,6 +19,8 @@
*/
package org.sonar.xoo.rule;
+import java.io.File;
+import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
@@ -27,12 +29,10 @@ import org.sonar.api.batch.fs.InputFile.Type;
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.NewIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.xoo.Xoo;
-import java.io.File;
-import java.io.IOException;
-
public class RandomAccessSensor implements Sensor {
private static final String SONAR_XOO_RANDOM_ACCESS_ISSUE_PATHS = "sonar.xoo.randomAccessIssue.paths";
@@ -63,11 +63,13 @@ public class RandomAccessSensor implements Sensor {
private void createIssues(InputFile file, SensorContext context) {
RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY);
- context.newIssue()
+ NewIssue newIssue = context.newIssue();
+ newIssue
.forRule(ruleKey)
- .onFile(file)
- .atLine(1)
- .message("This issue is generated on each file")
+ .addLocation(newIssue.newLocation()
+ .onFile(file)
+ .at(file.selectLine(1))
+ .message("This issue is generated on each file"))
.save();
}
}
diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
index a3cbbf5eb84..2b422ba50ee 100644
--- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
+++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/OneIssuePerLineSensorTest.java
@@ -19,6 +19,8 @@
*/
package org.sonar.xoo.rule;
+import java.io.IOException;
+import java.io.StringReader;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -27,6 +29,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
@@ -36,8 +39,6 @@ import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
import org.sonar.api.config.Settings;
import org.sonar.xoo.Xoo;
-import java.io.IOException;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -61,7 +62,8 @@ public class OneIssuePerLineSensorTest {
@Test
public void testRule() throws IOException {
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder().toPath());
- DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10);
+ DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY)
+ .initMetadata(new FileMetadata().readMetadata(new StringReader("a\nb\nc\nd\ne\nf\ng\nh\ni\n")));
fs.add(inputFile);
SensorContext context = mock(SensorContext.class);
@@ -79,13 +81,14 @@ public class OneIssuePerLineSensorTest {
ArgumentCaptor<DefaultIssue> argCaptor = ArgumentCaptor.forClass(DefaultIssue.class);
verify(sensorStorage, times(10)).store(argCaptor.capture());
assertThat(argCaptor.getAllValues()).hasSize(10); // One issue per line
- assertThat(argCaptor.getValue().overridenSeverity()).isNull();
+ assertThat(argCaptor.getValue().overriddenSeverity()).isNull();
}
@Test
public void testForceSeverity() throws IOException {
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder().toPath());
- DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY).setLines(10);
+ DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.xoo").setLanguage(Xoo.KEY)
+ .initMetadata(new FileMetadata().readMetadata(new StringReader("a\nb\nc\nd\ne\nf\ng\nh\ni\n")));
fs.add(inputFile);
SensorContext context = mock(SensorContext.class);
@@ -105,7 +108,7 @@ public class OneIssuePerLineSensorTest {
ArgumentCaptor<DefaultIssue> argCaptor = ArgumentCaptor.forClass(DefaultIssue.class);
verify(sensorStorage, times(10)).store(argCaptor.capture());
assertThat(argCaptor.getAllValues()).hasSize(10); // One issue per line
- assertThat(argCaptor.getValue().overridenSeverity()).isEqualTo(Severity.MINOR);
+ assertThat(argCaptor.getValue().overriddenSeverity()).isEqualTo(Severity.MINOR);
}
}