aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorMichal Duda <michalno1@gmail.com>2018-11-13 11:00:42 +0100
committersonartech <sonartech@sonarsource.com>2019-01-16 09:43:00 +0100
commit6dd294b1f5af7c74191db30101e3721d00102204 (patch)
tree372dbc219371a610c32fb8b723869291a7148c5f /sonar-plugin-api
parentb44c75c2b93ca2d91d6ce559a08a0d994c73bd85 (diff)
downloadsonarqube-6dd294b1f5af7c74191db30101e3721d00102204.tar.gz
sonarqube-6dd294b1f5af7c74191db30101e3721d00102204.zip
SONAR-11459 move dir and module issues to root
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java6
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java63
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java10
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java31
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java57
6 files changed, 138 insertions, 38 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
index a316dc2fbe8..58286e136e7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
@@ -108,7 +108,7 @@ public class SensorContextTester implements SensorContext {
private DefaultFileSystem fs;
private ActiveRules activeRules;
private InMemorySensorStorage sensorStorage;
- private InputModule module;
+ private DefaultInputModule module;
private SonarRuntime runtime;
private boolean cancelled;
@@ -220,7 +220,7 @@ public class SensorContextTester implements SensorContext {
@Override
public NewIssue newIssue() {
- return new DefaultIssue(sensorStorage);
+ return new DefaultIssue(module, sensorStorage);
}
public Collection<Issue> allIssues() {
@@ -229,7 +229,7 @@ public class SensorContextTester implements SensorContext {
@Override
public NewExternalIssue newExternalIssue() {
- return new DefaultExternalIssue(sensorStorage);
+ return new DefaultExternalIssue(module, sensorStorage);
}
@Override
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
index 79a62e03cc4..c993ee62d07 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/AbstractDefaultIssue.java
@@ -20,32 +20,42 @@
package org.sonar.api.batch.sensor.issue.internal;
import com.google.common.base.Preconditions;
+import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue.Flow;
import org.sonar.api.batch.sensor.issue.IssueLocation;
import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.api.utils.PathUtils;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;
-public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
+public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
protected IssueLocation primaryLocation;
protected List<List<IssueLocation>> flows = new ArrayList<>();
-
- protected AbstractDefaultIssue() {
- super(null);
+ protected DefaultInputModule projectRoot;
+
+ protected AbstractDefaultIssue(DefaultInputModule projectRoot) {
+ this(projectRoot, null);
}
-
- public AbstractDefaultIssue(@Nullable SensorStorage storage) {
+
+ public AbstractDefaultIssue(DefaultInputModule projectRoot, @Nullable SensorStorage storage) {
super(storage);
+ this.projectRoot = projectRoot;
}
-
+
public IssueLocation primaryLocation() {
return primaryLocation;
}
@@ -55,7 +65,7 @@ public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> exte
.<Flow>map(l -> () -> unmodifiableList(new ArrayList<>(l)))
.collect(toList());
}
-
+
public NewIssueLocation newLocation() {
return new DefaultIssueLocation();
}
@@ -63,23 +73,50 @@ public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> exte
public T at(NewIssueLocation primaryLocation) {
Preconditions.checkArgument(primaryLocation != null, "Cannot use a location that is null");
checkState(this.primaryLocation == null, "at() already called");
- this.primaryLocation = (DefaultIssueLocation) primaryLocation;
+ this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
Preconditions.checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
return (T) this;
}
public T addLocation(NewIssueLocation secondaryLocation) {
- flows.add(Arrays.asList((IssueLocation) secondaryLocation));
+ flows.add(Collections.singletonList(rewriteLocation((DefaultIssueLocation) secondaryLocation)));
return (T) this;
}
public T addFlow(Iterable<NewIssueLocation> locations) {
List<IssueLocation> flowAsList = new ArrayList<>();
for (NewIssueLocation issueLocation : locations) {
- flowAsList.add((DefaultIssueLocation) issueLocation);
+ flowAsList.add(rewriteLocation((DefaultIssueLocation) issueLocation));
}
flows.add(flowAsList);
return (T) this;
}
-
+
+ private DefaultIssueLocation rewriteLocation(DefaultIssueLocation location) {
+ InputComponent component = location.inputComponent();
+ Optional<Path> dirOrModulePath = Optional.empty();
+
+ if (component instanceof DefaultInputDir) {
+ DefaultInputDir dirComponent = (DefaultInputDir) component;
+ dirOrModulePath = Optional.of(projectRoot.getBaseDir().relativize(dirComponent.path()));
+ } else if (component instanceof DefaultInputModule && !Objects.equals(projectRoot.key(), component.key())) {
+ DefaultInputModule moduleComponent = (DefaultInputModule) component;
+ dirOrModulePath = Optional.of(projectRoot.getBaseDir().relativize(moduleComponent.getBaseDir()));
+ }
+
+ if (dirOrModulePath.isPresent()) {
+ String path = PathUtils.sanitize(dirOrModulePath.get().toString());
+ DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
+ fixedLocation.on(projectRoot);
+ StringBuilder fullMessage = new StringBuilder();
+ if (!isNullOrEmpty(path)) {
+ fullMessage.append("[").append(path).append("] ");
+ }
+ fullMessage.append(location.message());
+ fixedLocation.message(fullMessage.toString());
+ return fixedLocation;
+ } else {
+ return location;
+ }
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
index facceda9c6c..a9b9cc1051d 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssue.java
@@ -21,6 +21,7 @@ package org.sonar.api.batch.sensor.issue.internal;
import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
@@ -39,12 +40,12 @@ public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIs
private String engineId;
private String ruleId;
- public DefaultExternalIssue() {
- super(null);
+ public DefaultExternalIssue(DefaultInputModule projectRoot) {
+ this(projectRoot, null);
}
- public DefaultExternalIssue(@Nullable SensorStorage storage) {
- super(storage);
+ public DefaultExternalIssue(DefaultInputModule projectRoot, @Nullable SensorStorage storage) {
+ super(projectRoot, storage);
}
@Override
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
index d936ba09371..1b7de9d9ab0 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java
@@ -21,6 +21,7 @@ package org.sonar.api.batch.sensor.issue.internal;
import com.google.common.base.Preconditions;
import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue;
@@ -37,12 +38,12 @@ public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements
private Double gap;
private Severity overriddenSeverity;
- public DefaultIssue() {
- super(null);
+ public DefaultIssue(DefaultInputModule projectRoot) {
+ this(projectRoot, null);
}
- public DefaultIssue(@Nullable SensorStorage storage) {
- super(storage);
+ public DefaultIssue(DefaultInputModule projectRoot, @Nullable SensorStorage storage) {
+ super(projectRoot, storage);
}
public DefaultIssue forRule(RuleKey ruleKey) {
@@ -54,7 +55,6 @@ public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements
return this.ruleKey;
}
-
@Override
public DefaultIssue gap(@Nullable Double gap) {
Preconditions.checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java
index 33da8b1a2c1..6ef27d97f3c 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultExternalIssueTest.java
@@ -19,11 +19,16 @@
*/
package org.sonar.api.batch.sensor.issue.internal;
+import java.io.IOException;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.rule.Severity;
import org.sonar.api.batch.sensor.internal.SensorStorage;
@@ -35,6 +40,20 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
public class DefaultExternalIssueTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private DefaultInputModule projectRoot;
+
+ @Before
+ public void setup() throws IOException {
+ projectRoot = new DefaultInputModule(ProjectDefinition.create()
+ .setKey("foo")
+ .setBaseDir(temp.newFolder())
+ .setWorkDir(temp.newFolder()));
+ }
+
@Rule
public ExpectedException exception = ExpectedException.none();
@@ -45,7 +64,7 @@ public class DefaultExternalIssueTest {
@Test
public void build_file_issue() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultExternalIssue issue = new DefaultExternalIssue(storage)
+ DefaultExternalIssue issue = new DefaultExternalIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputFile)
.at(inputFile.selectLine(1))
@@ -73,7 +92,7 @@ public class DefaultExternalIssueTest {
@Test
public void fail_to_store_if_no_type() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultExternalIssue issue = new DefaultExternalIssue(storage)
+ DefaultExternalIssue issue = new DefaultExternalIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputFile)
.at(inputFile.selectLine(1))
@@ -90,7 +109,7 @@ public class DefaultExternalIssueTest {
@Test
public void fail_to_store_if_primary_location_is_not_a_file() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultExternalIssue issue = new DefaultExternalIssue(storage)
+ DefaultExternalIssue issue = new DefaultExternalIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(mock(InputComponent.class))
.message("Wrong way!"))
@@ -102,11 +121,11 @@ public class DefaultExternalIssueTest {
exception.expectMessage("External issues must be located in files");
issue.save();
}
-
+
@Test
public void fail_to_store_if_primary_location_has_no_message() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultExternalIssue issue = new DefaultExternalIssue(storage)
+ DefaultExternalIssue issue = new DefaultExternalIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputFile)
.at(inputFile.selectLine(1)))
@@ -123,7 +142,7 @@ public class DefaultExternalIssueTest {
@Test
public void fail_to_store_if_no_severity() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultExternalIssue issue = new DefaultExternalIssue(storage)
+ DefaultExternalIssue issue = new DefaultExternalIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputFile)
.at(inputFile.selectLine(1))
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java
index 37664b90cc3..5d36dcd2a9c 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java
@@ -19,7 +19,9 @@
*/
package org.sonar.api.batch.sensor.issue.internal;
+import java.io.File;
import java.io.IOException;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -41,14 +43,24 @@ public class DefaultIssueTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ private DefaultInputModule projectRoot;
+
private DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.php")
.initMetadata("Foo\nBar\n")
.build();
+ @Before
+ public void prepare() throws IOException {
+ projectRoot = new DefaultInputModule(ProjectDefinition.create()
+ .setKey("foo")
+ .setBaseDir(temp.newFolder())
+ .setWorkDir(temp.newFolder()));
+ }
+
@Test
public void build_file_issue() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultIssue issue = new DefaultIssue(storage)
+ DefaultIssue issue = new DefaultIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputFile)
.at(inputFile.selectLine(1))
@@ -68,19 +80,50 @@ public class DefaultIssueTest {
}
@Test
- public void build_directory_issue() {
+ public void move_directory_issue_to_project_root() {
SensorStorage storage = mock(SensorStorage.class);
- DefaultIssue issue = new DefaultIssue(storage)
+ DefaultIssue issue = new DefaultIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
- .on(new DefaultInputDir("foo", "src"))
+ .on(new DefaultInputDir("foo", "src/main").setModuleBaseDir(projectRoot.getBaseDir()))
.message("Wrong way!"))
.forRule(RuleKey.of("repo", "rule"))
.overrideSeverity(Severity.BLOCKER);
- assertThat(issue.primaryLocation().inputComponent()).isEqualTo(new DefaultInputDir("foo", "src"));
+ assertThat(issue.primaryLocation().inputComponent()).isEqualTo(projectRoot);
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
assertThat(issue.primaryLocation().textRange()).isNull();
- assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!");
+ assertThat(issue.primaryLocation().message()).isEqualTo("[src/main] Wrong way!");
+ assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
+
+ issue.save();
+
+ verify(storage).store(issue);
+ }
+
+ @Test
+ public void move_submodule_issue_to_project_root() {
+ File subModuleDirectory = new File(projectRoot.getBaseDir().toString(), "bar");
+ subModuleDirectory.mkdir();
+
+ ProjectDefinition subModuleDefinition = ProjectDefinition.create()
+ .setKey("foo/bar")
+ .setBaseDir(subModuleDirectory)
+ .setWorkDir(subModuleDirectory);
+ projectRoot.definition().addSubProject(subModuleDefinition);
+ DefaultInputModule subModule = new DefaultInputModule(subModuleDefinition);
+
+ SensorStorage storage = mock(SensorStorage.class);
+ DefaultIssue issue = new DefaultIssue(projectRoot, storage)
+ .at(new DefaultIssueLocation()
+ .on(subModule)
+ .message("Wrong way!"))
+ .forRule(RuleKey.of("repo", "rule"))
+ .overrideSeverity(Severity.BLOCKER);
+
+ assertThat(issue.primaryLocation().inputComponent()).isEqualTo(projectRoot);
+ assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
+ assertThat(issue.primaryLocation().textRange()).isNull();
+ assertThat(issue.primaryLocation().message()).isEqualTo("[bar] Wrong way!");
assertThat(issue.overriddenSeverity()).isEqualTo(Severity.BLOCKER);
issue.save();
@@ -92,7 +135,7 @@ public class DefaultIssueTest {
public void build_project_issue() throws IOException {
SensorStorage storage = mock(SensorStorage.class);
DefaultInputModule inputModule = new DefaultInputModule(ProjectDefinition.create().setKey("foo").setBaseDir(temp.newFolder()).setWorkDir(temp.newFolder()));
- DefaultIssue issue = new DefaultIssue(storage)
+ DefaultIssue issue = new DefaultIssue(projectRoot, storage)
.at(new DefaultIssueLocation()
.on(inputModule)
.message("Wrong way!"))