aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-07-22 12:23:11 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-07-22 12:35:56 +0200
commite24f017a3d20d9320a4dee91596d33d4e27b32bf (patch)
treefcfa188545e886a9edf5462aaa36eb469bd6a78d /sonar-plugin-api
parenta1defc3dd106409930d9323d7bc055f816c2bcd3 (diff)
downloadsonarqube-e24f017a3d20d9320a4dee91596d33d4e27b32bf.tar.gz
sonarqube-e24f017a3d20d9320a4dee91596d33d4e27b32bf.zip
SONAR-5389 Allow to create issues on directories and to override severity on issues
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputPath.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java30
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java26
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java15
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java32
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java43
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/component/ResourcePerspectives.java3
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java22
9 files changed, 131 insertions, 44 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputPath.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputPath.java
index 6a3ac3a0bf2..c4d2ae73f16 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputPath.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputPath.java
@@ -26,6 +26,8 @@ import java.io.Serializable;
* Layer over {@link java.io.File} for files or directories.
*
* @since 4.5
+ * @see InputFile
+ * @see InputDir
*/
public interface InputPath extends Serializable {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
index 7b79d948d10..55c5303cbae 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java
@@ -19,14 +19,14 @@
*/
package org.sonar.api.batch.fs.internal;
-import org.sonar.api.utils.PathUtils;
-
import com.google.common.base.Preconditions;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.utils.PathUtils;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
@@ -161,7 +161,11 @@ public class DefaultFileSystem implements FileSystem {
@Override
public InputDir inputDir(File dir) {
doPreloadFiles();
- return cache.inputDir(PathUtils.sanitize(new RelativeP));
+ String relativePath = PathUtils.sanitize(new PathResolver().relativePath(baseDir, dir));
+ if (relativePath == null) {
+ return null;
+ }
+ return cache.inputDir(relativePath);
}
public static Collection<InputFile> filter(Iterable<InputFile> target, FilePredicate predicate) {
@@ -186,6 +190,14 @@ public class DefaultFileSystem implements FileSystem {
}
/**
+ * Adds InputDir to the list.
+ */
+ public DefaultFileSystem add(InputDir inputDir) {
+ cache.add(inputDir);
+ return this;
+ }
+
+ /**
* Adds a language to the list. To be used only for unit tests that need to use {@link #languages()} without
* using {@link #add(org.sonar.api.batch.fs.InputFile)}.
*/
@@ -224,9 +236,16 @@ public class DefaultFileSystem implements FileSystem {
protected abstract void doAdd(InputFile inputFile);
+ protected abstract void doAdd(InputDir inputDir);
+
final void add(InputFile inputFile) {
doAdd(inputFile);
}
+
+ public void add(InputDir inputDir) {
+ doAdd(inputDir);
+ }
+
}
/**
@@ -255,6 +274,11 @@ public class DefaultFileSystem implements FileSystem {
protected void doAdd(InputFile inputFile) {
fileMap.put(inputFile.relativePath(), inputFile);
}
+
+ @Override
+ protected void doAdd(InputDir inputDir) {
+ dirMap.put(inputDir.relativePath(), inputDir);
+ }
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java
index 3e96bd664bb..22521ce0115 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java
@@ -27,9 +27,7 @@ import java.util.Collection;
/**
* @since 4.2
- * @deprecated since 4.5 use {@link ActiveRules}
*/
-@Deprecated
public interface Rules {
@CheckForNull
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java
index 713b86d6ba3..c56e623056c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/Issue.java
@@ -19,13 +19,12 @@
*/
package org.sonar.api.batch.sensor.issue;
-import org.sonar.api.batch.sensor.Sensor;
-
import com.google.common.annotations.Beta;
-import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.rule.RuleKey;
-import javax.annotation.Nullable;
+import javax.annotation.CheckForNull;
/**
* Issue reported by an {@link Sensor}
@@ -36,10 +35,10 @@ import javax.annotation.Nullable;
public interface Issue {
/**
- * The {@link InputFile} this issue belongs to. Returns null if issue is global to the project.
+ * The {@link InputPath} this issue belongs to. Returns null if issue is global to the project.
*/
- @Nullable
- InputFile inputFile();
+ @CheckForNull
+ InputPath inputPath();
/**
* The {@link RuleKey} of this issue.
@@ -52,14 +51,23 @@ public interface Issue {
String message();
/**
- * Line of the issue.
+ * Line of the issue. Null for global issues and issues on directories. Can also be null
+ * for files (issue global to the file).
*/
+ @CheckForNull
Integer line();
/**
* Effort to fix the issue. Used by technical debt model.
*/
- @Nullable
+ @CheckForNull
Double effortToFix();
+ /**
+ * See constants in {@link org.sonar.api.rule.Severity}.
+ * Can be null before issue is saved to tell to use severity configured in quality profile.
+ */
+ @CheckForNull
+ String severity();
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java
index 6b962d6bdcf..5480103b1e7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/IssueBuilder.java
@@ -20,8 +20,10 @@
package org.sonar.api.batch.sensor.issue;
import com.google.common.annotations.Beta;
+import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
import javax.annotation.Nullable;
@@ -44,12 +46,17 @@ public interface IssueBuilder {
IssueBuilder onFile(InputFile file);
/**
+ * The {@link InputDir} the issue belongs to. For global issues call {@link #onProject()}.
+ */
+ IssueBuilder onDir(InputDir inputDir);
+
+ /**
* Tell that the issue is global to the project.
*/
IssueBuilder onProject();
/**
- * Line of the issue. If no line is specified then issue is supposed to be global to the file.
+ * Line of the issue. Only available for {@link #onFile(InputFile)} issues. If no line is specified then issue is supposed to be global to the file.
*/
IssueBuilder atLine(int line);
@@ -64,6 +71,12 @@ public interface IssueBuilder {
IssueBuilder message(String message);
/**
+ * Severity of the issue. See {@link Severity}.
+ * Setting a null value means to use severity configured in quality profile.
+ */
+ IssueBuilder severity(@Nullable String severity);
+
+ /**
* Build the issue.
*/
Issue build();
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 d20d5c7700e..9ca0fdd4f82 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
@@ -19,15 +19,15 @@
*/
package org.sonar.api.batch.sensor.issue.internal;
-import org.sonar.api.batch.sensor.issue.Issue;
-
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.rule.RuleKey;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import java.io.Serializable;
@@ -36,19 +36,21 @@ import java.util.UUID;
public class DefaultIssue implements Issue, Serializable {
private final String key;
- private final InputFile inputFile;
+ private final InputPath inputPath;
private final RuleKey ruleKey;
- private final String message;
+ private String message;
private final Integer line;
private final Double effortToFix;
+ private String severity;
DefaultIssue(DefaultIssueBuilder builder) {
Preconditions.checkNotNull(builder.ruleKey, "ruleKey is mandatory on issue");
- this.inputFile = builder.file;
+ this.inputPath = builder.path;
this.ruleKey = builder.ruleKey;
this.message = builder.message;
this.line = builder.line;
this.effortToFix = builder.effortToFix;
+ this.severity = builder.severity;
this.key = builder.key == null ? UUID.randomUUID().toString() : builder.key;
Preconditions.checkState(!Strings.isNullOrEmpty(key), "Fail to generate issue key");
}
@@ -59,8 +61,8 @@ public class DefaultIssue implements Issue, Serializable {
@Override
@Nullable
- public InputFile inputFile() {
- return inputFile;
+ public InputPath inputPath() {
+ return inputPath;
}
@Override
@@ -73,6 +75,10 @@ public class DefaultIssue implements Issue, Serializable {
return message;
}
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
@Override
public Integer line() {
return line;
@@ -85,6 +91,16 @@ public class DefaultIssue implements Issue, Serializable {
}
@Override
+ @CheckForNull
+ public String severity() {
+ return severity;
+ }
+
+ public void setSeverity(String severity) {
+ this.severity = severity;
+ }
+
+ @Override
public boolean equals(Object o) {
if (this == o) {
return true;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java
index 8d8249d3058..62e89813f1c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueBuilder.java
@@ -19,24 +19,27 @@
*/
package org.sonar.api.batch.sensor.issue.internal;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.IssueBuilder;
-
import com.google.common.base.Preconditions;
+import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.IssueBuilder;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
import javax.annotation.Nullable;
public class DefaultIssueBuilder implements IssueBuilder {
String key;
- Boolean onProject = null;
- InputFile file;
+ boolean onProject = false;
+ InputPath path;
RuleKey ruleKey;
String message;
Integer line;
Double effortToFix;
+ String severity;
@Override
public DefaultIssueBuilder ruleKey(RuleKey ruleKey) {
@@ -46,26 +49,33 @@ public class DefaultIssueBuilder implements IssueBuilder {
@Override
public DefaultIssueBuilder onFile(InputFile file) {
- onProject(false);
+ Preconditions.checkState(!this.onProject, "onProject already called");
+ Preconditions.checkState(this.path == null, "onFile or onDir already called");
Preconditions.checkNotNull(file, "InputFile should be non null");
- this.file = file;
+ this.path = file;
return this;
}
@Override
- public DefaultIssueBuilder onProject() {
- onProject(true);
- this.file = null;
+ public DefaultIssueBuilder onDir(InputDir dir) {
+ Preconditions.checkState(!this.onProject, "onProject already called");
+ Preconditions.checkState(this.path == null, "onFile or onDir already called");
+ Preconditions.checkNotNull(dir, "InputDir should be non null");
+ this.path = dir;
return this;
}
- private void onProject(boolean isOnProject) {
- Preconditions.checkState(this.onProject == null, "onFile or onProject can be called only once");
- this.onProject = isOnProject;
+ @Override
+ public DefaultIssueBuilder onProject() {
+ Preconditions.checkState(!this.onProject, "onProject already called");
+ Preconditions.checkState(this.path == null, "onFile or onDir already called");
+ this.onProject = true;
+ return this;
}
@Override
public DefaultIssueBuilder atLine(int line) {
+ Preconditions.checkState(this.path != null && this.path instanceof InputFile, "atLine should be called after onFile");
this.line = line;
return this;
}
@@ -82,6 +92,13 @@ public class DefaultIssueBuilder implements IssueBuilder {
return this;
}
+ @Override
+ public IssueBuilder severity(@Nullable String severity) {
+ Preconditions.checkState(severity == null || Severity.ALL.contains(severity), "Invalid severity: " + severity);
+ this.severity = severity;
+ return this;
+ }
+
/**
* For testing only.
*/
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/component/ResourcePerspectives.java b/sonar-plugin-api/src/main/java/org/sonar/api/component/ResourcePerspectives.java
index 6877cf32f6d..d992b571001 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/component/ResourcePerspectives.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/component/ResourcePerspectives.java
@@ -21,6 +21,8 @@ package org.sonar.api.component;
import org.sonar.api.resources.Resource;
+import javax.annotation.CheckForNull;
+
/**
* Only on batch-side.
*
@@ -28,5 +30,6 @@ import org.sonar.api.resources.Resource;
*/
public interface ResourcePerspectives extends Perspectives {
+ @CheckForNull
<P extends Perspective> P as(Class<P> perspectiveClass, Resource resource);
}
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 25454a8f251..7e98d6e3591 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,14 +19,13 @@
*/
package org.sonar.api.batch.sensor.issue.internal;
-import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssueBuilder;
-
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.rule.RuleKey;
+
import static org.fest.assertions.Assertions.assertThat;
public class DefaultIssueTest {
@@ -44,7 +43,7 @@ public class DefaultIssueTest {
.message("Wrong way!")
.build();
- assertThat(issue.inputFile()).isEqualTo(new DefaultInputFile("src/Foo.php"));
+ assertThat(issue.inputPath()).isEqualTo(new DefaultInputFile("src/Foo.php"));
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
assertThat(issue.line()).isEqualTo(1);
assertThat(issue.effortToFix()).isEqualTo(10.0);
@@ -56,14 +55,13 @@ public class DefaultIssueTest {
Issue issue = new DefaultIssueBuilder()
.onProject()
.ruleKey(RuleKey.of("repo", "rule"))
- .atLine(1)
.effortToFix(10.0)
.message("Wrong way!")
.build();
- assertThat(issue.inputFile()).isNull();
+ assertThat(issue.inputPath()).isNull();
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("repo", "rule"));
- assertThat(issue.line()).isEqualTo(1);
+ assertThat(issue.line()).isNull();
assertThat(issue.effortToFix()).isEqualTo(10.0);
assertThat(issue.message()).isEqualTo("Wrong way!");
}
@@ -71,7 +69,7 @@ public class DefaultIssueTest {
@Test
public void not_allowed_to_call_onFile_and_onProject() {
thrown.expect(IllegalStateException.class);
- thrown.expectMessage("onFile or onProject can be called only once");
+ thrown.expectMessage("onProject already called");
new DefaultIssueBuilder()
.onProject()
.onFile(new DefaultInputFile("src/Foo.php"))
@@ -80,7 +78,15 @@ public class DefaultIssueTest {
.effortToFix(10.0)
.message("Wrong way!")
.build();
+ }
+ @Test
+ public void validate_severity() {
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("Invalid severity: FOO");
+ new DefaultIssueBuilder()
+ .severity("FOO")
+ .build();
}
}