You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

XooRulesDefinition.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2022 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  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.
  10. *
  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.
  15. *
  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.
  19. */
  20. package org.sonar.xoo.rule;
  21. import javax.annotation.Nullable;
  22. import org.sonar.api.SonarRuntime;
  23. import org.sonar.api.rule.RuleScope;
  24. import org.sonar.api.rules.RuleType;
  25. import org.sonar.api.server.rule.RuleDescriptionSection;
  26. import org.sonar.api.server.rule.RuleParamType;
  27. import org.sonar.api.server.rule.RulesDefinition;
  28. import org.sonar.api.server.rule.RulesDefinitionAnnotationLoader;
  29. import org.sonar.api.utils.Version;
  30. import org.sonar.xoo.Xoo;
  31. import org.sonar.xoo.Xoo2;
  32. import org.sonar.xoo.checks.Check;
  33. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY;
  34. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY;
  35. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY;
  36. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY;
  37. import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY;
  38. import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2017;
  39. import static org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version.Y2021;
  40. /**
  41. * Define all the coding rules that are supported on the repositories named "xoo" and "xoo2"
  42. */
  43. public class XooRulesDefinition implements RulesDefinition {
  44. public static final String XOO_REPOSITORY = "xoo";
  45. public static final String XOO2_REPOSITORY = "xoo2";
  46. private static final String TEN_MIN = "10min";
  47. @Nullable
  48. private final Version version;
  49. public XooRulesDefinition() {
  50. this(null);
  51. }
  52. public XooRulesDefinition(@Nullable SonarRuntime sonarRuntime) {
  53. this.version = sonarRuntime != null ? sonarRuntime.getApiVersion() : null;
  54. }
  55. @Override
  56. public void define(Context context) {
  57. defineRulesXoo(context);
  58. defineRulesXoo2(context);
  59. defineRulesXooExternal(context);
  60. }
  61. private static void defineRulesXoo2(Context context) {
  62. NewRepository repo = context.createRepository(XOO2_REPOSITORY, Xoo2.KEY).setName("Xoo2");
  63. NewRule hasTag = repo.createRule(HasTagSensor.RULE_KEY).setName("Has Tag");
  64. addAllDescriptionSections(hasTag, "Search for a given tag in Xoo files");
  65. NewRule oneIssuePerLine = repo.createRule(OneIssuePerLineSensor.RULE_KEY).setName("One Issue Per Line");
  66. addAllDescriptionSections(oneIssuePerLine, "Generate an issue on each line of a file. It requires the metric \"lines\".");
  67. oneIssuePerLine
  68. .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1min"))
  69. .setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code");
  70. repo.done();
  71. }
  72. private void defineRulesXoo(Context context) {
  73. NewRepository repo = context.createRepository(XOO_REPOSITORY, Xoo.KEY).setName("Xoo");
  74. new RulesDefinitionAnnotationLoader().load(repo, Check.ALL);
  75. NewRule hasTag = repo.createRule(HasTagSensor.RULE_KEY).setName("Has Tag")
  76. .setActivatedByDefault(true);
  77. addAllDescriptionSections(hasTag, "Search for a given tag in Xoo files");
  78. hasTag
  79. .setDebtRemediationFunction(hasTag.debtRemediationFunctions().constantPerIssue("2min"));
  80. hasTag.createParam("tag")
  81. .setDefaultValue("xoo")
  82. .setDescription("The tag to search for");
  83. NewRule ruleWithParameters = repo.createRule("RuleWithParameters").setName("Rule with parameters");
  84. addAllDescriptionSections(ruleWithParameters,
  85. "Rule containing parameter of different types : boolean, integer, etc. For information, no issue will be linked to this rule.");
  86. ruleWithParameters.createParam("string").setType(RuleParamType.STRING);
  87. ruleWithParameters.createParam("text").setType(RuleParamType.TEXT);
  88. ruleWithParameters.createParam("boolean").setType(RuleParamType.BOOLEAN);
  89. ruleWithParameters.createParam("integer").setType(RuleParamType.INTEGER);
  90. ruleWithParameters.createParam("float").setType(RuleParamType.FLOAT);
  91. NewRule oneIssuePerLine = repo.createRule(OneIssuePerLineSensor.RULE_KEY).setName("One Issue Per Line")
  92. .setTags("line");
  93. addAllDescriptionSections(oneIssuePerLine, "Generate an issue on each line of a file. It requires the metric \"lines\".");
  94. oneIssuePerLine
  95. .setDebtRemediationFunction(oneIssuePerLine.debtRemediationFunctions().linear("1min"))
  96. .setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code");
  97. NewRule oneQuickFixPerLine = repo.createRule(OneQuickFixPerLineSensor.RULE_KEY).setName("One Quick Fix Per Line")
  98. .setTags("line");
  99. addAllDescriptionSections(oneQuickFixPerLine,
  100. "Generate an issue with quick fix available on each line of a file. It requires the metric \"lines\".");
  101. oneQuickFixPerLine
  102. .setDebtRemediationFunction(oneQuickFixPerLine.debtRemediationFunctions().linear("1min"))
  103. .setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code");
  104. NewRule oneIssueOnDirPerFile = repo.createRule(OneIssueOnDirPerFileSensor.RULE_KEY).setName("One Issue On Dir Per File");
  105. addAllDescriptionSections(oneIssueOnDirPerFile,
  106. "Generate issues on directories");
  107. NewRule oneIssuePerFile = repo.createRule(OneIssuePerFileSensor.RULE_KEY).setName("One Issue Per File");
  108. oneIssuePerFile.setDebtRemediationFunction(oneIssuePerFile.debtRemediationFunctions().linear(TEN_MIN));
  109. addAllDescriptionSections(oneIssuePerFile, "Generate an issue on each file");
  110. NewRule oneIssuePerTestFile = repo.createRule(OneIssuePerTestFileSensor.RULE_KEY).setName("One Issue Per Test File")
  111. .setScope(RuleScope.TEST);
  112. oneIssuePerTestFile.setDebtRemediationFunction(oneIssuePerTestFile.debtRemediationFunctions().linear("8min"));
  113. addAllDescriptionSections(oneIssuePerTestFile, "Generate an issue on each test file");
  114. NewRule oneBugIssuePerTestLine = repo.createRule(OneBugIssuePerTestLineSensor.RULE_KEY).setName("One Bug Issue Per Test Line")
  115. .setScope(RuleScope.TEST)
  116. .setType(RuleType.BUG);
  117. addAllDescriptionSections(oneBugIssuePerTestLine, "Generate a bug issue on each line of a test file. It requires the metric \"lines\".");
  118. oneBugIssuePerTestLine
  119. .setDebtRemediationFunction(oneBugIssuePerTestLine.debtRemediationFunctions().linear("4min"));
  120. NewRule oneCodeSmellIssuePerTestLine = repo.createRule(OneCodeSmellIssuePerTestLineSensor.RULE_KEY).setName("One Code Smell Issue Per Test Line")
  121. .setScope(RuleScope.TEST)
  122. .setType(RuleType.CODE_SMELL);
  123. addAllDescriptionSections(oneCodeSmellIssuePerTestLine, "Generate a code smell issue on each line of a test file. It requires the metric \"lines\".");
  124. oneCodeSmellIssuePerTestLine
  125. .setDebtRemediationFunction(oneCodeSmellIssuePerTestLine.debtRemediationFunctions().linear("3min"));
  126. NewRule oneIssuePerDirectory = repo.createRule(OneIssuePerDirectorySensor.RULE_KEY).setName("One Issue Per Directory");
  127. oneIssuePerDirectory.setDebtRemediationFunction(oneIssuePerDirectory.debtRemediationFunctions().linear(TEN_MIN));
  128. addAllDescriptionSections(oneIssuePerDirectory, "Generate an issue on each non-empty directory");
  129. NewRule oneDayDebtPerFile = repo.createRule(OneDayDebtPerFileSensor.RULE_KEY).setName("One Day Debt Per File");
  130. oneDayDebtPerFile.setDebtRemediationFunction(oneDayDebtPerFile.debtRemediationFunctions().linear("1d"));
  131. addAllDescriptionSections(oneDayDebtPerFile, "Generate an issue on each file with a debt of one day");
  132. NewRule oneIssuePerModule = repo.createRule(OneIssuePerModuleSensor.RULE_KEY).setName("One Issue Per Module");
  133. oneIssuePerModule
  134. .setDebtRemediationFunction(oneIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h"))
  135. .setGapDescription("A certified architect will need roughly half an hour to start working on removal of modules, " +
  136. "then it's about one hour per module.");
  137. addAllDescriptionSections(oneIssuePerModule, "Generate an issue on each module");
  138. NewRule oneBlockerIssuePerFile = repo.createRule(OneBlockerIssuePerFileSensor.RULE_KEY).setName("One Blocker Issue Per File");
  139. addAllDescriptionSections(oneBlockerIssuePerFile, "Generate a blocker issue on each file, whatever the severity declared in the Quality profile");
  140. NewRule issueWithCustomMessage = repo.createRule(CustomMessageSensor.RULE_KEY).setName("Issue With Custom Message");
  141. addAllDescriptionSections(issueWithCustomMessage, "Generate an issue on each file with a custom message");
  142. NewRule oneIssuePerFileWithRandomAccess = repo.createRule(RandomAccessSensor.RULE_KEY).setName("One Issue Per File with Random Access");
  143. addAllDescriptionSections(oneIssuePerFileWithRandomAccess, "This issue is generated on each file");
  144. NewRule issueWithRangeAndMultipleLocations = repo.createRule(MultilineIssuesSensor.RULE_KEY).setName("Creates issues with ranges/multiple locations");
  145. addAllDescriptionSections(issueWithRangeAndMultipleLocations, "Issue with range and multiple locations");
  146. NewRule issueOnEachFileWithExtUnknown = repo.createRule(OneIssuePerUnknownFileSensor.RULE_KEY).setName("Creates issues on each file with extension 'unknown'");
  147. addAllDescriptionSections(issueOnEachFileWithExtUnknown, "This issue is generated on each file with extenstion 'unknown'");
  148. NewRule oneBugIssuePerLine = repo.createRule(OneBugIssuePerLineSensor.RULE_KEY).setName("One Bug Issue Per Line")
  149. .setType(RuleType.BUG);
  150. oneBugIssuePerLine
  151. .setDebtRemediationFunction(oneBugIssuePerLine.debtRemediationFunctions().linear("5min"));
  152. addAllDescriptionSections(oneBugIssuePerLine, "Generate a bug issue on each line of a file. It requires the metric \"lines\".");
  153. NewRule oneCodeSmellIssuePerLine = repo.createRule(OneCodeSmellIssuePerLineSensor.RULE_KEY).setName("One Code Smell Issue Per Line")
  154. .setType(RuleType.CODE_SMELL);
  155. oneCodeSmellIssuePerLine
  156. .setDebtRemediationFunction(oneCodeSmellIssuePerLine.debtRemediationFunctions().linear("9min"));
  157. addAllDescriptionSections(oneCodeSmellIssuePerLine, "Generate a code smell issue on each line of a file. It requires the metric \"lines\".");
  158. NewRule oneVulnerabilityIssuePerModule = repo.createRule(OneVulnerabilityIssuePerModuleSensor.RULE_KEY).setName("One Vulnerability Issue Per Module")
  159. .setType(RuleType.VULNERABILITY);
  160. addAllDescriptionSections(oneVulnerabilityIssuePerModule, "Generate an issue on each module");
  161. oneVulnerabilityIssuePerModule
  162. .setDebtRemediationFunction(oneVulnerabilityIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h"))
  163. .setGapDescription("A certified architect will need roughly half an hour to start working on removal of modules, " +
  164. "then it's about one hour per module.");
  165. NewRule templateofRule = repo
  166. .createRule("xoo-template")
  167. .setTemplate(true)
  168. .setName("Template of rule");
  169. addAllDescriptionSections(templateofRule, "Template to be overridden by custom rules");
  170. NewRule hotspot = repo.createRule(HotspotSensor.RULE_KEY)
  171. .setName("Find security hotspots")
  172. .setType(RuleType.SECURITY_HOTSPOT)
  173. .setActivatedByDefault(false);
  174. addAllDescriptionSections(hotspot, "Search for Security Hotspots in Xoo files");
  175. hotspot
  176. .setDebtRemediationFunction(hotspot.debtRemediationFunctions().constantPerIssue("2min"));
  177. if (version != null && version.isGreaterThanOrEqual(Version.create(9, 3))) {
  178. hotspot
  179. .addOwaspTop10(OwaspTop10.A1, OwaspTop10.A3)
  180. .addOwaspTop10(Y2021, OwaspTop10.A3, OwaspTop10.A2)
  181. .addCwe(1, 89, 123, 863);
  182. oneVulnerabilityIssuePerModule
  183. .addOwaspTop10(Y2017, OwaspTop10.A9, OwaspTop10.A10)
  184. .addOwaspTop10(Y2021, OwaspTop10.A6, OwaspTop10.A9)
  185. .addCwe(250, 564, 546, 943);
  186. }
  187. repo.done();
  188. }
  189. private static void defineRulesXooExternal(Context context) {
  190. NewRepository repo = context.createExternalRepository(OneExternalIssuePerLineSensor.ENGINE_ID, Xoo.KEY).setName(OneExternalIssuePerLineSensor.ENGINE_ID);
  191. repo.createRule(OnePredefinedRuleExternalIssuePerLineSensor.RULE_ID)
  192. .setSeverity(OnePredefinedRuleExternalIssuePerLineSensor.SEVERITY)
  193. .setType(OnePredefinedRuleExternalIssuePerLineSensor.TYPE)
  194. .setScope(RuleScope.ALL)
  195. .setHtmlDescription("Generates one external issue in each line")
  196. .addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY, "Generates one external issue in each line"))
  197. .setName("One external issue per line")
  198. .setTags("riri", "fifi", "loulou");
  199. repo.done();
  200. }
  201. private static void addAllDescriptionSections(NewRule rule, String description) {
  202. rule
  203. .setHtmlDescription(description)
  204. .addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY, "Introduction: " + description))
  205. .addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY, "Root cause: " + description))
  206. .addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY, "Assess the problem: " + description))
  207. .addDescriptionSection(descriptionSection(HOW_TO_FIX_SECTION_KEY, "How to fix: " + description))
  208. .addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY,
  209. "<a href=\"www.google.fr\"> Google </a><br><a href=\"https://stackoverflow.com/\"> StackOverflow</a>"))
  210. .addDescriptionSection(descriptionSection("fake_section_to_be_ignored",
  211. "fake_section_to_be_ignored"));
  212. }
  213. private static RuleDescriptionSection descriptionSection(String sectionKey, String htmlDescription) {
  214. return RuleDescriptionSection.builder()
  215. .sectionKey(sectionKey)
  216. .htmlContent(htmlDescription)
  217. .build();
  218. }
  219. }