@@ -40,9 +40,11 @@ import org.sonar.api.batch.fs.TextPointer; | |||
import org.sonar.api.batch.sensor.Sensor; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorDescriptor; | |||
import org.sonar.api.batch.sensor.issue.MessageFormatting; | |||
import org.sonar.api.batch.sensor.issue.NewIssue; | |||
import org.sonar.api.batch.sensor.issue.NewIssue.FlowType; | |||
import org.sonar.api.batch.sensor.issue.NewIssueLocation; | |||
import org.sonar.api.batch.sensor.issue.NewMessageFormatting; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.xoo.Xoo; | |||
@@ -68,10 +70,7 @@ public class MultilineIssuesSensor implements Sensor { | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("Multiline Issues") | |||
.onlyOnLanguages(Xoo.KEY) | |||
.createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY); | |||
descriptor.name("Multiline Issues").onlyOnLanguages(Xoo.KEY).createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY); | |||
} | |||
@Override | |||
@@ -97,19 +96,25 @@ public class MultilineIssuesSensor implements Sensor { | |||
for (ParsedIssue parsedIssue : parsedIssues) { | |||
NewIssue newIssue = context.newIssue().forRule(ruleKey); | |||
NewIssueLocation primaryLocation = newIssue.newLocation() | |||
.on(file) | |||
.at(file.newRange(parsedIssue.start, parsedIssue.end)); | |||
newIssue.at(primaryLocation.message("Primary location")); | |||
NewIssueLocation primaryLocation = newIssue.newLocation(); | |||
String message = "Primary location of the issue in xoo code"; | |||
List<NewMessageFormatting> newMessageFormattings = formatIssueMessage(message, primaryLocation.newMessageFormatting()); | |||
newIssue.at(primaryLocation.on(file) | |||
.at(file.newRange(parsedIssue.start, parsedIssue.end)) | |||
.message(message, newMessageFormattings)); | |||
for (ParsedFlow flow : flowIndex.getFlows(parsedIssue.issueId)) { | |||
List<NewIssueLocation> flowLocations = new LinkedList<>(); | |||
for (ParsedFlowLocation flowLocation : flow.getLocations()) { | |||
flowLocations.add(newIssue.newLocation() | |||
String locationMessage = "Xoo code, flow step #" + flowLocation.flowLocationId; | |||
NewIssueLocation newIssueLocation = newIssue.newLocation(); | |||
List<NewMessageFormatting> locationMessageFormattings = formatIssueMessage(locationMessage, newIssueLocation.newMessageFormatting()); | |||
newIssueLocation | |||
.on(file) | |||
.at(file.newRange(flowLocation.start, flowLocation.end)) | |||
.message("Flow step #" + flowLocation.flowLocationId)); | |||
.message(locationMessage, locationMessageFormattings); | |||
flowLocations.add(newIssueLocation); | |||
} | |||
if (flow.getType() != null) { | |||
@@ -122,6 +127,15 @@ public class MultilineIssuesSensor implements Sensor { | |||
} | |||
} | |||
private static List<NewMessageFormatting> formatIssueMessage(String message, NewMessageFormatting newMessageFormatting) { | |||
int startIndex = message.toLowerCase().indexOf("xoo"); | |||
if(startIndex == -1) { | |||
return List.of(); | |||
} | |||
int endIndex = startIndex + "xoo".length(); | |||
return List.of(newMessageFormatting.start(startIndex).end(endIndex).type(MessageFormatting.Type.CODE)); | |||
} | |||
private static Collection<ParsedIssue> parseIssues(InputFile file) { | |||
Map<Integer, ParsedIssue> issuesById = new HashMap<>(); | |||
@@ -35,7 +35,7 @@ import org.sonar.api.batch.rule.ActiveRule; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import org.sonar.api.batch.sensor.issue.Issue; | |||
import org.sonar.api.batch.sensor.issue.NewIssue; | |||
import org.sonar.api.batch.sensor.issue.IssueLocation; | |||
import org.sonar.api.batch.sensor.issue.NewIssue.FlowType; | |||
import org.sonar.api.batch.sensor.issue.internal.DefaultIssueFlow; | |||
import org.sonar.api.internal.apachecommons.io.IOUtils; | |||
@@ -61,7 +61,7 @@ public class MultilineIssuesSensorTest { | |||
} | |||
@Test | |||
public void execute_dataAndExecutionFlowsAreDetected() throws IOException { | |||
public void execute_dataAndExecutionFlowsAreDetectedAndMessageIsFormatted() throws IOException { | |||
DefaultInputFile inputFile = newTestFile(IOUtils.toString(getClass().getResource("dataflow.xoo"), StandardCharsets.UTF_8)); | |||
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); | |||
@@ -73,12 +73,17 @@ public class MultilineIssuesSensorTest { | |||
assertThat(sensorContextTester.allIssues()).hasSize(1); | |||
List<Issue.Flow> flows = sensorContextTester.allIssues().iterator().next().flows(); | |||
Issue issue = sensorContextTester.allIssues().iterator().next(); | |||
assertThat(issue.primaryLocation().messageFormattings()).isNotEmpty(); | |||
List<Issue.Flow> flows = issue.flows(); | |||
assertThat(flows).hasSize(2); | |||
List<DefaultIssueFlow> defaultIssueFlows = flows.stream().map(DefaultIssueFlow.class::cast).collect(Collectors.toList()); | |||
assertThat(defaultIssueFlows).extracting(DefaultIssueFlow::type).containsExactlyInAnyOrder(FlowType.DATA, FlowType.EXECUTION); | |||
assertThat(flows.get(0).locations()).extracting(IssueLocation::messageFormattings).isNotEmpty(); | |||
assertThat(flows.get(1).locations()).extracting(IssueLocation::messageFormattings).isNotEmpty(); | |||
} | |||
private DefaultInputFile newTestFile(String content) { |
@@ -28,7 +28,6 @@ import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Flow; | |||
import org.sonar.scanner.protocol.output.ScannerReport.FlowType; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Issue; | |||
@@ -69,7 +68,7 @@ public class MultilineIssuesMediumTest { | |||
List<Issue> issues = result.issuesFor(result.inputFile("xources/hello/Single.xoo")); | |||
assertThat(issues).hasSize(1); | |||
Issue issue = issues.get(0); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location"); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location of the issue in xoo code"); | |||
assertThat(issue.getTextRange().getStartLine()).isEqualTo(6); | |||
assertThat(issue.getTextRange().getStartOffset()).isEqualTo(23); | |||
assertThat(issue.getTextRange().getEndLine()).isEqualTo(6); | |||
@@ -81,7 +80,7 @@ public class MultilineIssuesMediumTest { | |||
List<Issue> issues = result.issuesFor(result.inputFile("xources/hello/Multiline.xoo")); | |||
assertThat(issues).hasSize(1); | |||
Issue issue = issues.get(0); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location"); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location of the issue in xoo code"); | |||
assertThat(issue.getTextRange().getStartLine()).isEqualTo(6); | |||
assertThat(issue.getTextRange().getStartOffset()).isEqualTo(23); | |||
assertThat(issue.getTextRange().getEndLine()).isEqualTo(7); | |||
@@ -93,7 +92,7 @@ public class MultilineIssuesMediumTest { | |||
List<Issue> issues = result.issuesFor(result.inputFile("xources/hello/Multiple.xoo")); | |||
assertThat(issues).hasSize(1); | |||
Issue issue = issues.get(0); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location"); | |||
assertThat(issue.getMsg()).isEqualTo("Primary location of the issue in xoo code"); | |||
assertThat(issue.getTextRange().getStartLine()).isEqualTo(6); | |||
assertThat(issue.getTextRange().getStartOffset()).isEqualTo(23); | |||
assertThat(issue.getTextRange().getEndLine()).isEqualTo(6); | |||
@@ -103,7 +102,7 @@ public class MultilineIssuesMediumTest { | |||
Flow flow = issue.getFlow(0); | |||
assertThat(flow.getLocationList()).hasSize(1); | |||
IssueLocation additionalLocation = flow.getLocation(0); | |||
assertThat(additionalLocation.getMsg()).isEqualTo("Flow step #1"); | |||
assertThat(additionalLocation.getMsg()).isEqualTo("Xoo code, flow step #1"); | |||
assertThat(additionalLocation.getTextRange().getStartLine()).isEqualTo(7); | |||
assertThat(additionalLocation.getTextRange().getStartOffset()).isEqualTo(26); | |||
assertThat(additionalLocation.getTextRange().getEndLine()).isEqualTo(7); |