3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.rule;
22 import java.util.Optional;
24 import java.util.stream.Collectors;
25 import org.elasticsearch.common.util.set.Sets;
26 import org.jetbrains.annotations.Nullable;
27 import org.sonar.api.server.rule.Context;
28 import org.sonar.api.server.rule.RuleDescriptionSection;
29 import org.sonar.api.server.rule.RulesDefinition;
30 import org.sonar.core.util.UuidFactory;
31 import org.sonar.db.rule.RuleDescriptionSectionContextDto;
32 import org.sonar.db.rule.RuleDescriptionSectionDto;
34 import static org.sonar.api.rules.RuleType.*;
36 public class AdvancedRuleDescriptionSectionsGenerator implements RuleDescriptionSectionsGenerator {
37 private final UuidFactory uuidFactory;
38 private final LegacyIssueRuleDescriptionSectionsGenerator legacyIssueRuleDescriptionSectionsGenerator;
40 public AdvancedRuleDescriptionSectionsGenerator(UuidFactory uuidFactory, LegacyIssueRuleDescriptionSectionsGenerator legacyIssueRuleDescriptionSectionsGenerator) {
41 this.uuidFactory = uuidFactory;
42 this.legacyIssueRuleDescriptionSectionsGenerator = legacyIssueRuleDescriptionSectionsGenerator;
46 public boolean isGeneratorForRule(RulesDefinition.Rule rule) {
47 return !rule.ruleDescriptionSections().isEmpty() && skipHotspotRulesForSonar16635(rule);
50 private static boolean skipHotspotRulesForSonar16635(RulesDefinition.Rule rule) {
51 return !SECURITY_HOTSPOT.equals(rule.type());
55 public Set<RuleDescriptionSectionDto> generateSections(RulesDefinition.Rule rule) {
56 Set<RuleDescriptionSectionDto> advancedSections = rule.ruleDescriptionSections().stream()
57 .map(this::toRuleDescriptionSectionDto)
58 .collect(Collectors.toSet());
59 return addLegacySectionToAdvancedSections(advancedSections, rule);
63 * This was done to preserve backward compatibility with SonarLint until they stop using htmlDesc field in api/rules/[show|search] endpoints, see SONAR-16635
64 * @deprecated the method should be removed once SonarLint supports rules.descriptionSections fields, I.E in 10.x
66 @Deprecated(since = "9.6", forRemoval = true)
67 private Set<RuleDescriptionSectionDto> addLegacySectionToAdvancedSections(Set<RuleDescriptionSectionDto> advancedSections, RulesDefinition.Rule rule) {
68 Set<RuleDescriptionSectionDto> legacySection = legacyIssueRuleDescriptionSectionsGenerator.generateSections(rule);
69 return Sets.union(advancedSections, legacySection);
72 private RuleDescriptionSectionDto toRuleDescriptionSectionDto(RuleDescriptionSection section) {
73 return RuleDescriptionSectionDto.builder()
74 .uuid(uuidFactory.create())
75 .key(section.getKey())
76 .content(section.getHtmlContent())
77 .context(toRuleDescriptionSectionContextDto(section.getContext()))
82 private static RuleDescriptionSectionContextDto toRuleDescriptionSectionContextDto(Optional<Context> context) {
84 .map(c -> RuleDescriptionSectionContextDto.of(c.getKey(), c.getDisplayName()))