diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2014-07-22 12:23:11 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2014-07-22 12:35:56 +0200 |
commit | e24f017a3d20d9320a4dee91596d33d4e27b32bf (patch) | |
tree | fcfa188545e886a9edf5462aaa36eb469bd6a78d /sonar-plugin-api | |
parent | a1defc3dd106409930d9323d7bc055f816c2bcd3 (diff) | |
download | sonarqube-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')
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(); } } |