aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2024-12-12 17:21:22 +0100
committerSteve Marion <steve.marion@sonarsource.com>2024-12-18 11:13:23 +0100
commit65e6d0fcea6605c0967adea83fef6ec6afcb5d41 (patch)
tree8a551d6a406565ed4845425c7caa2c5568994188
parent2f1464af44ca3ad98be345c7ce72b925d72069f2 (diff)
downloadsonarqube-65e6d0fcea6605c0967adea83fef6ec6afcb5d41.tar.gz
sonarqube-65e6d0fcea6605c0967adea83fef6ec6afcb5d41.zip
SONAR-18646 Drop htmlDesc from api/rules/show and api/rules/search
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/rule/converter/RuleRestResponseGenerator.java3
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/CreateActionIT.java3
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java1
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/ShowActionIT.java62
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/UpdateActionIT.java40
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java25
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java5
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java3
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java3
-rw-r--r--sonar-ws/src/main/protobuf/ws-rules.proto1
10 files changed, 54 insertions, 92 deletions
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/rule/converter/RuleRestResponseGenerator.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/rule/converter/RuleRestResponseGenerator.java
index 8c6765ba9fe..fcd5138c48a 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/rule/converter/RuleRestResponseGenerator.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/rule/converter/RuleRestResponseGenerator.java
@@ -144,13 +144,10 @@ public class RuleRestResponseGenerator {
.map(sectionDto -> toDescriptionSectionResponse(ruleDto, sectionDto))
.toList());
- String htmlDescription = ruleDescriptionFormatter.getDescriptionAsHtml(ruleDto);
if (MARKDOWN.equals(ruleDto.getDescriptionFormat())) {
Optional.ofNullable(ruleDto.getDefaultRuleDescriptionSection())
.map(RuleDescriptionSectionDto::getContent)
.ifPresent(builder::setMarkdownDescription);
- } else if (htmlDescription != null) {
- builder.setMarkdownDescription(macroInterpreter.interpret(htmlDescription));
}
}
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/CreateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/CreateActionIT.java
index ebb4b714130..897136c0b45 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/CreateActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/CreateActionIT.java
@@ -115,7 +115,6 @@ public class CreateActionIT {
"key": "java:MY_CUSTOM",
"repo": "java",
"name": "My custom rule",
- "htmlDesc": "Description",
"severity": "MAJOR",
"status": "BETA",
"type": "BUG",
@@ -175,7 +174,6 @@ public class CreateActionIT {
"key": "java:MY_CUSTOM",
"repo": "java",
"name": "My custom rule",
- "htmlDesc": "Description",
"severity": "INFO",
"status": "BETA",
"type": "VULNERABILITY",
@@ -231,7 +229,6 @@ public class CreateActionIT {
" \"key\": \"java:MY_CUSTOM\",\n" +
" \"repo\": \"java\",\n" +
" \"name\": \"My custom rule\",\n" +
- " \"htmlDesc\": \"Description\",\n" +
" \"severity\": \"MAJOR\",\n" +
" \"status\": \"REMOVED\",\n" +
" \"isTemplate\": false\n" +
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java
index 216f77cfcf8..b7b3255c820 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/SearchActionIT.java
@@ -378,7 +378,6 @@ class SearchActionIT {
// not returned fields
assertThat(result.hasGapDescription()).isFalse();
- assertThat(result.hasHtmlDesc()).isFalse();
assertThat(result.hasIsTemplate()).isFalse();
assertThat(result.hasLang()).isFalse();
assertThat(result.hasName()).isFalse();
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/ShowActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/ShowActionIT.java
index 6573293956b..7ef03042fd2 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/ShowActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/ShowActionIT.java
@@ -329,9 +329,13 @@ class ShowActionIT {
.setParam("key", customRule.getKey().toString())
.executeProtobuf(ShowResponse.class);
- assertThat(result.getRule().getHtmlDesc()).isEqualTo(INTERPRETED);
+ assertThat(result.getRule().getMdDesc()).isEqualTo("<div>line1\nline2</div>");
assertThat(result.getRule().getTemplateKey()).isEqualTo(templateRule.getKey().toString());
- verify(macroInterpreter, times(2)).interpret("&lt;div&gt;line1<br/>line2&lt;/div&gt;");
+ verify(macroInterpreter, times(1)).interpret("&lt;div&gt;line1<br/>line2&lt;/div&gt;");
+
+ assertThat(result.getRule().getDescriptionSections().getDescriptionSectionsList())
+ .extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent)
+ .containsExactly(tuple(DEFAULT_KEY, INTERPRETED));
}
@Test
@@ -370,8 +374,8 @@ class ShowActionIT {
Rule resultRule = result.getRule();
assertThat(resultRule)
- .extracting(Rule::getName, Rule::getHtmlDesc, Rule::getSeverity, Rule::getType)
- .containsExactlyInAnyOrder("adhoc name", "&lt;div&gt;desc2&lt;/div&gt;", Severity.BLOCKER, VULNERABILITY);
+ .extracting(Rule::getName, Rule::getSeverity, Rule::getType)
+ .containsExactlyInAnyOrder("adhoc name", Severity.BLOCKER, VULNERABILITY);
assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
.extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent)
@@ -398,8 +402,6 @@ class ShowActionIT {
.executeProtobuf(ShowResponse.class);
Rule resultRule = result.getRule();
- assertThat(resultRule.getHtmlDesc()).isEmpty();
- assertThat(resultRule.getMdDesc()).isEqualTo(resultRule.getHtmlDesc());
assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
.extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent, section -> section.getContext().getKey(), section -> section.getContext().getDisplayName())
@@ -424,7 +426,6 @@ class ShowActionIT {
.executeProtobuf(ShowResponse.class);
Rule resultRule = result.getRule();
- assertThat(resultRule.getHtmlDesc()).isEqualTo(INTERPRETED);
assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
.extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent)
.containsExactly(tuple(DEFAULT_KEY, INTERPRETED));
@@ -444,39 +445,12 @@ class ShowActionIT {
.executeProtobuf(ShowResponse.class);
Rule resultRule = result.getRule();
- assertThat(resultRule.getHtmlDesc()).isEqualTo(INTERPRETED);
assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
.extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent)
.containsExactly(tuple(DEFAULT_KEY, INTERPRETED));
}
@Test
- void show_if_advanced_sections_and_default_filters_out_default() {
- when(macroInterpreter.interpret(anyString())).thenAnswer(invocation -> invocation.getArgument(0));
-
- RuleDescriptionSectionDto section1 = createRuleDescriptionSection(ROOT_CAUSE_SECTION_KEY, "<div>Root is Root</div>");
- RuleDescriptionSectionDto defaultSection = createDefaultRuleDescriptionSection(uuidFactory.create(), "This is the default section");
-
- RuleDto rule = createRuleWithDescriptionSections(section1, defaultSection);
- rule.setType(RuleType.SECURITY_HOTSPOT);
- rule.setNoteUserUuid(userDto.getUuid());
- db.rules().insert(rule);
-
- ShowResponse result = ws.newRequest()
- .setParam(PARAM_KEY, rule.getKey().toString())
- .executeProtobuf(ShowResponse.class);
-
- Rule resultRule = result.getRule();
- assertThat(resultRule.getHtmlDesc()).contains(defaultSection.getContent());
-
- assertThat(resultRule.getMdDesc()).isEqualTo(resultRule.getHtmlDesc());
-
- assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
- .extracting(Rule.DescriptionSection::getKey, Rule.DescriptionSection::getContent)
- .containsExactlyInAnyOrder(tuple(ROOT_CAUSE_SECTION_KEY, "<div>Root is Root</div>"));
- }
-
- @Test
void show_rule_markdown_description() {
when(macroInterpreter.interpret(anyString())).thenAnswer(invocation -> invocation.getArgument(0));
@@ -493,7 +467,7 @@ class ShowActionIT {
Rule resultRule = result.getRule();
- assertThat(resultRule.getHtmlDesc()).contains("<strong>toto is toto</strong>");
+ assertThat(getDefaultSection(resultRule)).contains("<strong>toto is toto</strong>");
assertThat(resultRule.getMdDesc()).contains("*toto is toto*");
assertThat(resultRule.getDescriptionSections().getDescriptionSectionsList())
@@ -501,6 +475,14 @@ class ShowActionIT {
.contains(tuple(DEFAULT_KEY, "<strong>toto is toto</strong>"));
}
+ private static String getDefaultSection(Rule rule) {
+ return rule.getDescriptionSections().getDescriptionSectionsList().stream()
+ .filter(s -> "default".equals(s.getKey()))
+ .findFirst()
+ .map(Rule.DescriptionSection::getContent)
+ .orElse(null);
+ }
+
@Test
void ignore_predefined_info_on_adhoc_rule() {
RuleDto externalRule = newRule(createDefaultRuleDescriptionSection(uuidFactory.create(), "<div>predefined desc</div>"))
@@ -524,7 +506,7 @@ class ShowActionIT {
Rule resultRule = result.getRule();
assertThat(resultRule)
- .extracting(Rule::getName, Rule::getHtmlDesc, Rule::getSeverity, Rule::getType)
+ .extracting(Rule::getName, ShowActionIT::getDefaultSection, Rule::getSeverity, Rule::getType)
.containsExactlyInAnyOrder("adhoc name", "&lt;div&gt;adhoc desc&lt;/div&gt;", Severity.MAJOR, Common.RuleType.CODE_SMELL);
}
@@ -550,8 +532,12 @@ class ShowActionIT {
Rule resultRule = result.getRule();
assertThat(resultRule)
- .extracting(Rule::hasName, Rule::hasHtmlDesc, Rule::hasSeverity, Rule::getType)
- .containsExactlyInAnyOrder(false, false, false, UNKNOWN);
+ .extracting(Rule::hasName, ShowActionIT::getDescriptionSectionsCount, Rule::hasSeverity, Rule::getType)
+ .containsExactlyInAnyOrder(false, 1, false, UNKNOWN);
+ }
+
+ private static int getDescriptionSectionsCount(Rule r) {
+ return r.getDescriptionSections().getDescriptionSectionsCount();
}
@Test
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/UpdateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/UpdateActionIT.java
index 5c4197ddb81..144ed783e62 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/UpdateActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/rule/ws/UpdateActionIT.java
@@ -139,25 +139,27 @@ class UpdateActionIT {
.setParam("params", "regex=a.*")
.execute();
- assertJson(request.getInput()).isSimilarTo("{\n" +
- " \"rule\": {\n" +
- " \"key\": \"java:MY_CUSTOM\",\n" +
- " \"repo\": \"java\",\n" +
- " \"name\": \"My custom rule\",\n" +
- " \"htmlDesc\": \"Description\",\n" +
- " \"severity\": \"MAJOR\",\n" +
- " \"status\": \"BETA\",\n" +
- " \"isTemplate\": false,\n" +
- " \"templateKey\": \"java:S001\",\n" +
- " \"params\": [\n" +
- " {\n" +
- " \"key\": \"regex\",\n" +
- " \"htmlDesc\": \"Reg ex\",\n" +
- " \"defaultValue\": \"a.*\"\n" +
- " }\n" +
- " ]\n" +
- " }\n" +
- "}\n");
+ assertJson(request.getInput()).isSimilarTo("""
+ {
+ "rule": {
+ "key": "java:MY_CUSTOM",
+ "repo": "java",
+ "name": "My custom rule",
+ "mdDesc": "Description",
+ "severity": "MAJOR",
+ "status": "BETA",
+ "isTemplate": false,
+ "templateKey": "java:S001",
+ "params": [
+ {
+ "key": "regex",
+ "htmlDesc": "Reg ex",
+ "defaultValue": "a.*"
+ }
+ ]
+ }
+ }
+ """);
}
@Test
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
index a90216e1b55..7c615d3bef9 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
@@ -63,7 +63,6 @@ import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEPRECATED_KEYS;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DESCRIPTION_SECTIONS;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_EDUCATION_PRINCIPLES;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GAP_DESCRIPTION;
-import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_HTML_DESCRIPTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_INTERNAL_KEY;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_TEMPLATE;
@@ -179,10 +178,6 @@ public class RuleMapper {
private void setAdHocDescription(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
String adHocDescription = ruleDto.getAdHocDescription();
- if (adHocDescription != null && shouldReturnField(fieldsToReturn, FIELD_HTML_DESCRIPTION)) {
- ruleResponse.setHtmlDesc(macroInterpreter.interpret(adHocDescription));
- }
-
if (shouldReturnField(fieldsToReturn, FIELD_DESCRIPTION_SECTIONS) && adHocDescription != null) {
ruleResponse.clearDescriptionSections();
ruleResponse.getDescriptionSectionsBuilder().addDescriptionSectionsBuilder()
@@ -361,17 +356,9 @@ public class RuleMapper {
}
private void setDescriptionFields(Rules.Rule.Builder ruleResponse, RuleDto ruleDto, Set<String> fieldsToReturn) {
- if (shouldReturnField(fieldsToReturn, FIELD_HTML_DESCRIPTION)) {
- String htmlDescription = ruleDescriptionFormatter.getDescriptionAsHtml(ruleDto);
- if (htmlDescription != null) {
- ruleResponse.setHtmlDesc(macroInterpreter.interpret(htmlDescription));
- }
- }
-
if (shouldReturnField(fieldsToReturn, FIELD_DESCRIPTION_SECTIONS)) {
Set<RuleDescriptionSectionDto> ruleDescriptionSectionDtos = ruleDto.getRuleDescriptionSectionDtos();
Set<Rules.Rule.DescriptionSection> sections = ruleDescriptionSectionDtos.stream()
- .filter(sectionDto -> !isDefaultAndMoreThanOneSectionPresent(ruleDescriptionSectionDtos, sectionDto))
.map(sectionDto -> toDescriptionSection(ruleDto, sectionDto))
.collect(Collectors.toSet());
ruleResponse.setDescriptionSections(Rules.Rule.DescriptionSections.newBuilder().addAllDescriptionSections(sections).build());
@@ -382,22 +369,10 @@ public class RuleMapper {
Optional.ofNullable(ruleDto.getDefaultRuleDescriptionSection())
.map(RuleDescriptionSectionDto::getContent)
.ifPresent(ruleResponse::setMdDesc);
- } else {
- ruleResponse.setMdDesc(ruleResponse.getHtmlDesc());
}
}
}
- /**
- * This was done to preserve backward compatibility with SonarLint until they stop using htmlDesc field in api/rules/[show|search] endpoints, see SONAR-16635
- *
- * @deprecated the method should be removed once SonarLint supports rules.descriptionSections fields, I.E in 10.x and DB is cleaned up of non-necessary default sections.
- */
- @Deprecated(since = "9.6", forRemoval = true)
- private static boolean isDefaultAndMoreThanOneSectionPresent(Set<RuleDescriptionSectionDto> ruleDescriptionSectionDtos, RuleDescriptionSectionDto s) {
- return ruleDescriptionSectionDtos.size() > 1 && s.isDefault();
- }
-
private Rules.Rule.DescriptionSection toDescriptionSection(RuleDto ruleDto, RuleDescriptionSectionDto section) {
String htmlContent = ruleDescriptionFormatter.toHtml(ruleDto.getDescriptionFormat(), section);
String interpretedHtmlContent = macroInterpreter.interpret(htmlContent);
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
index 85f468ba652..5b169210967 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
@@ -68,6 +68,11 @@ public class RulesWsParameters {
public static final String FIELD_SYSTEM_TAGS = "sysTags";
public static final String FIELD_LANGUAGE = "lang";
public static final String FIELD_LANGUAGE_NAME = "langName";
+ /**
+ * For backward compatibility with SonarLint we still accept this field in the request, but we won't return it
+ * @deprecated since 2025.1
+ */
+ @Deprecated(since = "2025.1")
public static final String FIELD_HTML_DESCRIPTION = "htmlDesc";
public static final String FIELD_MARKDOWN_DESCRIPTION = "mdDesc";
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java
index e3fdcd222e0..b3c7e27d53e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java
@@ -198,7 +198,8 @@ public class SearchAction implements RulesWsAction {
new Change("10.8", "The values 'severity' and 'types' for the 'facets' parameter are not deprecated anymore."),
new Change("10.8", "The fields 'type' and 'severity' in the response are not deprecated anymore."),
new Change("10.8", "The value 'severity' for the 'f' parameter is not deprecated anymore."),
- new Change("2025.2", format("The facet '%s' has been added.", FACET_ACTIVE_IMPACT_SEVERITY)));
+ new Change("2025.1", format("The facet '%s' has been added.", FACET_ACTIVE_IMPACT_SEVERITY)),
+ new Change("2025.1", "The deprecated field 'htmlDesc' is not returned anymore, even if specified in the 'f' parameter."));
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java
index 41e5be91c2f..990d322ce9e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java
@@ -88,7 +88,8 @@ public class ShowAction implements RulesWsAction {
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("10.2", "The field 'severity' and 'type' in the response have been deprecated, use 'impacts' instead."),
new Change("10.8", format("Possible values '%s' and '%s' for response field 'severity' of 'impacts' have been added.", INFO.name(), BLOCKER.name())),
- new Change("10.8", "The field 'severity' and 'type' in the response are not deprecated anymore."));
+ new Change("10.8", "The field 'severity' and 'type' in the response are not deprecated anymore."),
+ new Change("2025.1", "The deprecated field 'htmlDesc' is not returned anymore, even if specified in the 'f' parameter."));
action
.createParam(PARAM_KEY)
diff --git a/sonar-ws/src/main/protobuf/ws-rules.proto b/sonar-ws/src/main/protobuf/ws-rules.proto
index d0e62066763..49373f0deeb 100644
--- a/sonar-ws/src/main/protobuf/ws-rules.proto
+++ b/sonar-ws/src/main/protobuf/ws-rules.proto
@@ -73,7 +73,6 @@ message Rule {
optional string repo = 2;
optional string name = 3;
optional string createdAt = 4;
- optional string htmlDesc = 5 [deprecated = true];
optional string htmlNote = 6;
optional string mdDesc = 7;
optional string mdNote = 8;