@@ -40,11 +40,12 @@ public class OneExternalIssuePerLineSensor implements Sensor { | |||
public static final Long EFFORT = 10l; | |||
public static final RuleType type = RuleType.BUG; | |||
public static final String ACTIVATE_EXTERNAL_ISSUES = "sonar.oneExternalIssuePerLine.activate"; | |||
private static final String NAME = "One External Issue Per Line"; | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("One External Issue Per Line") | |||
.name(NAME) | |||
.onlyOnLanguages(Xoo.KEY, Xoo2.KEY) | |||
.onlyWhenConfiguration(c -> c.getBoolean(ACTIVATE_EXTERNAL_ISSUES).orElse(false)); | |||
} | |||
@@ -73,6 +74,8 @@ public class OneExternalIssuePerLineSensor implements Sensor { | |||
.on(file) | |||
.at(file.selectLine(line)) | |||
.message("This issue is generated on each line")) | |||
.ruleTitle(NAME) | |||
.descriptionUrl("http://oneexternalissueperline.xoo.net") | |||
.severity(Severity.valueOf(SEVERITY)) | |||
.remediationEffort(EFFORT) | |||
.type(type) |
@@ -219,7 +219,7 @@ public class TrackerRawInputFactory { | |||
.setType(toRuleType(reportIssue.getType())) | |||
.setKey(RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + reportIssue.getRuleRepository(), reportIssue.getRuleKey())) | |||
.setPluginKey(reportIssue.getRuleRepository()) | |||
.setName(reportIssue.getRuleName()); | |||
.setName(reportIssue.getRuleTitle()); | |||
if (reportIssue.getSeverity() != Severity.UNSET_SEVERITY) { | |||
builder.setSeverity(reportIssue.getSeverity().name()); |
@@ -48,4 +48,9 @@ public interface ExternalIssue extends IIssue { | |||
* Type of the issue. | |||
*/ | |||
RuleType type(); | |||
/** | |||
* Short description of the rule. Should not depend on the issue being raised. | |||
*/ | |||
String ruleTitle(); | |||
} |
@@ -79,6 +79,11 @@ public interface NewExternalIssue { | |||
*/ | |||
NewIssueLocation newLocation(); | |||
/** | |||
* Add the description of the rule. Should not depend on the issue being raised. | |||
*/ | |||
NewExternalIssue ruleTitle(String title); | |||
/** | |||
* Save the issue. If rule key is unknown or rule not enabled in the current quality profile then a warning is logged but no exception | |||
* is thrown. |
@@ -36,6 +36,7 @@ public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIs | |||
private Severity severity; | |||
private String url; | |||
private RuleType type; | |||
private String ruleTitle; | |||
public DefaultExternalIssue() { | |||
super(null); | |||
@@ -70,12 +71,12 @@ public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIs | |||
@Override | |||
public void doSave() { | |||
requireNonNull(this.ruleKey, "ruleKey is mandatory on external issue"); | |||
requireNonNull(this.ruleKey, "Rule key is mandatory on external issue"); | |||
checkState(primaryLocation != null, "Primary location is mandatory on every external issue"); | |||
checkState(primaryLocation.inputComponent().isFile(), "External issues must be located in files"); | |||
checkState(type != null, "Type is mandatory on every external issue"); | |||
checkState(severity != null, "Severity is mandatory on every external issue"); | |||
checkState(ruleTitle != null, "Rule title is mandatory on every external issue"); | |||
checkState(severity != null, "Severity is mandatory on every external issue"); | |||
checkState(type != null, "Type is mandatory on every external issue"); | |||
storage.store(this); | |||
} | |||
@@ -100,4 +101,15 @@ public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIs | |||
this.type = type; | |||
return this; | |||
} | |||
@Override | |||
public String ruleTitle() { | |||
return ruleTitle; | |||
} | |||
@Override | |||
public DefaultExternalIssue ruleTitle(String ruleTitle) { | |||
this.ruleTitle = ruleTitle; | |||
return this; | |||
} | |||
} |
@@ -117,6 +117,7 @@ public class SensorContextTesterTest { | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.type(RuleType.BUG) | |||
.severity(Severity.BLOCKER) | |||
.ruleTitle("title") | |||
.save(); | |||
newExternalIssue = tester.newExternalIssue(); | |||
newExternalIssue | |||
@@ -124,6 +125,7 @@ public class SensorContextTesterTest { | |||
.type(RuleType.BUG) | |||
.severity(Severity.BLOCKER) | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.ruleTitle("title") | |||
.save(); | |||
assertThat(tester.allExternalIssues()).hasSize(2); | |||
} |
@@ -54,6 +54,7 @@ public class DefaultExternalIssueTest { | |||
.remediationEffort(10l) | |||
.descriptionUrl("url") | |||
.type(RuleType.BUG) | |||
.ruleTitle("rule") | |||
.severity(Severity.BLOCKER); | |||
assertThat(issue.primaryLocation().inputComponent()).isEqualTo(inputFile); | |||
@@ -63,6 +64,7 @@ public class DefaultExternalIssueTest { | |||
assertThat(issue.descriptionUrl()).isEqualTo("url"); | |||
assertThat(issue.type()).isEqualTo(RuleType.BUG); | |||
assertThat(issue.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(issue.ruleTitle()).isEqualTo("rule"); | |||
assertThat(issue.primaryLocation().message()).isEqualTo("Wrong way!"); | |||
issue.save(); | |||
@@ -81,6 +83,7 @@ public class DefaultExternalIssueTest { | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.remediationEffort(10l) | |||
.descriptionUrl("url") | |||
.ruleTitle("rule") | |||
.severity(Severity.BLOCKER); | |||
exception.expect(IllegalStateException.class); | |||
@@ -98,6 +101,7 @@ public class DefaultExternalIssueTest { | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.remediationEffort(10l) | |||
.descriptionUrl("url") | |||
.ruleTitle("rule") | |||
.severity(Severity.BLOCKER); | |||
exception.expect(IllegalStateException.class); | |||
@@ -116,6 +120,7 @@ public class DefaultExternalIssueTest { | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.remediationEffort(10l) | |||
.descriptionUrl("url") | |||
.ruleTitle("rule") | |||
.type(RuleType.BUG); | |||
exception.expect(IllegalStateException.class); | |||
@@ -123,4 +128,23 @@ public class DefaultExternalIssueTest { | |||
issue.save(); | |||
} | |||
@Test | |||
public void fail_to_store_if_no_rule_title() { | |||
SensorStorage storage = mock(SensorStorage.class); | |||
DefaultExternalIssue issue = new DefaultExternalIssue(storage) | |||
.at(new DefaultIssueLocation() | |||
.on(inputFile) | |||
.at(inputFile.selectLine(1)) | |||
.message("Wrong way!")) | |||
.forRule(RuleKey.of("repo", "rule")) | |||
.remediationEffort(10l) | |||
.descriptionUrl("url") | |||
.severity(Severity.BLOCKER) | |||
.type(RuleType.BUG); | |||
exception.expect(IllegalStateException.class); | |||
exception.expectMessage("Rule title is mandatory"); | |||
issue.save(); | |||
} | |||
} |
@@ -121,6 +121,7 @@ public class ModuleIssues { | |||
builder.setSeverity(severity); | |||
builder.setRuleRepository(issue.ruleKey().repository()); | |||
builder.setRuleKey(issue.ruleKey().rule()); | |||
builder.setRuleTitle(issue.ruleTitle()); | |||
builder.setMsg(primaryMessage); | |||
locationBuilder.setMsg(primaryMessage); | |||
@@ -155,7 +155,8 @@ public class ModuleIssuesTest { | |||
DefaultExternalIssue issue = new DefaultExternalIssue() | |||
.at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("Foo")) | |||
.forRule(SQUID_RULE_KEY) | |||
.severity(org.sonar.api.batch.rule.Severity.CRITICAL); | |||
.severity(org.sonar.api.batch.rule.Severity.CRITICAL) | |||
.ruleTitle("title"); | |||
moduleIssues.initAndAddExternalIssue(issue); | |||
@@ -201,7 +201,6 @@ message ExternalIssue { | |||
string descriptionUrl = 8; | |||
IssueType type = 9; | |||
string rule_title = 10; | |||
string rule_name = 11; | |||
} | |||
enum IssueType { |