Browse Source

SONAR-13357 Custom hotspot rule's description isn't split into tabs

tags/8.8.0.42792
Philippe Perrin 3 years ago
parent
commit
ffaa8f3cd6

+ 3
- 3
server/sonar-server-common/src/main/java/org/sonar/server/rule/HotspotRuleDescription.java View File

} }


public static HotspotRuleDescription from(RuleDefinitionDto dto) { public static HotspotRuleDescription from(RuleDefinitionDto dto) {
String description = dto.getDescription();
String description = dto.isCustomRule() ? RuleDescriptionFormatter.getDescriptionAsHtml(dto) : dto.getDescription();
return from(description); return from(description);
} }


if (endIndex == -1) { if (endIndex == -1) {
endIndex = description.length(); endIndex = description.length();
} }
return new String[] {
return new String[]{
description.substring(0, beginningIndex) + description.substring(endIndex), description.substring(0, beginningIndex) + description.substring(endIndex),
description.substring(beginningIndex, endIndex) description.substring(beginningIndex, endIndex)
}; };
} else { } else {
return new String[] {description, ""};
return new String[]{description, ""};
} }


} }

server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java → server/sonar-server-common/src/main/java/org/sonar/server/rule/RuleDescriptionFormatter.java View File


+ 38
- 0
server/sonar-server-common/src/test/java/org/sonar/server/rule/HotspotRuleDescriptionTest.java View File

import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.db.rule.RuleTesting; import org.sonar.db.rule.RuleTesting;


import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
assertThat(result.getFixIt().get()).isEqualTo(RECOMMENTEDCODINGPRACTICE + SEE); assertThat(result.getFixIt().get()).isEqualTo(RECOMMENTEDCODINGPRACTICE + SEE);
} }


@Test
public void parse_custom_rule_description() {
String ruleDescription = "This is the custom rule description";
String exceptionsContent = "This the exceptions section content";
String askContent = "This is the ask section content";
String recommendedContent = "This is the recommended section content";

RuleDefinitionDto dto = RuleTesting.newRule()
.setTemplateUuid("123")
.setDescriptionFormat(RuleDto.Format.MARKDOWN)
.setDescription(
ruleDescription + "\n"
+ "== Exceptions" + "\n"
+ exceptionsContent + "\n"
+ "== Ask Yourself Whether" + "\n"
+ askContent + "\n"
+ "== Recommended Secure Coding Practices" + "\n"
+ recommendedContent + "\n"
);

HotspotRuleDescription result = HotspotRuleDescription.from(dto);

assertThat(result.getRisk().get()).hasToString(
ruleDescription + "<br/>"
+ "<h2>Exceptions</h2>"
+ exceptionsContent + "<br/>"
);
assertThat(result.getVulnerable().get()).hasToString(
"<h2>Ask Yourself Whether</h2>"
+ askContent + "<br/>"
);
assertThat(result.getFixIt().get()).hasToString(
"<h2>Recommended Secure Coding Practices</h2>"
+ recommendedContent + "<br/>"
);
}

/* /*
* Bunch of static constant to create rule description. * Bunch of static constant to create rule description.
*/ */

server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java → server/sonar-server-common/src/test/java/org/sonar/server/rule/RuleDescriptionFormatterTest.java View File


+ 5
- 13
server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/ShowAction.java View File

import org.sonar.server.issue.TextRangeResponseFormatter; import org.sonar.server.issue.TextRangeResponseFormatter;
import org.sonar.server.issue.ws.UserResponseFormatter; import org.sonar.server.issue.ws.UserResponseFormatter;
import org.sonar.server.rule.HotspotRuleDescription; import org.sonar.server.rule.HotspotRuleDescription;
import org.sonar.server.rule.RuleDescriptionFormatter;
import org.sonar.server.security.SecurityStandards; import org.sonar.server.security.SecurityStandards;
import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.MacroInterpreter;
import org.sonarqube.ws.Common; import org.sonarqube.ws.Common;
.setSecurityCategory(sqCategory.getKey()) .setSecurityCategory(sqCategory.getKey())
.setVulnerabilityProbability(sqCategory.getVulnerability().name()); .setVulnerabilityProbability(sqCategory.getVulnerability().name());


