diff --git a/build.gradle b/build.gradle index 824f0fe..073e92e 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,7 @@ dependencies { compile("org.sonarsource.java:sonar-java-plugin:4.3.0.7717") testCompile("org.assertj:assertj-core:2.8.0") + testCompile("org.skyscreamer:jsonassert:1.5.0") testCompile("junit:junit:4.12") } diff --git a/src/main/java/cc/Config.java b/src/main/java/cc/Config.java index 5b9a48d..1eb2635 100644 --- a/src/main/java/cc/Config.java +++ b/src/main/java/cc/Config.java @@ -5,10 +5,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.stream.JsonReader; -import java.io.File; -import java.io.FileNotFoundException; import java.io.FileReader; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/cc/JsonReport.java b/src/main/java/cc/JsonReport.java index 6600db3..833fcf6 100644 --- a/src/main/java/cc/JsonReport.java +++ b/src/main/java/cc/JsonReport.java @@ -1,14 +1,15 @@ package cc; -import com.google.gson.JsonObject; -import com.google.gson.JsonArray; -import java.io.PrintStream; +import cc.models.CodeClimateIssue; +import cc.serialization.GsonFactory; +import com.google.gson.Gson; + import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Arrays; import java.util.function.Function; -import org.sonarlint.cli.util.Logger; + import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; import org.sonarsource.sonarlint.core.client.api.common.analysis.AnalysisResults; import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; @@ -21,6 +22,13 @@ public class JsonReport implements org.sonarlint.cli.report.Reporter { "VULNERABILITY" ); + final Gson gson; + final String baseDir; + + public JsonReport(String baseDir) { + this.baseDir = baseDir; + this.gson = new GsonFactory().create(); + } @Override public void execute(String projectName, Date date, Collection trackables, AnalysisResults result, Function ruleDescriptionProducer) { @@ -28,56 +36,10 @@ public void execute(String projectName, Date date, Collection trackab Issue issue = trackable.getIssue(); RuleDetails ruleDetails = ruleDescriptionProducer.apply(issue.getRuleKey()); - if (VALID_RULE_DETAIL_TYPES.contains(ruleDetails.getType())) { - JsonObject json = new JsonObject(); - json.addProperty("type", "issue"); - json.addProperty("check_name", issue.getRuleKey()); - json.addProperty("severity", ruleDetails.getSeverity().toLowerCase()); - json.addProperty("description", issue.getMessage()); - - JsonObject content = new JsonObject(); - json.add("content", content); - content.addProperty("body", ruleDetails.getHtmlDescription()); - // // ruleDetails.getExtendedDescription(); - - JsonObject location = new JsonObject(); - json.add("location", location); - - // Code Climate CLI expects relative path to file - location.addProperty("path", issue.getInputFile().getPath().replaceFirst("^/tmp/code/", "")); - - JsonObject lines = new JsonObject(); - location.add("lines", lines); - - if (issue.getStartLine() != null) { - lines.addProperty("begin", issue.getStartLine()); - - if (issue.getEndLine() != null) { - lines.addProperty("end", issue.getEndLine()); - } else { - lines.addProperty("end", 1); - } - } else { - lines.addProperty("begin", 1); - lines.addProperty("end", 1); - } - - String category; - switch (ruleDetails.getType()) { - case "VULNERABILITY": { - category = "Security"; - break; - } - default: { - category = "Bug Risk"; - break; - } - } - JsonArray categories = new JsonArray(); - categories.add(category); - json.add("categories", categories); - - System.out.println(json.toString() + "\0"); + String type = ruleDetails.getType(); + if (VALID_RULE_DETAIL_TYPES.contains(type)) { + CodeClimateIssue codeClimateIssue = CodeClimateIssue.from(issue, ruleDetails, baseDir); + System.out.println(gson.toJson(codeClimateIssue) + "\0"); } } } diff --git a/src/main/java/cc/models/Categories.java b/src/main/java/cc/models/Categories.java new file mode 100644 index 0000000..568e39d --- /dev/null +++ b/src/main/java/cc/models/Categories.java @@ -0,0 +1,26 @@ +package cc.models; + +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; + +import java.util.ArrayList; + +class Categories extends ArrayList { + public Categories(String ruleType) { + String category; + switch (ruleType) { + case "VULNERABILITY": { + category = "Security"; + break; + } + default: { + category = "Bug Risk"; + break; + } + } + add(category); + } + + public static Categories from(RuleDetails ruleDetails) { + return new Categories(ruleDetails.getType()); + } +} diff --git a/src/main/java/cc/models/CodeClimateIssue.java b/src/main/java/cc/models/CodeClimateIssue.java new file mode 100644 index 0000000..c193296 --- /dev/null +++ b/src/main/java/cc/models/CodeClimateIssue.java @@ -0,0 +1,34 @@ +package cc.models; + +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; + +public class CodeClimateIssue { + public final String type = "issue"; + public final String checkName; + public final String severity; + public final String description; + public final Content content; + public final Location location; + public final Categories categories; + + public CodeClimateIssue(String checkName, String severity, String description, Content content, Location location, Categories categories) { + this.checkName = checkName; + this.severity = severity; + this.description = description; + this.content = content; + this.location = location; + this.categories = categories; + } + + public static CodeClimateIssue from(Issue issue, RuleDetails ruleDetails, String baseDir) { + String checkName = issue.getRuleKey(); + String description = issue.getMessage(); + String severity = Severity.from(ruleDetails); + Content content = Content.from(ruleDetails); + Location location = Location.from(baseDir, issue); + Categories categories = Categories.from(ruleDetails); + return new CodeClimateIssue(checkName, severity, description, content, location, categories); + } + +} diff --git a/src/main/java/cc/models/Content.java b/src/main/java/cc/models/Content.java new file mode 100644 index 0000000..1840150 --- /dev/null +++ b/src/main/java/cc/models/Content.java @@ -0,0 +1,15 @@ +package cc.models; + +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; + +class Content { + String body; + + public Content(String body) { + this.body = body; + } + + public static Content from(RuleDetails ruleDetails) { + return new Content(ruleDetails.getHtmlDescription()); + } +} diff --git a/src/main/java/cc/models/Lines.java b/src/main/java/cc/models/Lines.java new file mode 100644 index 0000000..f885eb3 --- /dev/null +++ b/src/main/java/cc/models/Lines.java @@ -0,0 +1,20 @@ +package cc.models; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; + +class Lines { + final Integer begin; + final Integer end; + + public Lines(Integer begin, Integer end) { + this.begin = begin; + this.end = end; + } + + public static Lines from(Issue issue) { + if(issue.getStartLine() == null || issue.getEndLine() == null) { + return null; + } + return new Lines(issue.getStartLine(), issue.getEndLine()); + } +} diff --git a/src/main/java/cc/models/Location.java b/src/main/java/cc/models/Location.java new file mode 100644 index 0000000..f39de09 --- /dev/null +++ b/src/main/java/cc/models/Location.java @@ -0,0 +1,25 @@ +package cc.models; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile; +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; + +class Location { + final String path; + final Lines lines; + + public Location(String baseDir, String path, Lines lines) { + String regex = ("^" + baseDir + "/").replace("//", "/"); + this.path = path.replaceFirst(regex, ""); + this.lines = lines; + } + + public static Location from(String baseDir, Issue issue) { + ClientInputFile inputFile = issue.getInputFile(); + + if (inputFile == null || inputFile.getPath() == null) { + return null; + } + + return new Location(baseDir, inputFile.getPath(), Lines.from(issue)); + } +} diff --git a/src/main/java/cc/models/Severity.java b/src/main/java/cc/models/Severity.java new file mode 100644 index 0000000..5fdd33f --- /dev/null +++ b/src/main/java/cc/models/Severity.java @@ -0,0 +1,15 @@ +package cc.models; + +import com.google.gson.annotations.SerializedName; +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; + +public class Severity { + + public static String from(RuleDetails ruleDetails) { + String severity = ruleDetails.getSeverity(); + if(severity == null) { + return null; + } + return severity.toLowerCase(); + } +} diff --git a/src/main/java/cc/serialization/GsonFactory.java b/src/main/java/cc/serialization/GsonFactory.java new file mode 100644 index 0000000..ad30d57 --- /dev/null +++ b/src/main/java/cc/serialization/GsonFactory.java @@ -0,0 +1,13 @@ +package cc.serialization; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonFactory { + public Gson create() { + return new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + } +} diff --git a/src/main/java/org/sonarlint/cli/CustomMain.java b/src/main/java/org/sonarlint/cli/CustomMain.java index fa4b029..b6d2ff0 100644 --- a/src/main/java/org/sonarlint/cli/CustomMain.java +++ b/src/main/java/org/sonarlint/cli/CustomMain.java @@ -98,7 +98,7 @@ public CustomReportFactory(Charset charset) { @Override public List createReporters(Path basePath) { - return Arrays.asList(new JsonReport()); + return Arrays.asList(new JsonReport(basePath.toString())); } } } \ No newline at end of file diff --git a/src/test/java/cc/JsonReportTest.java b/src/test/java/cc/JsonReportTest.java new file mode 100644 index 0000000..3b637b8 --- /dev/null +++ b/src/test/java/cc/JsonReportTest.java @@ -0,0 +1,62 @@ +package cc; + +import org.junit.Before; +import org.junit.Test; +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; +import org.sonarsource.sonarlint.core.tracking.Trackable; +import support.fakes.FakeRuleDetails; +import support.OutputHelper; +import support.fakes.FakeIssue; +import support.fakes.FakeTrackable; + +import java.util.Date; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +public class JsonReportTest { + + OutputHelper output; + + @Before + public void setUp() throws Exception { + output = OutputHelper.setup(); + } + + @Test + public void serialize_issue() throws Exception { + executeReport("major", new FakeIssue("file.java", 0, 1)); + assertThat(output.stdout.toString()).contains("\"type\":\"issue\""); + } + + @Test + public void serialize_issue_relative_path() throws Exception { + executeReport("major", new FakeIssue("/tmp/dir/file.java", 0, 1)); + assertThat(output.stdout.toString()).contains("\"path\":\"dir/file.java\""); + } + + @Test + public void does_not_include_unknown_severity() throws Exception { + executeReport(null, new FakeIssue("file.java", 0, 1)); + assertThat(output.stdout.toString()).doesNotContain("severity"); + } + + @Test + public void does_not_include_unknown_path() throws Exception { + executeReport("major", new FakeIssue(null, 1, 0)); + assertThat(output.stdout.toString()).doesNotContain("path"); + } + + @Test + public void does_not_include_unknown_location() throws Exception { + executeReport("major", new FakeIssue("file.java", null, null)); + assertThat(output.stdout.toString()).doesNotContain("lines"); + } + + void executeReport(String severity, FakeIssue issue) { + RuleDetails ruleDetails = new FakeRuleDetails(severity); + List trackables = asList(new FakeTrackable(issue)); + new JsonReport("/tmp").execute("prj", new Date(0), trackables, null, _ruleKey -> ruleDetails); + } +} \ No newline at end of file diff --git a/src/test/java/cc/models/CodeClimateIssueTest.java b/src/test/java/cc/models/CodeClimateIssueTest.java new file mode 100644 index 0000000..d26a271 --- /dev/null +++ b/src/test/java/cc/models/CodeClimateIssueTest.java @@ -0,0 +1,36 @@ +package cc.models; + +import cc.serialization.GsonFactory; +import com.google.gson.Gson; +import org.junit.Test; +import support.fakes.FakeRuleDetails; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CodeClimateIssueTest { + + @Test + public void down_case_severities() throws Exception { + assertThat(createIssueForSeverity("MAJOR").severity).isEqualTo("major"); + assertThat(createIssueForSeverity("MINOR").severity).isEqualTo("minor"); + assertThat(createIssueForSeverity("CRITICAL").severity).isEqualTo("critical"); + assertThat(createIssueForSeverity(null).severity).isNull(); + } + + @Test + public void properly_serialize_severity() throws Exception { + Gson gson = new GsonFactory().create(); + assertThat(gson.toJson(createIssueForSeverity("INFO"))).contains("\"severity\":\"info\""); + } + + private CodeClimateIssue createIssueForSeverity(String severity) { + return new CodeClimateIssue( + "check", + Severity.from(new FakeRuleDetails(severity)), + "desc", + new Content(""), + new Location("/tmp", "path", new Lines(0, 1)), + new Categories("VULNERABILITY") + ); + } +} \ No newline at end of file diff --git a/src/test/java/integration/ConfigurationOptionsTest.java b/src/test/java/integration/ConfigurationOptionsTest.java index f898e92..0769dc8 100644 --- a/src/test/java/integration/ConfigurationOptionsTest.java +++ b/src/test/java/integration/ConfigurationOptionsTest.java @@ -5,7 +5,7 @@ import org.junit.BeforeClass; import org.junit.Test; import org.sonarlint.cli.SonarProperties; -import support.TestSystem; +import support.SystemHelper; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -16,7 +16,7 @@ public class ConfigurationOptionsTest { ByteArrayOutputStream stdout; ByteArrayOutputStream stderr; - TestSystem system; + SystemHelper system; @BeforeClass public static void beforeAll() { @@ -25,7 +25,7 @@ public static void beforeAll() { @Before public void setUp() throws Exception { - system = new TestSystem(); + system = new SystemHelper(); stdout = new ByteArrayOutputStream(); stderr = new ByteArrayOutputStream(); @@ -42,8 +42,8 @@ public void limit_path_included_within_analysis() throws Exception { App.execute(new String[]{}, system); String output = stdout.toString(); - assertThat(output).contains("issue", "fixtures/multiple_paths/src/included/java/pkg1/HasIssue.java"); - assertThat(output).doesNotContain("fixtures/multiple_paths/src/excluded/java/pkg1/HasIssue.java"); + assertThat(output).contains("\"type\":\"issue\"", "src/included/java/pkg1/HasIssue.java"); + assertThat(output).doesNotContain("src/excluded/java/pkg1/HasIssue.java"); } @Test @@ -52,9 +52,9 @@ public void include_all_files_by_default() throws Exception { String output = stdout.toString(); assertThat(output).contains( - "issue", - "fixtures/multiple_paths/src/included/java/pkg1/HasIssue.java", - "fixtures/multiple_paths/src/excluded/java/pkg1/HasIssue.java" + "\"type\":\"issue\"", + "src/included/java/pkg1/HasIssue.java", + "src/excluded/java/pkg1/HasIssue.java" ); } } diff --git a/src/test/java/integration/SanityCheckTest.java b/src/test/java/integration/SanityCheckTest.java index 62d979a..171c5c8 100644 --- a/src/test/java/integration/SanityCheckTest.java +++ b/src/test/java/integration/SanityCheckTest.java @@ -1,54 +1,59 @@ package integration; +import org.assertj.core.util.Strings; import org.junit.Test; +import org.skyscreamer.jsonassert.JSONAssert; import support.Shell; -import java.util.Arrays; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; public class SanityCheckTest { @Test public void executeJavaLibFixture() throws Exception { - List expectedOutput = Arrays.asList("{\"type\":\"issue\"," + + String expectedOutput = + "[" + + "{\"type\":\"issue\"," + "\"check_name\":\"squid:S1994\"," + "\"severity\":\"major\"," + "\"description\":\"This loop's stop condition tests \\\"k\\\" but the incrementer updates \\\"i\\\".\"," + "\"content\":{\"body\":\"

It is almost always an error when a for loop's stop condition and incrementer don't act on the same variable. Even when it is not," + " it\\ncould confuse future maintainers of the code," + " and should be avoided.

\\n

Noncompliant Code Example

\\n
\\nfor (i = 0; i < 10; j++) {  // Noncompliant\\n  // ...\\n}\\n
\\n

Compliant Solution

\\n
\\nfor (i = 0; i < 10; i++) {\\n  // ...\\n}\\n
\"}," + - "\"location\":{\"path\":\"fixtures/java_lib/main/java/Library.java\"," + + "\"location\":{\"path\":\"main/java/Library.java\"," + "\"lines\":{\"begin\":17," + "\"end\":17}}," + - "\"categories\":[\"Bug Risk\"]}\u0000", - "{\"type\":\"issue\"," + + "\"categories\":[\"Bug Risk\"]}" + + ",{\"type\":\"issue\"," + "\"check_name\":\"squid:S1994\"," + "\"severity\":\"major\"," + "\"description\":\"This loop's stop condition tests \\\"k\\\" but the incrementer updates \\\"i\\\".\"," + "\"content\":{\"body\":\"

It is almost always an error when a for loop's stop condition and incrementer don't act on the same variable. Even when it is not," + " it\\ncould confuse future maintainers of the code," + " and should be avoided.

\\n

Noncompliant Code Example

\\n
\\nfor (i = 0; i < 10; j++) {  // Noncompliant\\n  // ...\\n}\\n
\\n

Compliant Solution

\\n
\\nfor (i = 0; i < 10; i++) {\\n  // ...\\n}\\n
\"}," + - "\"location\":{\"path\":\"fixtures/java_lib/main/java/Library.java\"," + + "\"location\":{\"path\":\"main/java/Library.java\"," + "\"lines\":{\"begin\":20," + "\"end\":20}}," + - "\"categories\":[\"Bug Risk\"]}\u0000", - "{\"type\":\"issue\"," + + "\"categories\":[\"Bug Risk\"]}" + + ",{\"type\":\"issue\"," + "\"check_name\":\"squid:S1994\"," + "\"severity\":\"major\"," + "\"description\":\"This loop's stop condition tests \\\"k\\\" but the incrementer updates \\\"i\\\".\"," + "\"content\":{\"body\":\"

It is almost always an error when a for loop's stop condition and incrementer don't act on the same variable. Even when it is not," + " it\\ncould confuse future maintainers of the code," + " and should be avoided.

\\n

Noncompliant Code Example

\\n
\\nfor (i = 0; i < 10; j++) {  // Noncompliant\\n  // ...\\n}\\n
\\n

Compliant Solution

\\n
\\nfor (i = 0; i < 10; i++) {\\n  // ...\\n}\\n
\"}," + - "\"location\":{\"path\":\"fixtures/java_lib/main/java/Library.java\"," + + "\"location\":{\"path\":\"main/java/Library.java\"," + "\"lines\":{\"begin\":23," + "\"end\":23}}," + - "\"categories\":[\"Bug Risk\"]}\u0000"); + "\"categories\":[\"Bug Risk\"]}" + + "]"; Shell.Process process = Shell.execute("build/codeclimate-sonar fixtures/java_lib"); assertThat(process.exitCode).isEqualTo(0); - assertThat(process.stdout).contains(expectedOutput); + assertThat(process.stdout).contains("\u0000"); + + String stdoutAsJson = "[" + Strings.join(process.stdout.split("\u0000")).with(",") + "]"; + JSONAssert.assertEquals(stdoutAsJson, expectedOutput, false); } } diff --git a/src/test/java/support/OutputHelper.java b/src/test/java/support/OutputHelper.java new file mode 100644 index 0000000..ea5e7e3 --- /dev/null +++ b/src/test/java/support/OutputHelper.java @@ -0,0 +1,23 @@ +package support; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +public class OutputHelper { + public final OutputStream stdout; + public final OutputStream stderr; + + public OutputHelper(OutputStream out, OutputStream err) { + this.stdout = out; + this.stderr = err; + } + + public static OutputHelper setup() { + OutputStream out = new ByteArrayOutputStream(); + OutputStream err = new ByteArrayOutputStream(); + System.setOut(new PrintStream(out)); + System.setErr(new PrintStream(err)); + return new OutputHelper(out, err); + } +} diff --git a/src/test/java/support/TestSystem.java b/src/test/java/support/SystemHelper.java similarity index 93% rename from src/test/java/support/TestSystem.java rename to src/test/java/support/SystemHelper.java index 687030e..9b15da6 100644 --- a/src/test/java/support/TestSystem.java +++ b/src/test/java/support/SystemHelper.java @@ -4,7 +4,7 @@ import java.util.Properties; -public class TestSystem extends System2 { +public class SystemHelper extends System2 { public int exitCode; final Properties properties = new Properties(); diff --git a/src/test/java/support/fakes/FakeClientInputFile.java b/src/test/java/support/fakes/FakeClientInputFile.java new file mode 100644 index 0000000..eb068e8 --- /dev/null +++ b/src/test/java/support/fakes/FakeClientInputFile.java @@ -0,0 +1,48 @@ +package support.fakes; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile; + +import javax.annotation.CheckForNull; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +public class FakeClientInputFile implements ClientInputFile { + String path; + + public FakeClientInputFile(String path) { + this.path = path; + } + + @Override + public String getPath() { + return path; + } + + @CheckForNull + @Override + public boolean isTest() { + return false; + } + + @CheckForNull + @Override + public Charset getCharset() { + return null; + } + + @Override + public G getClientObject() { + return null; + } + + @Override + public InputStream inputStream() throws IOException { + return null; + } + + @Override + public String contents() throws IOException { + return null; + } +} diff --git a/src/test/java/support/fakes/FakeIssue.java b/src/test/java/support/fakes/FakeIssue.java new file mode 100644 index 0000000..1c25af1 --- /dev/null +++ b/src/test/java/support/fakes/FakeIssue.java @@ -0,0 +1,82 @@ +package support.fakes; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.ClientInputFile; +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; + +import javax.annotation.CheckForNull; +import java.util.List; + +public class FakeIssue implements Issue { + + String path = "/tmp/File.java"; + Integer startLine; + Integer endLine; + + public FakeIssue(String path, Integer startLine, Integer endLine) { + this.path = path; + this.startLine = startLine; + this.endLine = endLine; + } + + @Override + public String getSeverity() { + return null; + } + + @CheckForNull + @Override + public String getType() { + return null; + } + + @CheckForNull + @Override + public String getMessage() { + return null; + } + + @Override + public String getRuleKey() { + return null; + } + + @Override + public String getRuleName() { + return null; + } + + @CheckForNull + @Override + public Integer getStartLine() { + return startLine; + } + + @CheckForNull + @Override + public Integer getStartLineOffset() { + return null; + } + + @CheckForNull + @Override + public Integer getEndLine() { + return endLine; + } + + @CheckForNull + @Override + public Integer getEndLineOffset() { + return null; + } + + @Override + public List flows() { + return null; + } + + @CheckForNull + @Override + public ClientInputFile getInputFile() { + return new FakeClientInputFile(path); + } +} diff --git a/src/test/java/support/fakes/FakeRuleDetails.java b/src/test/java/support/fakes/FakeRuleDetails.java new file mode 100644 index 0000000..284eecc --- /dev/null +++ b/src/test/java/support/fakes/FakeRuleDetails.java @@ -0,0 +1,54 @@ +package support.fakes; + +import org.sonarsource.sonarlint.core.client.api.common.RuleDetails; + +import javax.annotation.CheckForNull; + +public class FakeRuleDetails implements RuleDetails { + private String severity; + + public FakeRuleDetails(String severity) { + this.severity = severity; + } + + @Override + public String getKey() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getHtmlDescription() { + return null; + } + + @Override + public String getLanguage() { + return null; + } + + @Override + public String getSeverity() { + return severity; + } + + @CheckForNull + @Override + public String getType() { + return "BUG"; + } + + @Override + public String[] getTags() { + return new String[0]; + } + + @Override + public String getExtendedDescription() { + return null; + } +} diff --git a/src/test/java/support/fakes/FakeTrackable.java b/src/test/java/support/fakes/FakeTrackable.java new file mode 100644 index 0000000..fa01a06 --- /dev/null +++ b/src/test/java/support/fakes/FakeTrackable.java @@ -0,0 +1,87 @@ +package support.fakes; + +import org.sonarsource.sonarlint.core.client.api.common.analysis.Issue; +import org.sonarsource.sonarlint.core.tracking.TextRange; +import org.sonarsource.sonarlint.core.tracking.Trackable; + +import javax.annotation.CheckForNull; + +public class FakeTrackable implements Trackable{ + + private FakeIssue fakeIssue; + + public FakeTrackable(FakeIssue fakeIssue) { + this.fakeIssue = fakeIssue; + } + + @Override + public Issue getIssue() { + return fakeIssue; + } + + @Override + public String getRuleKey() { + return null; + } + + @Override + public String getRuleName() { + return null; + } + + @Override + public String getSeverity() { + return null; + } + + @Override + public String getMessage() { + return null; + } + + @CheckForNull + @Override + public Integer getLine() { + return null; + } + + @CheckForNull + @Override + public Integer getLineHash() { + return null; + } + + @CheckForNull + @Override + public TextRange getTextRange() { + return null; + } + + @CheckForNull + @Override + public Integer getTextRangeHash() { + return null; + } + + @CheckForNull + @Override + public Long getCreationDate() { + return null; + } + + @CheckForNull + @Override + public String getServerIssueKey() { + return null; + } + + @Override + public boolean isResolved() { + return false; + } + + @Override + public String getAssignee() { + return null; + } +}