if (ruleDefinitionDto.isCustomRule()) {
String htmlDescription = RuleDescriptionFormatter.getDescriptionAsHtml(ruleDefinitionDto);
if (htmlDescription != null) {
ruleBuilder.setRiskDescription(macroInterpreter.interpret(htmlDescription));
}
} else {
HotspotRuleDescription hotspotRuleDescription = HotspotRuleDescription.from(ruleDefinitionDto);
hotspotRuleDescription.getVulnerable().ifPresent(ruleBuilder::setVulnerabilityDescription);
hotspotRuleDescription.getRisk().ifPresent(ruleBuilder::setRiskDescription);
hotspotRuleDescription.getFixIt().ifPresent(ruleBuilder::setFixRecommendations);
}
HotspotRuleDescription hotspotRuleDescription = HotspotRuleDescription.from(ruleDefinitionDto);
hotspotRuleDescription.getVulnerable().ifPresent(ruleBuilder::setVulnerabilityDescription);
hotspotRuleDescription.getRisk().ifPresent(ruleBuilder::setRiskDescription);
hotspotRuleDescription.getFixIt().ifPresent(ruleBuilder::setFixRecommendations);


responseBuilder.setRule(ruleBuilder.build()); responseBuilder.setRule(ruleBuilder.build());
} }
boolean hotspotOnProject = Objects.equals(project.uuid(), componentUuid); boolean hotspotOnProject = Objects.equals(project.uuid(), componentUuid);
ComponentDto component = hotspotOnProject ? project ComponentDto component = hotspotOnProject ? project
: dbClient.componentDao().selectByUuid(dbSession, componentUuid) : dbClient.componentDao().selectByUuid(dbSession, componentUuid)
.orElseThrow(() -> new NotFoundException(format("Component with uuid '%s' does not exist", componentUuid)));
.orElseThrow(() -> new NotFoundException(format("Component with uuid '%s' does not exist", componentUuid)));


return new Components(project, component); return new Components(project, component);
} }

+ 2
- 6
server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/ShowActionTest.java View File

userSessionRule.logIn().addProjectPermission(UserRole.USER, project); userSessionRule.logIn().addProjectPermission(UserRole.USER, project);
ComponentDto file = dbTester.components().insertComponent(newFileDto(project)); ComponentDto file = dbTester.components().insertComponent(newFileDto(project));


String description = "<div>line1\nline2</div>";
String parsedDescription = "&lt;div&gt;line1<br/>line2&lt;/div&gt;";
String resultingDescription = "!" + parsedDescription + "!";
String description = "== Title\n<div>line1\nline2</div>";


RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT, RuleDefinitionDto rule = newRule(SECURITY_HOTSPOT,
r -> r.setTemplateUuid("123") r -> r.setTemplateUuid("123")
.setDescription(description) .setDescription(description)
.setDescriptionFormat(MARKDOWN)); .setDescriptionFormat(MARKDOWN));


doReturn(resultingDescription).when(macroInterpreter).interpret(parsedDescription);

IssueDto hotspot = dbTester.issues().insertHotspot(rule, project, file); IssueDto hotspot = dbTester.issues().insertHotspot(rule, project, file);
mockChangelogAndCommentsFormattingContext(); mockChangelogAndCommentsFormattingContext();


Hotspots.ShowWsResponse response = newRequest(hotspot) Hotspots.ShowWsResponse response = newRequest(hotspot)
.executeProtobuf(Hotspots.ShowWsResponse.class); .executeProtobuf(Hotspots.ShowWsResponse.class);


assertThat(response.getRule().getRiskDescription()).isEqualTo(resultingDescription);
assertThat(response.getRule().getRiskDescription()).isEqualTo("<h2>Title</h2>&lt;div&gt;line1<br/>line2&lt;/div&gt;");
} }


@Test @Test

+ 1
- 1
sonar-markdown/src/main/java/org/sonar/markdown/HtmlHeadingChannel.java View File

CharSequence headingText = token.subSequence(index, token.length()); CharSequence headingText = token.subSequence(index, token.length());


output.append("<h" + headingLevel + ">"); output.append("<h" + headingLevel + ">");
output.append(headingText);
output.append(headingText.toString().trim());
output.append("</h" + headingLevel + ">"); output.append("</h" + headingLevel + ">");
} }
} }

+ 2
- 2
sonar-markdown/src/test/java/org/sonar/markdown/MarkdownTest.java View File



@Test @Test
public void shouldDecorateHeadings() { public void shouldDecorateHeadings() {
assertThat(Markdown.convertToHtml(" = Top\r== Sub\r\n=== Subsub\n ==== \n 1.five"))
.isEqualTo("<h1>Top\r</h1><h2>Sub\r\n</h2><h3>Subsub\n</h3><h4></h4> 1.five");
assertThat(Markdown.convertToHtml(" = Top\r== Sub\r\n=== Sub sub\n ==== \n 1.five"))
.isEqualTo("<h1>Top</h1><h2>Sub</h2><h3>Sub sub</h3><h4></h4> 1.five");
} }


@Test @Test

Loading…
Cancel
Save