From 236154100f9741cfd1efa3a3905525bbc49fb5c5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 28 Jul 2017 11:33:36 +0200 Subject: [PATCH 01/24] [doc] Add possibility to override editme link location If the page contains the variable "editmepath" in the yaml frontmatter, this will be used instead of "page.path" (the actual markdown file). This is useful, if the page is generated from another source. --- docs/_layouts/page.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html index 78a082ab1..8e65184b0 100644 --- a/docs/_layouts/page.html +++ b/docs/_layouts/page.html @@ -41,7 +41,12 @@

{{ page.title }}

{% if site.github_editme_path %} - Edit me + {% assign editmepath = page.path %} + {% if page.editmepath %} + {% assign editmepath = page.editmepath %} + {% endif %} + + Edit me {% endif %} From 509acb6d8f8a29f5fe45933fab29ac9335fc800e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 28 Jul 2017 11:34:59 +0200 Subject: [PATCH 02/24] [doc] Add option to select the active sidebar item If the page contains the variable "sidebaractiveurl" in the yaml frontmatter, this is additionally used to select the active item in the sidebar. Useful, if the page doesn't have its own item, but wants to activate e.g. the parent page. --- docs/_includes/sidebar.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_includes/sidebar.html b/docs/_includes/sidebar.html index 235ce7357..30adf8722 100644 --- a/docs/_includes/sidebar.html +++ b/docs/_includes/sidebar.html @@ -12,7 +12,7 @@ {% if folderitem.output contains "web" %} {% if folderitem.external_url %}
  • {{folderitem.title}}
  • - {% elsif page.url == folderitem.url %} + {% elsif page.url == folderitem.url or page.sidebaractiveurl == folderitem.url %}
  • {{folderitem.title}}
  • {% else %}
  • {{folderitem.title}}
  • From 84313b9ebeaa376b11da5d201895aada4fae0e7a Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 28 Jul 2017 12:14:13 +0200 Subject: [PATCH 03/24] [doc] Create a simple rule doc generator --- .../pmd/docs/GenerateRuleDocsTest.java | 19 ++ .../pmd/docs/RuleDocGenerator.java | 295 ++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java create mode 100644 pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java new file mode 100644 index 000000000..11546defa --- /dev/null +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java @@ -0,0 +1,19 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import java.nio.file.FileSystems; + +import org.junit.Test; + +public class GenerateRuleDocsTest { + @Test + public void generateDocs() { + long start = System.currentTimeMillis(); + RuleDocGenerator generator = new RuleDocGenerator(); + generator.generate(FileSystems.getDefault().getPath("..").toAbsolutePath().normalize()); + System.out.println("Generated docs in " + (System.currentTimeMillis() - start) + " ms"); + } +} diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java new file mode 100644 index 000000000..df752152e --- /dev/null +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -0,0 +1,295 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; + +import net.sourceforge.pmd.PropertyDescriptor; +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; +import net.sourceforge.pmd.lang.Language; + +public class RuleDocGenerator { + private static final String LANGUAGE_INDEX_FILENAME_PATTERN = "docs/pages/pmd/rules/${language.tersename}.md"; + private static final String LANGUAGE_INDEX_PERMALINK_PATTERN = "pmd_rules_${language.tersename}.html"; + private static final String RULESET_INDEX_FILENAME_PATTERN = "docs/pages/pmd/rules/${language.tersename}/${ruleset.name}.md"; + private static final String RULESET_INDEX_PERMALINK_PATTERN = "pmd_rules_${language.tersename}_${ruleset.name}.html"; + + private Path root; + + public void generate(Path root) { + this.root = Objects.requireNonNull(root, "Root directory must be provided"); + + Path docsDir = root.resolve("docs"); + if (!Files.exists(docsDir) || !Files.isDirectory(docsDir)) { + throw new IllegalArgumentException("Couldn't find \"docs\" subdirectory"); + } + + Map> rulesets; + try { + rulesets = loadAndSortRulesets(); + generateLanguageIndex(rulesets); + generateRuleSetIndex(rulesets); + + } catch (RuleSetNotFoundException | IOException e) { + throw new RuntimeException(e); + } + } + + private Path getAbsoluteOutputPath(String filename) { + return root.resolve(FilenameUtils.normalize(filename)); + } + + private Map> loadAndSortRulesets() throws RuleSetNotFoundException { + RuleSetFactory ruleSetFactory = new RuleSetFactory(); + Iterator registeredRuleSets = ruleSetFactory.getRegisteredRuleSets(); + + Map> rulesets = new HashMap<>(); + + while (registeredRuleSets.hasNext()) { + RuleSet ruleset = registeredRuleSets.next(); + Language language = getRuleSetLanguage(ruleset); + + if (!rulesets.containsKey(language)) { + rulesets.put(language, new ArrayList()); + } + rulesets.get(language).add(ruleset); + } + + for (List rulesetsOfOneLanguage : rulesets.values()) { + Collections.sort(rulesetsOfOneLanguage, new Comparator() { + @Override + public int compare(RuleSet o1, RuleSet o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }); + } + return rulesets; + } + + /** + * Rulesets could potentially contain rules from various languages. + * But for built-in rulesets, all rules within one ruleset belong to + * one language. So we take the language of the first rule. + * @param ruleset + * @return the terse name of the ruleset's language + */ + private static Language getRuleSetLanguage(RuleSet ruleset) { + Collection rules = ruleset.getRules(); + if (rules.isEmpty()) { + throw new RuntimeException("Ruleset " + ruleset.getFileName() + " is empty!"); + } + return rules.iterator().next().getLanguage(); + } + + /** + * Writes for each language an index file, which lists the rulesets, the rules + * and links to the ruleset pages. + * @param rulesets all rulesets + * @throws IOException + */ + private void generateLanguageIndex(Map> rulesets) throws IOException { + for (Map.Entry> entry : rulesets.entrySet()) { + String languageTersename = entry.getKey().getTerseName(); + String filename = LANGUAGE_INDEX_FILENAME_PATTERN + .replace("${language.tersename}", languageTersename); + Path path = getAbsoluteOutputPath(filename); + + List lines = new LinkedList<>(); + lines.add("---"); + lines.add("title: " + entry.getKey().getName() + " Rules"); + lines.add("permalink: " + LANGUAGE_INDEX_PERMALINK_PATTERN.replace("${language.tersename}", languageTersename)); + lines.add("folder: pmd/rules"); + lines.add("---"); + + lines.add("List of rulesets and rules contained in each ruleset."); + lines.add(""); + + for (RuleSet ruleset : entry.getValue()) { + String link = RULESET_INDEX_PERMALINK_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + lines.add("* [" + ruleset.getName() + "](" + link + "): " + getRuleSetDescriptionSingleLine(ruleset)); + } + lines.add(""); + + for (RuleSet ruleset : entry.getValue()) { + lines.add("## " + ruleset.getName()); + + for (Rule rule : ruleset.getRules()) { + String link = RULESET_INDEX_PERMALINK_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + link += "#" + rule.getName().toLowerCase(Locale.ROOT); + lines.add("* [" + rule.getName() + "](" + link + "): " + getShortRuleDescription(rule)); + } + lines.add(""); + } + + System.out.println("Generated " + path); + Files.write(path, lines, StandardCharsets.UTF_8); + } + } + + /** + * Shortens and escapes (for markdown) some special characters. Otherwise the shortened text + * could contain some unfinished sequences. + * @param rule + * @return + */ + private static String getShortRuleDescription(Rule rule) { + return StringUtils.abbreviate( + StringUtils.stripToEmpty(rule.getDescription().replaceAll("\n|\r", "") + .replaceAll("\\|", "\\\\|") + .replaceAll("`", "'") + .replaceAll("\\*", "")), 100); + } + + /** + * Gets the sanitized base name of the ruleset. + * For some reason, the filename might contain some newlines, which are removed. + * @param ruleset + * @return + */ + private static String getRuleSetFilename(RuleSet ruleset) { + return FilenameUtils.getBaseName(StringUtils.chomp(ruleset.getFileName())); + } + + private static String getRuleSetDescriptionSingleLine(RuleSet ruleset) { + String description = ruleset.getDescription(); + description = description.replaceAll("\\n|\\r", " "); + description = StringUtils.stripToEmpty(description); + return description; + } + + /** + * Generates for each ruleset a page. The page contains the details for each rule. + * + * @param rulesets all rulesets + * @throws IOException + */ + private void generateRuleSetIndex(Map> rulesets) throws IOException { + for (Map.Entry> entry : rulesets.entrySet()) { + String languageTersename = entry.getKey().getTerseName(); + for (RuleSet ruleset : entry.getValue()) { + String filename = RULESET_INDEX_FILENAME_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + + Path path = getAbsoluteOutputPath(filename); + + String permalink = RULESET_INDEX_PERMALINK_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ruleset)); + + List lines = new LinkedList<>(); + lines.add("---"); + lines.add("title: " + ruleset.getName()); + lines.add("summary: " + getRuleSetDescriptionSingleLine(ruleset)); + lines.add("permalink: " + permalink); + lines.add("folder: pmd/rules/" + languageTersename); + lines.add("sidebaractiveurl: /" + LANGUAGE_INDEX_PERMALINK_PATTERN.replace("${language.tersename}", languageTersename)); + lines.add("editmepath: ../" + getRuleSetSourceFilepath(ruleset)); + lines.add("---"); + + for (Rule rule : ruleset.getRules()) { + lines.add("## " + rule.getName()); + if (rule.getSince() != null) { + lines.add("**Since:** " + rule.getSince()); + lines.add(""); + } + lines.add("**Priority:** " + rule.getPriority() + " (" + rule.getPriority().getPriority() + ")"); + lines.add(""); + + lines.add(StringUtils.stripToEmpty(rule.getDescription())); + lines.add(""); + if (!rule.getExamples().isEmpty()) { + lines.add("**Example(s):**"); + for (String example : rule.getExamples()) { + lines.add("```"); + lines.add(StringUtils.stripToEmpty(example)); + lines.add("```"); + lines.add(""); + } + } + if (!rule.getPropertyDescriptors().isEmpty()) { + lines.add("**This rule has the following properties:**"); + lines.add(""); + lines.add("|Name|Default Value|Description|"); + lines.add("|----|-------------|-----------|"); + for (PropertyDescriptor propertyDescriptor : rule.getPropertyDescriptors()) { + lines.add("|" + propertyDescriptor.name() + + "|" + (propertyDescriptor.defaultValue() != null ? String.valueOf(propertyDescriptor.defaultValue()) : "") + + "|" + propertyDescriptor.description() + + "|"); + } + lines.add(""); + } + } + + Files.createDirectories(path.getParent()); + Files.write(path, lines, StandardCharsets.UTF_8); + System.out.println("Generated " + path); + } + } + } + + /** + * Searches for the source file of the given ruleset. This provides the information + * for the "editme" link. + * + * @param ruleset the ruleset to search for. + * @return + * @throws IOException + */ + private static String getRuleSetSourceFilepath(RuleSet ruleset) throws IOException { + Path root = FileSystems.getDefault().getPath("..").toAbsolutePath().normalize(); + final String rulesetFilename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName())); + final List foundPathResult = new LinkedList<>(); + + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String path = file.toString(); + if (path.contains("src") && path.endsWith(rulesetFilename)) { + foundPathResult.add(file); + return FileVisitResult.TERMINATE; + } + return super.visitFile(file, attrs); + } + }); + + if (!foundPathResult.isEmpty()) { + Path foundPath = foundPathResult.get(0); + foundPath = root.relativize(foundPath); + return foundPath.toString(); + } + + return StringUtils.chomp(ruleset.getFileName()); + } +} From 4dd218bc25f92817f112a79393dc240a58be38b0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 28 Jul 2017 12:14:47 +0200 Subject: [PATCH 04/24] [doc] Add initially generated rule docs and update sidebar --- docs/_data/sidebars/pmd_sidebar.yml | 10 +- docs/pages/pmd/rules/apex.md | 91 +- docs/pages/pmd/rules/apex/apexunit.md | 69 + docs/pages/pmd/rules/apex/braces.md | 134 ++ docs/pages/pmd/rules/apex/complexity.md | 365 ++++ docs/pages/pmd/rules/apex/performance.md | 66 + docs/pages/pmd/rules/apex/security.md | 336 ++++ docs/pages/pmd/rules/apex/style.md | 185 ++ docs/pages/pmd/rules/ecmascript.md | 33 + docs/pages/pmd/rules/ecmascript/basic.md | 307 +++ docs/pages/pmd/rules/ecmascript/braces.md | 124 ++ .../pages/pmd/rules/ecmascript/unnecessary.md | 96 + docs/pages/pmd/rules/java.md | 361 +++- docs/pages/pmd/rules/java/android.md | 87 + docs/pages/pmd/rules/java/basic.md | 734 +++++++ docs/pages/pmd/rules/java/braces.md | 118 ++ docs/pages/pmd/rules/java/clone.md | 155 ++ docs/pages/pmd/rules/java/codesize.md | 532 +++++ docs/pages/pmd/rules/java/comments.md | 136 ++ docs/pages/pmd/rules/java/controversial.md | 690 +++++++ docs/pages/pmd/rules/java/coupling.md | 178 ++ docs/pages/pmd/rules/java/design.md | 1708 +++++++++++++++++ docs/pages/pmd/rules/java/empty.md | 314 +++ docs/pages/pmd/rules/java/finalizers.md | 151 ++ docs/pages/pmd/rules/java/imports.md | 155 ++ docs/pages/pmd/rules/java/j2ee.md | 238 +++ docs/pages/pmd/rules/java/javabeans.md | 67 + docs/pages/pmd/rules/java/junit.md | 360 ++++ .../pmd/rules/java/logging-jakarta-commons.md | 134 ++ docs/pages/pmd/rules/java/logging-java.md | 161 ++ docs/pages/pmd/rules/java/migrating.md | 391 ++++ docs/pages/pmd/rules/java/naming.md | 530 +++++ docs/pages/pmd/rules/java/optimizations.md | 363 ++++ docs/pages/pmd/rules/java/strictexception.md | 342 ++++ docs/pages/pmd/rules/java/strings.md | 415 ++++ docs/pages/pmd/rules/java/sunsecure.md | 60 + docs/pages/pmd/rules/java/unnecessary.md | 316 +++ docs/pages/pmd/rules/java/unusedcode.md | 102 + docs/pages/pmd/rules/javascript.md | 6 - docs/pages/pmd/rules/jsp.md | 24 +- docs/pages/pmd/rules/jsp/basic-jsf.md | 33 + docs/pages/pmd/rules/jsp/basic.md | 293 +++ docs/pages/pmd/rules/plsql.md | 33 +- docs/pages/pmd/rules/plsql/TomKytesDespair.md | 68 + docs/pages/pmd/rules/plsql/codesize.md | 524 +++++ docs/pages/pmd/rules/plsql/dates.md | 133 ++ docs/pages/pmd/rules/plsql/strictsyntax.md | 46 + docs/pages/pmd/rules/vf.md | 13 + docs/pages/pmd/rules/vf/security.md | 46 + docs/pages/pmd/rules/vm.md | 18 +- docs/pages/pmd/rules/vm/basic.md | 140 ++ docs/pages/pmd/rules/xml.md | 15 +- docs/pages/pmd/rules/xml/basic.md | 29 + docs/pages/pmd/rules/xsl.md | 13 + docs/pages/pmd/rules/xsl/xpath.md | 52 + 55 files changed, 12047 insertions(+), 53 deletions(-) create mode 100644 docs/pages/pmd/rules/apex/apexunit.md create mode 100644 docs/pages/pmd/rules/apex/braces.md create mode 100644 docs/pages/pmd/rules/apex/complexity.md create mode 100644 docs/pages/pmd/rules/apex/performance.md create mode 100644 docs/pages/pmd/rules/apex/security.md create mode 100644 docs/pages/pmd/rules/apex/style.md create mode 100644 docs/pages/pmd/rules/ecmascript.md create mode 100644 docs/pages/pmd/rules/ecmascript/basic.md create mode 100644 docs/pages/pmd/rules/ecmascript/braces.md create mode 100644 docs/pages/pmd/rules/ecmascript/unnecessary.md create mode 100644 docs/pages/pmd/rules/java/android.md create mode 100644 docs/pages/pmd/rules/java/basic.md create mode 100644 docs/pages/pmd/rules/java/braces.md create mode 100644 docs/pages/pmd/rules/java/clone.md create mode 100644 docs/pages/pmd/rules/java/codesize.md create mode 100644 docs/pages/pmd/rules/java/comments.md create mode 100644 docs/pages/pmd/rules/java/controversial.md create mode 100644 docs/pages/pmd/rules/java/coupling.md create mode 100644 docs/pages/pmd/rules/java/design.md create mode 100644 docs/pages/pmd/rules/java/empty.md create mode 100644 docs/pages/pmd/rules/java/finalizers.md create mode 100644 docs/pages/pmd/rules/java/imports.md create mode 100644 docs/pages/pmd/rules/java/j2ee.md create mode 100644 docs/pages/pmd/rules/java/javabeans.md create mode 100644 docs/pages/pmd/rules/java/junit.md create mode 100644 docs/pages/pmd/rules/java/logging-jakarta-commons.md create mode 100644 docs/pages/pmd/rules/java/logging-java.md create mode 100644 docs/pages/pmd/rules/java/migrating.md create mode 100644 docs/pages/pmd/rules/java/naming.md create mode 100644 docs/pages/pmd/rules/java/optimizations.md create mode 100644 docs/pages/pmd/rules/java/strictexception.md create mode 100644 docs/pages/pmd/rules/java/strings.md create mode 100644 docs/pages/pmd/rules/java/sunsecure.md create mode 100644 docs/pages/pmd/rules/java/unnecessary.md create mode 100644 docs/pages/pmd/rules/java/unusedcode.md delete mode 100644 docs/pages/pmd/rules/javascript.md create mode 100644 docs/pages/pmd/rules/jsp/basic-jsf.md create mode 100644 docs/pages/pmd/rules/jsp/basic.md create mode 100644 docs/pages/pmd/rules/plsql/TomKytesDespair.md create mode 100644 docs/pages/pmd/rules/plsql/codesize.md create mode 100644 docs/pages/pmd/rules/plsql/dates.md create mode 100644 docs/pages/pmd/rules/plsql/strictsyntax.md create mode 100644 docs/pages/pmd/rules/vf.md create mode 100644 docs/pages/pmd/rules/vf/security.md create mode 100644 docs/pages/pmd/rules/vm/basic.md create mode 100644 docs/pages/pmd/rules/xml/basic.md create mode 100644 docs/pages/pmd/rules/xsl.md create mode 100644 docs/pages/pmd/rules/xsl/xpath.md diff --git a/docs/_data/sidebars/pmd_sidebar.yml b/docs/_data/sidebars/pmd_sidebar.yml index ec2717372..319260753 100644 --- a/docs/_data/sidebars/pmd_sidebar.yml +++ b/docs/_data/sidebars/pmd_sidebar.yml @@ -79,7 +79,7 @@ entries: url: /pmd_rules_java.html output: web, pdf - title: JavaScript Rules - url: /pmd_rules_javascript.html + url: /pmd_rules_ecmascript.html output: web, pdf - title: JSP Rules url: /pmd_rules_jsp.html @@ -87,12 +87,18 @@ entries: - title: PLSQL Rules url: /pmd_rules_plsql.html output: web, pdf + - title: VisualForce Rules + url: /pmd_rules_vf.html + output: web, pdf - title: Apache Velocity Rules url: /pmd_rules_vm.html output: web, pdf - - title: XML and XSL Rules + - title: XML Rules url: /pmd_rules_xml.html output: web, pdf + - title: XSL Rules + url: /pmd_rules_xsl.html + output: web, pdf - title: Language Specific Documentation output: web, pdf folderitems: diff --git a/docs/pages/pmd/rules/apex.md b/docs/pages/pmd/rules/apex.md index a3210e3c0..69a09cb34 100644 --- a/docs/pages/pmd/rules/apex.md +++ b/docs/pages/pmd/rules/apex.md @@ -1,43 +1,60 @@ --- title: Apex Rules -tags: [languages] -summary: PMD Apex Rules -sidebar: pmd_sidebar permalink: pmd_rules_apex.html -last_updated: July 3, 2016 folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [ApexUnit](pmd_rules_apex_apexunit.html): These rules deal with different problems that can occur with Apex unit tests. +* [Braces](pmd_rules_apex_braces.html): The Braces ruleset contains rules regarding the use and placement of braces. +* [Complexity](pmd_rules_apex_complexity.html): The Complexity ruleset contains rules that find problems related to code size or complexity. +* [Performance](pmd_rules_apex_performance.html): The Performance ruleset contains a collection of good practices which should be followed. +* [Security](pmd_rules_apex_security.html): These rules deal with different security problems that can occur within Apex. +* [Style](pmd_rules_apex_style.html): The Style Ruleset contains rules regarding preferred usage of names and identifiers. + +## ApexUnit +* [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_apexunit.html#apexunittestclassshouldhaveasserts): Apex unit tests should include at least one assertion. This makes the tests more robust, and usi... +* [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_apexunit.html#apexunittestshouldnotuseseealldatatrue): Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database... + +## Braces +* [IfStmtsMustUseBraces](pmd_rules_apex_braces.html#ifstmtsmustusebraces): Avoid using if statements without using braces to surround the code block. If the codeformatting ... +* [WhileLoopsMustUseBraces](pmd_rules_apex_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using braces to surround the code block. If the codeformat... +* [IfElseStmtsMustUseBraces](pmd_rules_apex_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formattingor indent... +* [ForLoopsMustUseBraces](pmd_rules_apex_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using surrounding braces. If the code formatting orindentati... + +## Complexity +* [AvoidDeeplyNestedIfStmts](pmd_rules_apex_complexity.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... +* [ExcessiveParameterList](pmd_rules_apex_complexity.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... +* [ExcessiveClassLength](pmd_rules_apex_complexity.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [NcssMethodCount](pmd_rules_apex_complexity.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NcssTypeCount](pmd_rules_apex_complexity.html#ncsstypecount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NcssConstructorCount](pmd_rules_apex_complexity.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [StdCyclomaticComplexity](pmd_rules_apex_complexity.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [TooManyFields](pmd_rules_apex_complexity.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... +* [ExcessivePublicCount](pmd_rules_apex_complexity.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... + +## Performance +* [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops): New objects created within loops should be checked to see if they can created outside them and re... +* [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops): Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch ... + +## Security +* [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations): Detect classes declared without explicit sharing mode if DML methods are used. Thisforces the dev... +* [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect): Checks against redirects to user-controlled locations. This prevents attackers fromredirecting us... +* [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint): Checks against accessing endpoints under plain http. You should always usehttps for security. +* [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam): Makes sure that all values obtained from URL parameters are properly escaped / sanitizedto avoid ... +* [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse): Reports on calls to 'addError' with disabled escaping. The message passed to 'addError'will be di... +* [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto): The rule makes sure you are using randomly generated IVs and keys for 'Crypto' calls.Hard-wiring ... +* [ApexCSRF](pmd_rules_apex_security.html#apexcsrf): Check to avoid making DML operations in Apex class constructor/init method. This preventsmodifica... +* [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection): Detects the usage of untrusted / unescaped variables in DML queries. +* [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation): The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation.Since... +* [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods): Checks against calling dangerous methods.For the time being, it reports: Against 'FinancialForce'... +* [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred): Detects hardcoded credentials used in requests to an endpoint.You should refrain from hardcoding ... + +## Style +* [VariableNamingConventions](pmd_rules_apex_style.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... +* [MethodNamingConventions](pmd_rules_apex_style.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. +* [ClassNamingConventions](pmd_rules_apex_style.html#classnamingconventions): Class names should always begin with an upper case character. +* [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_style.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. +* [AvoidLogicInTrigger](pmd_rules_apex_style.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... +* [AvoidGlobalModifier](pmd_rules_apex_style.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... -## PMD Has the Following Rules for Apex *(Salesforce)* - -### Performance - -| Rule | Description | -| --- | --- | -| AvoidSoqlInLoops | New objects created within loops should be checked to see if they can created outside them and reused. | -| AvoidDmlStatementsInLoops | Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. | - -### Complexity - -| Rule | Description | -| --- | --- | -| AvoidDeeplyNestedIfStmts | Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. | -| ExcessiveParameterList | Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. | -| ExcessiveClassLength | Excessive class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. | -| NcssMethodCount | This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. | -| NcssTypeCount | This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. | -| NcssConstructorCount | This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. | -| StdCyclomaticComplexity | Complexity directly affects maintenance costs is determined by the number of decision points in a method plus one for the method entry. The decision points include ‘if’, ‘while’, ‘for’, and ‘case labels’ calls. Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. | -| TooManyFields | Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, possibly through grouping related fields in new objects. For example, a class with individual city/state/zip fields could park them within a single Address field. | -| ExcessivePublicCount | Classes with large numbers of public methods and attributes require disproportionate testing efforts since combinational side effects grow rapidly and increase risk. Refactoring these classes into smaller ones not only increases testability and reliability but also allows new variations to be developed easily. | - -### Style - -| Rule | Description | -| --- | --- | -| VariableNamingConventions | A variable naming conventions rule - customize this to your liking. Currently, it checks for final variables that should be fully capitalized and non-final variables that should not include underscores. | -| MethodNamingConventions | Method names should always begin with a lower case character, and should not contain underscores. | -| ClassNamingConventions | Class names should always begin with an upper case character. | -| MethodWithSameNameAsEnclosingClass | Non-constructor methods should not have the same name as the enclosing class. | -| AvoidLogicInTrigger | As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style. Therefore delegate the triggers work to a regular class (often called Trigger handler class). See more here: Trigger Frameworks and Apex Trigger Best Practices | -| AvoidGlobalModifier | Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. Many interfaces (e.g. Batch) required global modifiers in the past but don’t require this anymore. Don’t look yourself in. | diff --git a/docs/pages/pmd/rules/apex/apexunit.md b/docs/pages/pmd/rules/apex/apexunit.md new file mode 100644 index 000000000..ced790393 --- /dev/null +++ b/docs/pages/pmd/rules/apex/apexunit.md @@ -0,0 +1,69 @@ +--- +title: ApexUnit +summary: These rules deal with different problems that can occur with Apex unit tests. +permalink: pmd_rules_apex_apexunit.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/apexunit.xml +--- +## ApexUnitTestClassShouldHaveAsserts +**Since:** 5.5.1 + +**Priority:** Medium (3) + +Apex unit tests should include at least one assertion. This makes the tests more robust, and using assert + with messages provide the developer a clearer idea of what the test does. + +**Example(s):** +``` +@isTest +public class Foo { + public static testMethod void testSomething() { + Account a = null; + // This is better than having a NullPointerException + // System.assertNotEquals(a, null, 'account not found'); + a.toString(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexUnitTestShouldNotUseSeeAllDataTrue +**Since:** 5.5.1 + +**Priority:** Medium (3) + +Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests. + +**Example(s):** +``` +@isTest(seeAllData = true) +public class Foo { + public static testMethod void testSomething() { + Account a = null; + // This is better than having a NullPointerException + // System.assertNotEquals(a, null, 'account not found'); + a.toString(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + diff --git a/docs/pages/pmd/rules/apex/braces.md b/docs/pages/pmd/rules/apex/braces.md new file mode 100644 index 000000000..fd560383e --- /dev/null +++ b/docs/pages/pmd/rules/apex/braces.md @@ -0,0 +1,134 @@ +--- +title: Braces +summary: The Braces ruleset contains rules regarding the use and placement of braces. +permalink: pmd_rules_apex_braces.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/braces.xml +--- +## IfStmtsMustUseBraces +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. + +**Example(s):** +``` +if (foo) // not recommended + x++; + +if (foo) { // preferred approach + x++; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## WhileLoopsMustUseBraces +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid using 'while' statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. + +**Example(s):** +``` +while (true) // not recommended + x++; + +while (true) { // preferred approach + x++; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## IfElseStmtsMustUseBraces +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest. + +**Example(s):** +``` +// this is OK +if (foo) x++; + + // but this is not +if (foo) + x = x+1; + else + x = x-1; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ForLoopsMustUseBraces +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid using 'for' statements without using surrounding braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest. + +**Example(s):** +``` +for (int i = 0; i < 42; i++) // not recommended + foo(); + +for (int i = 0; i < 42; i++) { // preferred approach + foo(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + diff --git a/docs/pages/pmd/rules/apex/complexity.md b/docs/pages/pmd/rules/apex/complexity.md new file mode 100644 index 000000000..fd8dca388 --- /dev/null +++ b/docs/pages/pmd/rules/apex/complexity.md @@ -0,0 +1,365 @@ +--- +title: Complexity +summary: The Complexity ruleset contains rules that find problems related to code size or complexity. +permalink: pmd_rules_apex_complexity.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/complexity.xml +--- +## AvoidDeeplyNestedIfStmts +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. + +**Example(s):** +``` +public class Foo { + public void bar(Integer x, Integer y, Integer z) { + if (x>y) { + if (y>z) { + if (z==x) { + // !! too deep + } + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|problemDepth|3|The if statement depth reporting threshold| + +## ExcessiveParameterList +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. + +**Example(s):** +``` +// too many arguments liable to be mixed up +public void addPerson(int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { + ... +} +// preferred approach +public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { + ... +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + +## ExcessiveClassLength +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +public class Foo { + public void bar1() { + // 1000 lines of code + } + public void bar2() { + // 1000 lines of code + } + public void bar3() { + // 1000 lines of code + } + public void barN() { + // 1000 lines of code + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + +## NcssMethodCount +**Since:** 5.5.0 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +public class Foo extends Bar { + //this method only has 1 NCSS lines + public Integer methd() { + super.methd(); + + + + return 1; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + +## NcssTypeCount +**Since:** 5.5.0 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +//this class only has 6 NCSS lines +public class Foo extends Bar { + public Foo() { + super(); + + + + + + super.foo(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + +## NcssConstructorCount +**Since:** 5.5.0 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +public class Foo extends Bar { + //this constructor only has 1 NCSS lines + public Foo() { + super(); + + + + + super.foo(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + +## StdCyclomaticComplexity +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. + +**Example(s):** +``` +// This has a Cyclomatic Complexity = 12 + public class Foo { +1 public void example() { +2 if (a == b || (c == d && e == f)) { +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else { + switch (z) { +9 case 1: + fiddle(); + break; +10 case 2: + fiddle(); + break; +11 case 3: + fiddle(); + break; +12 default: + fiddle(); + break; + } + } + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## TooManyFields +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field. + +**Example(s):** +``` +public class Person { + // too many separate fields + int birthYear; + int birthMonth; + int birthDate; + float height; + float weight; +} + +public class Person { + // this is more manageable + Date birthDate; + BodyMeasurements measurements; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|maxfields|15|Max allowable fields| + +## ExcessivePublicCount +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily. + +**Example(s):** +``` +public class Foo { + public String value; + public Bar something; + public Variable var; + // [... more more public attributes ...] + + public void doWork() {} + public void doMoreWork() {} + public void doWorkAgain() {} + // [... more more public methods ...] +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md new file mode 100644 index 000000000..d58eaf941 --- /dev/null +++ b/docs/pages/pmd/rules/apex/performance.md @@ -0,0 +1,66 @@ +--- +title: Performance +summary: The Performance ruleset contains a collection of good practices which should be followed. +permalink: pmd_rules_apex_performance.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/performance.xml +--- +## AvoidSoqlInLoops +**Since:** 5.5.0 + +**Priority:** Medium (3) + +New objects created within loops should be checked to see if they can created outside them and reused. + +**Example(s):** +``` +public class Something { + public static void main( String as[] ) { + for (Integer i = 0; i < 10; i++) { + List accounts = [SELECT Id FROM Account]; + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## AvoidDmlStatementsInLoops +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. + +**Example(s):** +``` +public class Something { + public void foo() { + for (Integer i = 0; i < 151; i++) { + Account account; + ... + insert account; + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md new file mode 100644 index 000000000..f7928661c --- /dev/null +++ b/docs/pages/pmd/rules/apex/security.md @@ -0,0 +1,336 @@ +--- +title: Security +summary: These rules deal with different security problems that can occur within Apex. +permalink: pmd_rules_apex_security.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/security.xml +--- +## ApexSharingViolations +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Detect classes declared without explicit sharing mode if DML methods are used. This +forces the developer to take access restrictions into account before modifying objects. + +**Example(s):** +``` +public without sharing class Foo { +// DML operation here +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexOpenRedirect +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Checks against redirects to user-controlled locations. This prevents attackers from +redirecting users to phishing sites. + +**Example(s):** +``` +public without sharing class Foo { + String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param'); + PageReference page() { + return new PageReference(unsafeLocation); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexInsecureEndpoint +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Checks against accessing endpoints under plain **http**. You should always use +**https** for security. + +**Example(s):** +``` +public without sharing class Foo { + void foo() { + HttpRequest req = new HttpRequest(); + req.setEndpoint('http://localhost:com'); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexXSSFromURLParam +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Makes sure that all values obtained from URL parameters are properly escaped / sanitized +to avoid XSS attacks. + +**Example(s):** +``` +public without sharing class Foo { + String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param'); + String usedLater = unescapedstring; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexXSSFromEscapeFalse +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Reports on calls to `addError` with disabled escaping. The message passed to `addError` +will be displayed directly to the user in the UI, making it prime ground for XSS +attacks if unescaped. + +**Example(s):** +``` +public without sharing class Foo { + Trigger.new[0].addError(vulnerableHTMLGoesHere, false); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexBadCrypto +**Since:** 5.5.3 + +**Priority:** Medium (3) + +The rule makes sure you are using randomly generated IVs and keys for `Crypto` calls. +Hard-wiring these values greatly compromises the security of encrypted data. + +**Example(s):** +``` +public without sharing class Foo { + Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123'); + Blob hardCodedKey = Blob.valueOf('0000000000000000'); + Blob data = Blob.valueOf('Data to be encrypted'); + Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexCSRF +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Check to avoid making DML operations in Apex class constructor/init method. This prevents +modification of the database just by accessing a page. + +**Example(s):** +``` +public class Foo { + public init() { + insert data; + } + + public Foo() { + insert data; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexSOQLInjection +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Detects the usage of untrusted / unescaped variables in DML queries. + +**Example(s):** +``` +public class Foo { + public void test1(String t1) { + Database.query('SELECT Id FROM Account' + t1); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexCRUDViolation +**Since:** 5.5.3 + +**Priority:** Medium (3) + +The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. +Since Apex runs in system mode not having proper permissions checks results in escalation of +privilege and may produce runtime errors. This check forces you to handle such scenarios. + +**Example(s):** +``` +public class Foo { + public Contact foo(String status, String ID) { + Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID]; + + // Make sure we can update the database before even trying + if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) { + return null; + } + + c.Status__c = status; + update c; + return c; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexDangerousMethods +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Checks against calling dangerous methods. + +For the time being, it reports: + +* Against `FinancialForce`'s `Configuration.disableTriggerCRUDSecurity()`. Disabling CRUD security +opens the door to several attacks and requires manual validation, which is unreliable. +* Calling `System.debug` passing sensitive data as parameter, which could lead to exposure +of private data. + +**Example(s):** +``` +public class Foo { + public Foo() { + Configuration.disableTriggerCRUDSecurity(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ApexSuggestUsingNamedCred +**Since:** 5.5.3 + +**Priority:** Medium (3) + +Detects hardcoded credentials used in requests to an endpoint. + +You should refrain from hardcoding credentials: + * They are hard to mantain by being mixed in application code + * Particularly hard to update them when used from different classes + * Granting a developer access to the codebase means granting knowledge + of credentials, keeping a two-level access is not possible. + * Using different credentials for different environments is troublesome + and error-prone. + +Instead, you should use *Named Credentials* and a callout endpoint. + +For more information, you can check [this](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials.htm) + +**Example(s):** +``` +public class Foo { + public void foo(String username, String password) { + Blob headerValue = Blob.valueOf(username + ':' + password); + String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); + req.setHeader('Authorization', authorizationHeader); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + diff --git a/docs/pages/pmd/rules/apex/style.md b/docs/pages/pmd/rules/apex/style.md new file mode 100644 index 000000000..409f3284e --- /dev/null +++ b/docs/pages/pmd/rules/apex/style.md @@ -0,0 +1,185 @@ +--- +title: Style +summary: The Style Ruleset contains rules regarding preferred usage of names and identifiers. +permalink: pmd_rules_apex_style.html +folder: pmd/rules/apex +sidebaractiveurl: /pmd_rules_apex.html +editmepath: ../pmd-apex/src/main/resources/rulesets/apex/style.xml +--- +## VariableNamingConventions +**Since:** 5.5.0 + +**Priority:** High (1) + +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores. + +**Example(s):** +``` +public class Foo { + public static final Integer MY_NUM = 0; + public String myTest = ''; + DataModule dmTest = new DataModule(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|parameterSuffix|[]|Method parameter variable suffixes| +|parameterPrefix|[]|Method parameter variable prefixes| +|localSuffix|[]|Local variable suffixes| +|localPrefix|[]|Local variable prefixes| +|memberSuffix|[]|Member variable suffixes| +|memberPrefix|[]|Member variable prefixes| +|staticSuffix|[]|Static variable suffixes| +|staticPrefix|[]|Static variable prefixes| +|checkParameters|true|Check constructor and method parameter variables| +|checkLocals|true|Check local variables| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|checkMembers|true|Check member variables| + +## MethodNamingConventions +**Since:** 5.5.0 + +**Priority:** High (1) + +Method names should always begin with a lower case character, and should not contain underscores. + +**Example(s):** +``` +public class Foo { + public void fooStuff() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## ClassNamingConventions +**Since:** 5.5.0 + +**Priority:** High (1) + +Class names should always begin with an upper case character. + +**Example(s):** +``` +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## MethodWithSameNameAsEnclosingClass +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Non-constructor methods should not have the same name as the enclosing class. + +**Example(s):** +``` +public class MyClass { + // this is OK because it is a constructor + public MyClass() {} + // this is bad because it is a method + public void MyClass() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## AvoidLogicInTrigger +**Since:** 5.5.0 + +**Priority:** Medium (3) + +As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style. +Therefore delegate the triggers work to a regular class (often called Trigger handler class). + +See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices + +**Example(s):** +``` +trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { + for(Account acc : Trigger.new) { + if(Trigger.isInsert) { + ... + } + + ... + + if(Trigger.isDelete) { + ... + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + +## AvoidGlobalModifier +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. +Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in. + +**Example(s):** +``` +global class Unchangeable { + global UndeletableType unchangable(UndeletableType param) { + // ... + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| + diff --git a/docs/pages/pmd/rules/ecmascript.md b/docs/pages/pmd/rules/ecmascript.md new file mode 100644 index 000000000..ae2fa9c98 --- /dev/null +++ b/docs/pages/pmd/rules/ecmascript.md @@ -0,0 +1,33 @@ +--- +title: Ecmascript Rules +permalink: pmd_rules_ecmascript.html +folder: pmd/rules +--- +List of rulesets and rules contained in each ruleset. + +* [Basic Ecmascript](pmd_rules_ecmascript_basic.html): Rules concerning basic ECMAScript guidelines. +* [Braces](pmd_rules_ecmascript_braces.html): The Braces Ruleset contains a collection of braces rules. +* [Unnecessary](pmd_rules_ecmascript_unnecessary.html): The Unnecessary Ruleset contains a collection of rules for unnecessary code. + +## Basic Ecmascript +* [AssignmentInOperand](pmd_rules_ecmascript_basic.html#assignmentinoperand): Avoid assignments in operands; this can make code more complicated and harder to read. This is s... +* [UnreachableCode](pmd_rules_ecmascript_basic.html#unreachablecode): A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements a... +* [InnaccurateNumericLiteral](pmd_rules_ecmascript_basic.html#innaccuratenumericliteral): The numeric literal will have at different value at runtime, which can happen if you provide too ... +* [ConsistentReturn](pmd_rules_ecmascript_basic.html#consistentreturn): ECMAScript does provide for return types on functions, and therefore there is no solid rule as to... +* [ScopeForInVariable](pmd_rules_ecmascript_basic.html#scopeforinvariable): A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the... +* [EqualComparison](pmd_rules_ecmascript_basic.html#equalcomparison): Using == in condition may lead to unexpected results, as the variables are automatically casted t... +* [GlobalVariable](pmd_rules_ecmascript_basic.html#globalvariable): This rule helps to avoid using accidently global variables by simply missing the "var" declaratio... +* [AvoidTrailingComma](pmd_rules_ecmascript_basic.html#avoidtrailingcomma): This rule helps improve code portability due to differences in browser treatment of trailing comm... +* [UseBaseWithParseInt](pmd_rules_ecmascript_basic.html#usebasewithparseint): TODO + +## Braces +* [IfStmtsMustUseBraces](pmd_rules_ecmascript_braces.html#ifstmtsmustusebraces): Avoid using if statements without using curly braces. +* [IfElseStmtsMustUseBraces](pmd_rules_ecmascript_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using curly braces. +* [WhileLoopsMustUseBraces](pmd_rules_ecmascript_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using curly braces. +* [ForLoopsMustUseBraces](pmd_rules_ecmascript_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. + +## Unnecessary +* [UnnecessaryParentheses](pmd_rules_ecmascript_unnecessary.html#unnecessaryparentheses): Unnecessary parentheses should be removed. +* [UnnecessaryBlock](pmd_rules_ecmascript_unnecessary.html#unnecessaryblock): An unnecessary Block is present. Such Blocks are often used in other languages to introduce a... +* [NoElseReturn](pmd_rules_ecmascript_unnecessary.html#noelsereturn): The else block in a if-else-construct is unnecessary if the 'if' block contains a return. Then... + diff --git a/docs/pages/pmd/rules/ecmascript/basic.md b/docs/pages/pmd/rules/ecmascript/basic.md new file mode 100644 index 000000000..b62e0e0c1 --- /dev/null +++ b/docs/pages/pmd/rules/ecmascript/basic.md @@ -0,0 +1,307 @@ +--- +title: Basic Ecmascript +summary: Rules concerning basic ECMAScript guidelines. +permalink: pmd_rules_ecmascript_basic.html +folder: pmd/rules/ecmascript +sidebaractiveurl: /pmd_rules_ecmascript.html +editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/basic.xml +--- +## AssignmentInOperand +**Since:** 5.0 + +**Priority:** Medium High (2) + +Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime +indicative of the bug where the assignment operator '=' was used instead of the equality operator '=='. + +**Example(s):** +``` +var x = 2; +// Bad +if ((x = getX()) == 3) { + alert('3!'); +} + +function getX() { + return 3; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|allowIf|false|Allow assignment within the conditional expression of an if statement| +|allowFor|false|Allow assignment within the conditional expression of a for statement| +|allowWhile|false|Allow assignment within the conditional expression of a while statement| +|allowTernary|false|Allow assignment within the conditional expression of a ternary operator| +|allowTernaryResults|false|Allow assignment within the result expressions of a ternary operator| +|allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| + +## UnreachableCode +**Since:** 5.0 + +**Priority:** High (1) + +A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these +will never execute. This is a bug, or extremely poor style. + +**Example(s):** +``` +// Ok +function foo() { + return 1; +} +// Bad +function bar() { + var x = 1; + return x; + x = 2; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## InnaccurateNumericLiteral +**Since:** 5.0 + +**Priority:** Medium High (2) + +The numeric literal will have at different value at runtime, which can happen if you provide too much +precision in a floating point number. This may result in numeric calculations being in error. + +**Example(s):** +``` +var a = 9; // Ok +var b = 999999999999999; // Ok +var c = 999999999999999999999; // Not good +var w = 1.12e-4; // Ok +var x = 1.12; // Ok +var y = 1.1234567890123; // Ok +var z = 1.12345678901234567; // Not good +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ConsistentReturn +**Since:** 5.0 + +**Priority:** Medium High (2) + +ECMAScript does provide for return types on functions, and therefore there is no solid rule as to their usage. +However, when a function does use returns they should all have a value, or all with no value. Mixed return +usage is likely a bug, or at best poor style. + +**Example(s):** +``` +// Ok +function foo() { + if (condition1) { + return true; + } + return false; +} + +// Bad +function bar() { + if (condition1) { + return; + } + return false; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|rhinoLanguageVersion|VERSION_DEFAULT|Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.| +|recordingLocalJsDocComments|true|Specifies that JsDoc comments are produced in the AST.| +|recordingComments|true|Specifies that comments are produced in the AST.| + +## ScopeForInVariable +**Since:** 5.0 + +**Priority:** High (1) + +A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the 'var' keyword can +refer to a variable in an enclosing scope outside the nearest enclosing scope. This will overwrite the +existing value of the variable in the outer scope when the body of the for-in is evaluated. When the for-in loop +has finished, the variable will contain the last value used in the for-in, and the original value from before +the for-in loop will be gone. Since the for-in variable name is most likely intended to be a temporary name, it +is better to explicitly scope the variable name to the nearest enclosing scope with 'var'. + +**Example(s):** +``` +// Ok +function foo() { + var p = 'clean'; + function() { + var obj = { dirty: 'dirty' }; + for (var p in obj) { // Use 'var' here. + obj[p] = obj[p]; + } + return x; + }(); + + // 'p' still has value of 'clean'. +} +// Bad +function bar() { + var p = 'clean'; + function() { + var obj = { dirty: 'dirty' }; + for (p in obj) { // Oh no, missing 'var' here! + obj[p] = obj[p]; + } + return x; + }(); + + // 'p' is trashed and has value of 'dirty'! +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EqualComparison +**Since:** 5.0 + +**Priority:** Medium (3) + +Using == in condition may lead to unexpected results, as the variables are automatically casted to be of the + same type. The === operator avoids the casting. + +**Example(s):** +``` +// Ok +if (someVar === true) { + ... +} +// Ok +if (someVar !== 3) { + ... +} +// Bad +if (someVar == true) { + ... +} +// Bad +if (someVar != 3) { + ... +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## GlobalVariable +**Since:** 5.0 + +**Priority:** High (1) + +This rule helps to avoid using accidently global variables by simply missing the "var" declaration. +Global variables can lead to side-effects that are hard to debug. + +**Example(s):** +``` +function(arg) { + notDeclaredVariable = 1; // this will create a global variable and trigger the rule + + var someVar = 1; // this is a local variable, that's ok + + window.otherGlobal = 2; // this will not trigger the rule, although it is a global variable. +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidTrailingComma +**Since:** 5.1 + +**Priority:** High (1) + +This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. + +**Example(s):** +``` +function(arg) { + var obj1 = { a : 1 }; // Ok + var arr1 = [ 1, 2 ]; // Ok + + var obj2 = { a : 1, }; // Syntax error in some browsers! + var arr2 = [ 1, 2, ]; // Length 2 or 3 depending on the browser! +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|allowObjectLiteral|false|Allow a trailing comma within an object literal| +|allowArrayLiteral|false|Allow a trailing comma within an array literal| + +## UseBaseWithParseInt +**Since:** 5.0.1 + +**Priority:** High (1) + +TODO + +**Example(s):** +``` +parseInt("10",base); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/ecmascript/braces.md b/docs/pages/pmd/rules/ecmascript/braces.md new file mode 100644 index 000000000..37246da17 --- /dev/null +++ b/docs/pages/pmd/rules/ecmascript/braces.md @@ -0,0 +1,124 @@ +--- +title: Braces +summary: The Braces Ruleset contains a collection of braces rules. +permalink: pmd_rules_ecmascript_braces.html +folder: pmd/rules/ecmascript +sidebaractiveurl: /pmd_rules_ecmascript.html +editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/braces.xml +--- +## IfStmtsMustUseBraces +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using if statements without using curly braces. + +**Example(s):** +``` +// Ok +if (foo) { + x++; +} + +// Bad +if (foo) + x++; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## IfElseStmtsMustUseBraces +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using if..else statements without using curly braces. + +**Example(s):** +``` +// Ok +if (foo) { + x++; +} else { + y++; +} + +// Bad +if (foo) + x++; +else + y++; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## WhileLoopsMustUseBraces +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using 'while' statements without using curly braces. + +**Example(s):** +``` +// Ok +while (true) { + x++; +} + +// Bad +while (true) + x++; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ForLoopsMustUseBraces +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using 'for' statements without using curly braces. + +**Example(s):** +``` +// Ok +for (var i = 0; i < 42; i++) { + foo(); +} + +// Bad +for (var i = 0; i < 42; i++) + foo(); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/ecmascript/unnecessary.md b/docs/pages/pmd/rules/ecmascript/unnecessary.md new file mode 100644 index 000000000..84bfdd4be --- /dev/null +++ b/docs/pages/pmd/rules/ecmascript/unnecessary.md @@ -0,0 +1,96 @@ +--- +title: Unnecessary +summary: The Unnecessary Ruleset contains a collection of rules for unnecessary code. +permalink: pmd_rules_ecmascript_unnecessary.html +folder: pmd/rules/ecmascript +sidebaractiveurl: /pmd_rules_ecmascript.html +editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/unnecessary.xml +--- +## UnnecessaryParentheses +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Unnecessary parentheses should be removed. + +**Example(s):** +``` +var x = 1; // Ok +var y = (1 + 1); // Ok +var z = ((1 + 1)); // Bad +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnnecessaryBlock +**Since:** 5.0 + +**Priority:** Medium (3) + +An unnecessary Block is present. Such Blocks are often used in other languages to + introduce a new variable scope. Blocks do not behave like this in ECMAScipt, and using them can + be misleading. Considering removing this unnecessary Block. + +**Example(s):** +``` +if (foo) { + // Ok +} +if (bar) { + { + // Bad + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoElseReturn +**Since:** 5.5.0 + +**Priority:** Medium (3) + +The else block in a if-else-construct is unnecessary if the `if` block contains a return. + Then the content of the else block can be put outside. + + See also: http://eslint.org/docs/rules/no-else-return + +**Example(s):** +``` +// Bad: +if (x) { + return y; +} else { + return z; +} + +// Good: +if (x) { + return y; +} +return z; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index 8a8e7b489..cfc556a67 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -1,6 +1,365 @@ --- title: Java Rules -sidebar: pmd_sidebar permalink: pmd_rules_java.html folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [Android](pmd_rules_java_android.html): These rules deal with the Android SDK, mostly related to best practices. To get better results, make sure that the auxclasspath is defined for type resolution to work. +* [Basic](pmd_rules_java_basic.html): The Basic ruleset contains a collection of good practices which should be followed. +* [Braces](pmd_rules_java_braces.html): The Braces ruleset contains rules regarding the use and placement of braces. +* [Clone Implementation](pmd_rules_java_clone.html): The Clone Implementation ruleset contains a collection of rules that find questionable usages of the clone() method. +* [Code Size](pmd_rules_java_codesize.html): The Code Size ruleset contains rules that find problems related to code size or complexity. +* [Comments](pmd_rules_java_comments.html): Rules intended to catch errors related to code comments +* [Controversial](pmd_rules_java_controversial.html): The Controversial ruleset contains rules that, for whatever reason, are considered controversial. They are held here to allow people to include them as they see fit within their custom rulesets. +* [Coupling](pmd_rules_java_coupling.html): Rules which find instances of high or inappropriate coupling between objects and packages. +* [Design](pmd_rules_java_design.html): The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches are suggested. +* [Empty Code](pmd_rules_java_empty.html): The Empty Code ruleset contains rules that find empty statements of any kind (empty method, empty block statement, empty try or catch block,...). +* [Finalizer](pmd_rules_java_finalizers.html): These rules deal with different problems that can occur with finalizers. +* [Import Statements](pmd_rules_java_imports.html): These rules deal with different problems that can occur with import statements. +* [J2EE](pmd_rules_java_j2ee.html): Rules specific to the use of J2EE implementations. +* [Jakarta Commons Logging](pmd_rules_java_logging-jakarta-commons.html): The Jakarta Commons Logging ruleset contains a collection of rules that find questionable usages of that framework. +* [Java Logging](pmd_rules_java_logging-java.html): The Java Logging ruleset contains a collection of rules that find questionable usages of the logger. +* [JavaBeans](pmd_rules_java_javabeans.html): The JavaBeans Ruleset catches instances of bean rules not being followed. +* [JUnit](pmd_rules_java_junit.html): These rules deal with different problems that can occur with JUnit tests. +* [Migration](pmd_rules_java_migrating.html): Contains rules about migrating from one JDK version to another. Don't use these rules directly, rather, use a wrapper ruleset such as migrating_to_13.xml. +* [Naming](pmd_rules_java_naming.html): The Naming Ruleset contains rules regarding preferred usage of names and identifiers. +* [Optimization](pmd_rules_java_optimizations.html): These rules deal with different optimizations that generally apply to best practices. +* [Security Code Guidelines](pmd_rules_java_sunsecure.html): These rules check the security guidelines from Sun, published at http://java.sun.com/security/seccodeguide.html#gcg +* [Strict Exceptions](pmd_rules_java_strictexception.html): These rules provide some strict guidelines about throwing and catching exceptions. +* [String and StringBuffer](pmd_rules_java_strings.html): These rules deal with different issues that can arise with manipulation of the String, StringBuffer, or StringBuilder instances. +* [Unnecessary](pmd_rules_java_unnecessary.html): The Unnecessary Ruleset contains a collection of rules for unnecessary code. +* [Unused Code](pmd_rules_java_unusedcode.html): The Unused Code ruleset contains rules that find unused or ineffective code. + +## Android +* [CallSuperFirst](pmd_rules_java_android.html#callsuperfirst): Super should be called at the start of the method +* [CallSuperLast](pmd_rules_java_android.html#callsuperlast): Super should be called at the end of the method +* [DoNotHardCodeSDCard](pmd_rules_java_android.html#donothardcodesdcard): Use Environment.getExternalStorageDirectory() instead of "/sdcard" + +## Basic +* [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +* [ForLoopShouldBeWhileLoop](pmd_rules_java_basic.html#forloopshouldbewhileloop): Some for loops can be simplified to while loops, this makes them more concise. +* [OverrideBothEqualsAndHashcode](pmd_rules_java_basic.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... +* [DoubleCheckedLocking](pmd_rules_java_basic.html#doublecheckedlocking): Partially created objects can be returned by the Double Checked Locking pattern when used in Java... +* [ReturnFromFinallyBlock](pmd_rules_java_basic.html#returnfromfinallyblock): Avoid returning from a finally block, this can discard exceptions. +* [UnconditionalIfStatement](pmd_rules_java_basic.html#unconditionalifstatement): Do not use "if" statements whose conditionals are always true or always false. +* [BooleanInstantiation](pmd_rules_java_basic.html#booleaninstantiation): Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boole... +* [CollapsibleIfStatements](pmd_rules_java_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... +* [ClassCastExceptionWithToArray](pmd_rules_java_basic.html#classcastexceptionwithtoarray): When deriving an array of a specific class from your Collection, one should provide an array ofth... +* [AvoidDecimalLiteralsInBigDecimalConstructor](pmd_rules_java_basic.html#avoiddecimalliteralsinbigdecimalconstructor): One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actu... +* [MisplacedNullCheck](pmd_rules_java_basic.html#misplacednullcheck): The null check here is misplaced. If the variable is null a NullPointerException will be thrown.E... +* [AvoidThreadGroup](pmd_rules_java_basic.html#avoidthreadgroup): Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environmentit... +* [BrokenNullCheck](pmd_rules_java_basic.html#brokennullcheck): The null check is broken since it will throw a NullPointerException itself.It is likely that you ... +* [BigIntegerInstantiation](pmd_rules_java_basic.html#bigintegerinstantiation): Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) andfor Ja... +* [AvoidUsingOctalValues](pmd_rules_java_basic.html#avoidusingoctalvalues): Integer literals should not start with zero since this denotes that the rest of literal will bein... +* [AvoidUsingHardCodedIP](pmd_rules_java_basic.html#avoidusinghardcodedip): Application with hard-coded IP addresses can become impossible to deploy in some cases.Externaliz... +* [CheckResultSet](pmd_rules_java_basic.html#checkresultset): Always check the return values of navigation methods (next, previous, first, last) of a ResultSet... +* [AvoidMultipleUnaryOperators](pmd_rules_java_basic.html#avoidmultipleunaryoperators): The use of multiple unary operators may be problematic, and/or confusing.Ensure that the intended... +* [ExtendsObject](pmd_rules_java_basic.html#extendsobject): No need to explicitly extend Object. +* [CheckSkipResult](pmd_rules_java_basic.html#checkskipresult): The skip() method may skip a smaller number of bytes than requested. Check the returned value to ... +* [AvoidBranchingStatementAsLastInLoop](pmd_rules_java_basic.html#avoidbranchingstatementaslastinloop): Using a branching statement as the last part of a loop may be a bug, and/or is confusing.Ensure t... +* [DontCallThreadRun](pmd_rules_java_basic.html#dontcallthreadrun): Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, ... +* [DontUseFloatTypeForLoopIndices](pmd_rules_java_basic.html#dontusefloattypeforloopindices): Don't use floating point for loop indices. If you must use floating point, use doubleunless you'r... +* [SimplifiedTernary](pmd_rules_java_basic.html#simplifiedternary): Look for ternary operators with the form 'condition ? literalBoolean : foo'or 'condition ? foo : ... + +## Braces +* [IfStmtsMustUseBraces](pmd_rules_java_braces.html#ifstmtsmustusebraces): Avoid using if statements without using braces to surround the code block. If the code formatting... +* [WhileLoopsMustUseBraces](pmd_rules_java_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using braces to surround the code block. If the code forma... +* [IfElseStmtsMustUseBraces](pmd_rules_java_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formatting or inden... +* [ForLoopsMustUseBraces](pmd_rules_java_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. If the code formatting or indentation is... + +## Clone Implementation +* [ProperCloneImplementation](pmd_rules_java_clone.html#propercloneimplementation): Object clone() should be implemented with super.clone(). +* [CloneThrowsCloneNotSupportedException](pmd_rules_java_clone.html#clonethrowsclonenotsupportedexception): The method clone() should throw a CloneNotSupportedException. +* [CloneMethodMustImplementCloneable](pmd_rules_java_clone.html#clonemethodmustimplementcloneable): The method clone() should only be implemented if the class implements the Cloneable interface wit... +* [CloneMethodReturnTypeMustMatchClassName](pmd_rules_java_clone.html#clonemethodreturntypemustmatchclassname): If a class implements cloneable the return type of the method clone() must be the class name. Tha... +* [CloneMethodMustBePublic](pmd_rules_java_clone.html#clonemethodmustbepublic): The java Manual says "By convention, classes that implement this interface should overrideObject.... + +## Code Size +* [NPathComplexity](pmd_rules_java_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [ExcessiveMethodLength](pmd_rules_java_codesize.html#excessivemethodlength): When methods are excessively long this usually indicates that the method is doing more than itsna... +* [ExcessiveParameterList](pmd_rules_java_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... +* [ExcessiveClassLength](pmd_rules_java_codesize.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [CyclomaticComplexity](pmd_rules_java_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [StdCyclomaticComplexity](pmd_rules_java_codesize.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [ModifiedCyclomaticComplexity](pmd_rules_java_codesize.html#modifiedcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [ExcessivePublicCount](pmd_rules_java_codesize.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... +* [TooManyFields](pmd_rules_java_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... +* [NcssMethodCount](pmd_rules_java_codesize.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NcssTypeCount](pmd_rules_java_codesize.html#ncsstypecount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NcssConstructorCount](pmd_rules_java_codesize.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [TooManyMethods](pmd_rules_java_codesize.html#toomanymethods): A class with too many methods is probably a good suspect for refactoring, in order to reduce its ... + +## Comments +* [CommentRequired](pmd_rules_java_comments.html#commentrequired): Denotes whether comments are required (or unwanted) for specific language elements. +* [CommentSize](pmd_rules_java_comments.html#commentsize): Determines whether the dimensions of non-header comments found are within the specified limits. +* [CommentContent](pmd_rules_java_comments.html#commentcontent): A rule for the politically correct... we don't want to offend anyone. +* [CommentDefaultAccessModifier](pmd_rules_java_comments.html#commentdefaultaccessmodifier): To avoid mistakes if we want that a Method, Field or Nested class have a default access modifier ... + +## Controversial +* [UnnecessaryConstructor](pmd_rules_java_controversial.html#unnecessaryconstructor): This rule detects when a constructor is not necessary; i.e., when there is only one constructor,i... +* [NullAssignment](pmd_rules_java_controversial.html#nullassignment): Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, th... +* [OnlyOneReturn](pmd_rules_java_controversial.html#onlyonereturn): A method should have only one exit point, and that should be the last statement in the method. +* [AssignmentInOperand](pmd_rules_java_controversial.html#assignmentinoperand): Avoid assignments in operands; this can make code more complicated and harder to read. +* [AtLeastOneConstructor](pmd_rules_java_controversial.html#atleastoneconstructor): Each class should declare at least one constructor. +* [DontImportSun](pmd_rules_java_controversial.html#dontimportsun): Avoid importing anything from the 'sun.' packages. These packages are not portable and are likel... +* [SuspiciousOctalEscape](pmd_rules_java_controversial.html#suspiciousoctalescape): A suspicious octal escape sequence was found inside a String literal.The Java language specificat... +* [CallSuperInConstructor](pmd_rules_java_controversial.html#callsuperinconstructor): It is a good practice to call super() in a constructor. If super() is not called butanother const... +* [UnnecessaryParentheses](pmd_rules_java_controversial.html#unnecessaryparentheses): Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. +* [DefaultPackage](pmd_rules_java_controversial.html#defaultpackage): Use explicit scoping instead of accidental usage of default package private level.The rule allows... +* [DataflowAnomalyAnalysis](pmd_rules_java_controversial.html#dataflowanomalyanalysis): The dataflow analysis tracks local definitions, undefinitions and references to variables on diff... +* [AvoidFinalLocalVariable](pmd_rules_java_controversial.html#avoidfinallocalvariable): Avoid using final local variables, turn them into fields. +* [AvoidUsingShortType](pmd_rules_java_controversial.html#avoidusingshorttype): Java uses the 'short' type to reduce memory usage, not to optimize calculation. In fact, the JVM ... +* [AvoidUsingVolatile](pmd_rules_java_controversial.html#avoidusingvolatile): Use of the keyword 'volatile' is generally used to fine tune a Java application, and therefore, r... +* [AvoidUsingNativeCode](pmd_rules_java_controversial.html#avoidusingnativecode): Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portabilit... +* [AvoidAccessibilityAlteration](pmd_rules_java_controversial.html#avoidaccessibilityalteration): Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(),as... +* [DoNotCallGarbageCollectionExplicitly](pmd_rules_java_controversial.html#donotcallgarbagecollectionexplicitly): Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Co... +* [OneDeclarationPerLine](pmd_rules_java_controversial.html#onedeclarationperline): Java allows the use of several variables declaration of the same type on one line. However, itcan... +* [AvoidPrefixingMethodParameters](pmd_rules_java_controversial.html#avoidprefixingmethodparameters): Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readab... +* [AvoidLiteralsInIfCondition](pmd_rules_java_controversial.html#avoidliteralsinifcondition): Avoid using hard-coded literals in conditional statements. By declaring them as static variableso... +* [UseObjectForClearerAPI](pmd_rules_java_controversial.html#useobjectforclearerapi): When you write a public method, you should be thinking in terms of an API. If your method is publ... +* [UseConcurrentHashMap](pmd_rules_java_controversial.html#useconcurrenthashmap): Since Java5 brought a new implementation of the Map designed for multi-threaded access, you canpe... + +## Coupling +* [CouplingBetweenObjects](pmd_rules_java_coupling.html#couplingbetweenobjects): This rule counts the number of unique attributes, local variables, and return types within an obj... +* [ExcessiveImports](pmd_rules_java_coupling.html#excessiveimports): A high number of imports can indicate a high degree of coupling within an object. This rule count... +* [LooseCoupling](pmd_rules_java_coupling.html#loosecoupling): The use of implementation types as object references limits your ability to use alternateimplemen... +* [LoosePackageCoupling](pmd_rules_java_coupling.html#loosepackagecoupling): Avoid using classes from the configured package hierarchy outside of the package hierarchy, excep... +* [LawOfDemeter](pmd_rules_java_coupling.html#lawofdemeter): The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce couplin... + +## Design +* [UseUtilityClass](pmd_rules_java_design.html#useutilityclass): For classes that only have static methods, consider making them utility classes.Note that this do... +* [SimplifyBooleanReturns](pmd_rules_java_design.html#simplifybooleanreturns): Avoid unnecessary if-then-else statements when returning a boolean. The result ofthe conditional ... +* [SimplifyBooleanExpressions](pmd_rules_java_design.html#simplifybooleanexpressions): Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. +* [SwitchStmtsShouldHaveDefault](pmd_rules_java_design.html#switchstmtsshouldhavedefault): All switch statements should include a default option to catch any unspecified values. +* [AvoidDeeplyNestedIfStmts](pmd_rules_java_design.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... +* [AvoidReassigningParameters](pmd_rules_java_design.html#avoidreassigningparameters): Reassigning values to incoming parameters is not recommended. Use temporary local variables inst... +* [SwitchDensity](pmd_rules_java_design.html#switchdensity): A high ratio of statements to labels in a switch statement implies that the switch statementis ov... +* [ConstructorCallsOverridableMethod](pmd_rules_java_design.html#constructorcallsoverridablemethod): Calling overridable methods during construction poses a risk of invoking methods on an incomplete... +* [AccessorClassGeneration](pmd_rules_java_design.html#accessorclassgeneration): Instantiation by way of private constructors from outside of the constructor's class often causes... +* [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic): If a final field is assigned to a compile-time constant, it could be made static, thus saving ove... +* [CloseResource](pmd_rules_java_design.html#closeresource): Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after... +* [NonStaticInitializer](pmd_rules_java_design.html#nonstaticinitializer): A non-static initializer block will be called any time a constructor is invoked (just prior toinv... +* [DefaultLabelNotLastInSwitchStmt](pmd_rules_java_design.html#defaultlabelnotlastinswitchstmt): By convention, the default label should be the last label in a switch statement. +* [NonCaseLabelInSwitchStatement](pmd_rules_java_design.html#noncaselabelinswitchstatement): A non-case label (e.g. a named break/continue label) was present in a switch statement.This legal... +* [OptimizableToArrayCall](pmd_rules_java_design.html#optimizabletoarraycall): Calls to a collection's toArray() method should specify target arrays sized to match the size of ... +* [BadComparison](pmd_rules_java_design.html#badcomparison): Avoid equality comparisons with Double.NaN. Due to the implicit lack of representationprecision w... +* [EqualsNull](pmd_rules_java_design.html#equalsnull): Tests for null should not use the equals() method. The '==' operator should be used instead. +* [ConfusingTernary](pmd_rules_java_design.html#confusingternary): Avoid negation within an "if" expression with an "else" clause. For example, rephrase: if (x !=... +* [InstantiationToGetClass](pmd_rules_java_design.html#instantiationtogetclass): Avoid instantiating an object just to call getClass() on it; use the .class public member instead. +* [IdempotentOperations](pmd_rules_java_design.html#idempotentoperations): Avoid idempotent operations - they have no effect. +* [SimpleDateFormatNeedsLocale](pmd_rules_java_design.html#simpledateformatneedslocale): Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-approp... +* [ImmutableField](pmd_rules_java_design.html#immutablefield): Identifies private fields whose values never change once they are initialized either in the decla... +* [UseLocaleWithCaseConversions](pmd_rules_java_design.html#uselocalewithcaseconversions): When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with la... +* [AvoidProtectedFieldInFinalClass](pmd_rules_java_design.html#avoidprotectedfieldinfinalclass): Do not use protected fields in final classes since they cannot be subclassed.Clarify your intent ... +* [AssignmentToNonFinalStatic](pmd_rules_java_design.html#assignmenttononfinalstatic): Identifies a possible unsafe usage of a static field. +* [MissingStaticMethodInNonInstantiatableClass](pmd_rules_java_design.html#missingstaticmethodinnoninstantiatableclass): A class that has private constructors and does not have any static methods or fields cannot be used. +* [AvoidSynchronizedAtMethodLevel](pmd_rules_java_design.html#avoidsynchronizedatmethodlevel): Method-level synchronization can cause problems when new code is added to the method.Block-level ... +* [MissingBreakInSwitch](pmd_rules_java_design.html#missingbreakinswitch): Switch statements without break or return statements for each case optionmay indicate problematic... +* [UseNotifyAllInsteadOfNotify](pmd_rules_java_design.html#usenotifyallinsteadofnotify): Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, th... +* [AvoidInstanceofChecksInCatchClause](pmd_rules_java_design.html#avoidinstanceofchecksincatchclause): Each caught exception type should be handled in its own catch clause. +* [AbstractClassWithoutAbstractMethod](pmd_rules_java_design.html#abstractclasswithoutabstractmethod): The abstract class does not contain any abstract methods. An abstract class suggestsan incomplete... +* [SimplifyConditional](pmd_rules_java_design.html#simplifyconditional): No need to check for null before an instanceof; the instanceof keyword returns false when given a... +* [CompareObjectsWithEquals](pmd_rules_java_design.html#compareobjectswithequals): Use equals() to compare object references; avoid comparing them with ==. +* [PositionLiteralsFirstInComparisons](pmd_rules_java_design.html#positionliteralsfirstincomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... +* [PositionLiteralsFirstInCaseInsensitiveComparisons](pmd_rules_java_design.html#positionliteralsfirstincaseinsensitivecomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... +* [UnnecessaryLocalBeforeReturn](pmd_rules_java_design.html#unnecessarylocalbeforereturn): Avoid the creation of unnecessary local variables +* [NonThreadSafeSingleton](pmd_rules_java_design.html#nonthreadsafesingleton): Non-thread safe singletons can result in bad state changes. Eliminatestatic singletons if possibl... +* [SingleMethodSingleton](pmd_rules_java_design.html#singlemethodsingleton): Some classes contain overloaded getInstance. The problem with overloaded getInstance methodsis th... +* [SingletonClassReturningNewInstance](pmd_rules_java_design.html#singletonclassreturningnewinstance): Some classes contain overloaded getInstance. The problem with overloaded getInstance methodsis th... +* [UncommentedEmptyMethodBody](pmd_rules_java_design.html#uncommentedemptymethodbody): Uncommented Empty Method Body finds instances where a method body does not containstatements, but... +* [UncommentedEmptyConstructor](pmd_rules_java_design.html#uncommentedemptyconstructor): Uncommented Empty Constructor finds instances where a constructor does notcontain statements, but... +* [UnsynchronizedStaticDateFormatter](pmd_rules_java_design.html#unsynchronizedstaticdateformatter): SimpleDateFormat instances are not synchronized. Sun recommends using separate format instancesfo... +* [PreserveStackTrace](pmd_rules_java_design.html#preservestacktrace): Throwing a new exception from a catch block without passing the original exception into thenew ex... +* [UseCollectionIsEmpty](pmd_rules_java_design.html#usecollectionisempty): The isEmpty() method on java.util.Collection is provided to determine if a collection has any ele... +* [ClassWithOnlyPrivateConstructorsShouldBeFinal](pmd_rules_java_design.html#classwithonlyprivateconstructorsshouldbefinal): A class with only private constructors should be final, unless the private constructoris invoked ... +* [EmptyMethodInAbstractClassShouldBeAbstract](pmd_rules_java_design.html#emptymethodinabstractclassshouldbeabstract): Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to ... +* [SingularField](pmd_rules_java_design.html#singularfield): Fields whose scopes are limited to just single methods do not rely on the containingobject to pro... +* [ReturnEmptyArrayRatherThanNull](pmd_rules_java_design.html#returnemptyarrayratherthannull): For any method that returns an array, it is a better to return an empty array rather than anull r... +* [AbstractClassWithoutAnyMethod](pmd_rules_java_design.html#abstractclasswithoutanymethod): If an abstract class does not provides any methods, it may be acting as a simple data containerth... +* [TooFewBranchesForASwitchStatement](pmd_rules_java_design.html#toofewbranchesforaswitchstatement): Switch statements are indended to be used to support complex branching behaviour. Using a switch ... +* [LogicInversion](pmd_rules_java_design.html#logicinversion): Use opposite operator instead of negating the whole expression with a logic complement operator. +* [UseVarargs](pmd_rules_java_design.html#usevarargs): Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic... +* [FieldDeclarationsShouldBeAtStartOfClass](pmd_rules_java_design.html#fielddeclarationsshouldbeatstartofclass): Fields should be declared at the top of the class, before any method declarations, constructors, ... +* [GodClass](pmd_rules_java_design.html#godclass): The God Class rule detects the God Class design flaw using metrics. God classes do too many thing... +* [AvoidProtectedMethodInFinalClassNotExtending](pmd_rules_java_design.html#avoidprotectedmethodinfinalclassnotextending): Do not use protected methods in most final classes since they cannot be subclassed. This shouldon... +* [ConstantsInInterface](pmd_rules_java_design.html#constantsininterface): Avoid constants in interfaces. Interfaces should define types, constants are implementation detai... +* [AccessorMethodGeneration](pmd_rules_java_design.html#accessormethodgeneration): When accessing a private field / method from another class, the Java compiler will generate a acc... + +## Empty Code +* [EmptyCatchBlock](pmd_rules_java_empty.html#emptycatchblock): Empty Catch Block finds instances where an exception is caught, but nothing is done. In most cir... +* [EmptyIfStmt](pmd_rules_java_empty.html#emptyifstmt): Empty If Statement finds instances where a condition is checked but nothing is done about it. +* [EmptyWhileStmt](pmd_rules_java_empty.html#emptywhilestmt): Empty While Statement finds all instances where a while statement does nothing. If it is a timin... +* [EmptyTryBlock](pmd_rules_java_empty.html#emptytryblock): Avoid empty try blocks - what's the point? +* [EmptyFinallyBlock](pmd_rules_java_empty.html#emptyfinallyblock): Empty finally blocks serve no purpose and should be removed. +* [EmptySwitchStatements](pmd_rules_java_empty.html#emptyswitchstatements): Empty switch statements serve no purpose and should be removed. +* [EmptySynchronizedBlock](pmd_rules_java_empty.html#emptysynchronizedblock): Empty synchronized blocks serve no purpose and should be removed. +* [EmptyStatementNotInLoop](pmd_rules_java_empty.html#emptystatementnotinloop): An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' or 'wh... +* [EmptyInitializer](pmd_rules_java_empty.html#emptyinitializer): Empty initializers serve no purpose and should be removed. +* [EmptyStatementBlock](pmd_rules_java_empty.html#emptystatementblock): Empty block statements serve no purpose and should be removed. +* [EmptyStaticInitializer](pmd_rules_java_empty.html#emptystaticinitializer): An empty static initializer serve no purpose and should be removed. + +## Finalizer +* [EmptyFinalizer](pmd_rules_java_finalizers.html#emptyfinalizer): Empty finalize methods serve no purpose and should be removed. +* [FinalizeOnlyCallsSuperFinalize](pmd_rules_java_finalizers.html#finalizeonlycallssuperfinalize): If the finalize() is implemented, it should do something besides just calling super.finalize(). +* [FinalizeOverloaded](pmd_rules_java_finalizers.html#finalizeoverloaded): Methods named finalize() should not have parameters. It is confusing and most likely an attempt ... +* [FinalizeDoesNotCallSuperFinalize](pmd_rules_java_finalizers.html#finalizedoesnotcallsuperfinalize): If the finalize() is implemented, its last action should be to call super.finalize. +* [FinalizeShouldBeProtected](pmd_rules_java_finalizers.html#finalizeshouldbeprotected): When overriding the finalize(), the new method should be set as protected. If made public, other... +* [AvoidCallingFinalize](pmd_rules_java_finalizers.html#avoidcallingfinalize): The method Object.finalize() is called by the garbage collector on an object when garbage collect... + +## Import Statements +* [DuplicateImports](pmd_rules_java_imports.html#duplicateimports): Duplicate or overlapping import statements should be avoided. +* [DontImportJavaLang](pmd_rules_java_imports.html#dontimportjavalang): Avoid importing anything from the package 'java.lang'. These classes are automatically imported ... +* [UnusedImports](pmd_rules_java_imports.html#unusedimports): Avoid the use of unused import statements to prevent unwanted dependencies. +* [ImportFromSamePackage](pmd_rules_java_imports.html#importfromsamepackage): There is no need to import a type that lives in the same package. +* [TooManyStaticImports](pmd_rules_java_imports.html#toomanystaticimports): If you overuse the static import feature, it can make your program unreadable and unmaintainable,... +* [UnnecessaryFullyQualifiedName](pmd_rules_java_imports.html#unnecessaryfullyqualifiedname): Import statements allow the use of non-fully qualified names. The use of a fully qualified namew... + +## J2EE +* [UseProperClassLoader](pmd_rules_java_j2ee.html#useproperclassloader): In J2EE, the getClassLoader() method might not work as expected. Use Thread.currentThread().getCo... +* [MDBAndSessionBeanNamingConvention](pmd_rules_java_j2ee.html#mdbandsessionbeannamingconvention): The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. +* [RemoteSessionInterfaceNamingConvention](pmd_rules_java_j2ee.html#remotesessioninterfacenamingconvention): A Remote Home interface type of a Session EJB should be suffixed by 'Home'. +* [LocalInterfaceSessionNamingConvention](pmd_rules_java_j2ee.html#localinterfacesessionnamingconvention): The Local Interface of a Session EJB should be suffixed by 'Local'. +* [LocalHomeNamingConvention](pmd_rules_java_j2ee.html#localhomenamingconvention): The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. +* [RemoteInterfaceNamingConvention](pmd_rules_java_j2ee.html#remoteinterfacenamingconvention): Remote Interface of a Session EJB should not have a suffix. +* [DoNotCallSystemExit](pmd_rules_java_j2ee.html#donotcallsystemexit): Web applications should not call System.exit(), since only the web container or theapplication se... +* [StaticEJBFieldShouldBeFinal](pmd_rules_java_j2ee.html#staticejbfieldshouldbefinal): According to the J2EE specification, an EJB should not have any static fieldswith write access. H... +* [DoNotUseThreads](pmd_rules_java_j2ee.html#donotusethreads): The J2EE specification explicitly forbids the use of threads. + +## Jakarta Commons Logging +* [UseCorrectExceptionLogging](pmd_rules_java_logging-jakarta-commons.html#usecorrectexceptionlogging): To make sure the full stacktrace is printed out, use the logging statement with two arguments: a ... +* [ProperLogger](pmd_rules_java_logging-jakarta-commons.html#properlogger): A logger should normally be defined private static final and be associated with the correct class... +* [GuardDebugLogging](pmd_rules_java_logging-jakarta-commons.html#guarddebuglogging): When log messages are composed by concatenating strings, the whole section should be guarded ... +* [GuardLogStatement](pmd_rules_java_logging-jakarta-commons.html#guardlogstatement): Whenever using a log level, one should check if the loglevel is actually enabled, orotherwise ski... + +## Java Logging +* [MoreThanOneLogger](pmd_rules_java_logging-java.html#morethanonelogger): Normally only one logger is used in each class. +* [LoggerIsNotStaticFinal](pmd_rules_java_logging-java.html#loggerisnotstaticfinal): In most cases, the Logger reference can be declared as static and final. +* [SystemPrintln](pmd_rules_java_logging-java.html#systemprintln): References to System.(out\|err).print are usually intended for debugging purposes and can remain ... +* [AvoidPrintStackTrace](pmd_rules_java_logging-java.html#avoidprintstacktrace): Avoid printStackTrace(); use a logger call instead. +* [GuardLogStatementJavaUtil](pmd_rules_java_logging-java.html#guardlogstatementjavautil): Whenever using a log level, one should check if the loglevel is actually enabled, orotherwise ski... +* [InvalidSlf4jMessageFormat](pmd_rules_java_logging-java.html#invalidslf4jmessageformat): Check for messages in slf4j loggers with non matching number of arguments and placeholders. + +## JavaBeans +* [BeanMembersShouldSerialize](pmd_rules_java_javabeans.html#beanmembersshouldserialize): If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializab... +* [MissingSerialVersionUID](pmd_rules_java_javabeans.html#missingserialversionuid): Serializable classes should provide a serialVersionUID field. + +## JUnit +* [JUnitStaticSuite](pmd_rules_java_junit.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static. +* [JUnitSpelling](pmd_rules_java_junit.html#junitspelling): Some JUnit framework methods are easy to misspell. +* [JUnitAssertionsShouldIncludeMessage](pmd_rules_java_junit.html#junitassertionsshouldincludemessage): JUnit assertions should include an informative message - i.e., use the three-argument version of ... +* [JUnitTestsShouldIncludeAssert](pmd_rules_java_junit.html#junittestsshouldincludeassert): JUnit tests should include at least one assertion. This makes the tests more robust, and using a... +* [TestClassWithoutTestCases](pmd_rules_java_junit.html#testclasswithouttestcases): Test classes end with the suffix Test. Having a non-test class with that name is not a good pract... +* [UnnecessaryBooleanAssertion](pmd_rules_java_junit.html#unnecessarybooleanassertion): A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the... +* [UseAssertEqualsInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertequalsinsteadofasserttrue): This rule detects JUnit assertions in object equality. These assertions should be made by more sp... +* [UseAssertSameInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertsameinsteadofasserttrue): This rule detects JUnit assertions in object references equality. These assertions should be made... +* [UseAssertNullInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertnullinsteadofasserttrue): This rule detects JUnit assertions in object references equality. These assertions should be made... +* [SimplifyBooleanAssertion](pmd_rules_java_junit.html#simplifybooleanassertion): Avoid negation in an assertTrue or assertFalse test.For example, rephrase: assertTrue(!expr); ... +* [JUnitTestContainsTooManyAsserts](pmd_rules_java_junit.html#junittestcontainstoomanyasserts): JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, ... +* [UseAssertTrueInsteadOfAssertEquals](pmd_rules_java_junit.html#useasserttrueinsteadofassertequals): When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, ins... + +## Migration +* [ReplaceVectorWithList](pmd_rules_java_migrating.html#replacevectorwithlist): Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe oper... +* [ReplaceHashtableWithMap](pmd_rules_java_migrating.html#replacehashtablewithmap): Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. +* [ReplaceEnumerationWithIterator](pmd_rules_java_migrating.html#replaceenumerationwithiterator): Consider replacing Enumeration usages with the newer java.util.Iterator +* [AvoidEnumAsIdentifier](pmd_rules_java_migrating.html#avoidenumasidentifier): Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. +* [AvoidAssertAsIdentifier](pmd_rules_java_migrating.html#avoidassertasidentifier): Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. +* [IntegerInstantiation](pmd_rules_java_migrating.html#integerinstantiation): Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(... +* [ByteInstantiation](pmd_rules_java_migrating.html#byteinstantiation): Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf().It m... +* [ShortInstantiation](pmd_rules_java_migrating.html#shortinstantiation): Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf().It... +* [LongInstantiation](pmd_rules_java_migrating.html#longinstantiation): Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf().It m... +* [JUnit4TestShouldUseBeforeAnnotation](pmd_rules_java_migrating.html#junit4testshouldusebeforeannotation): In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUni... +* [JUnit4TestShouldUseAfterAnnotation](pmd_rules_java_migrating.html#junit4testshoulduseafterannotation): In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.... +* [JUnit4TestShouldUseTestAnnotation](pmd_rules_java_migrating.html#junit4testshouldusetestannotation): In JUnit 3, the framework executed all methods which started with the word test as a unit test. I... +* [JUnit4SuitesShouldUseSuiteAnnotation](pmd_rules_java_migrating.html#junit4suitesshouldusesuiteannotation): In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicatedthro... +* [JUnitUseExpected](pmd_rules_java_migrating.html#junituseexpected): In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. + +## Naming +* [ShortVariable](pmd_rules_java_naming.html#shortvariable): Fields, local variables, or parameter names that are very short are not helpful to the reader. +* [LongVariable](pmd_rules_java_naming.html#longvariable): Fields, formal arguments, or local variable names that are too long can make the code difficult t... +* [ShortMethodName](pmd_rules_java_naming.html#shortmethodname): Method names that are very short are not helpful to the reader. +* [VariableNamingConventions](pmd_rules_java_naming.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... +* [MethodNamingConventions](pmd_rules_java_naming.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. +* [ClassNamingConventions](pmd_rules_java_naming.html#classnamingconventions): Class names should always begin with an upper case character. +* [AbstractNaming](pmd_rules_java_naming.html#abstractnaming): Abstract classes should be named 'AbstractXXX'. +* [AvoidDollarSigns](pmd_rules_java_naming.html#avoiddollarsigns): Avoid using dollar signs in variable/method/class/interface names. +* [MethodWithSameNameAsEnclosingClass](pmd_rules_java_naming.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. +* [SuspiciousHashcodeMethodName](pmd_rules_java_naming.html#suspicioushashcodemethodname): The method name and return type are suspiciously close to hashCode(), which may denote an intenti... +* [SuspiciousConstantFieldName](pmd_rules_java_naming.html#suspiciousconstantfieldname): Field names using all uppercase characters - Sun's Java naming conventions indicating constants -... +* [SuspiciousEqualsMethodName](pmd_rules_java_naming.html#suspiciousequalsmethodname): The method name and parameter number are suspiciously close to equals(Object), which can denote a... +* [AvoidFieldNameMatchingTypeName](pmd_rules_java_naming.html#avoidfieldnamematchingtypename): It is somewhat confusing to have a field name matching the declaring class name.This probably mea... +* [AvoidFieldNameMatchingMethodName](pmd_rules_java_naming.html#avoidfieldnamematchingmethodname): It can be confusing to have a field name with the same name as a method. While this is permitted,... +* [NoPackage](pmd_rules_java_naming.html#nopackage): Detects when a class or interface does not have a package definition. +* [PackageCase](pmd_rules_java_naming.html#packagecase): Detects when a package definition contains uppercase characters. +* [MisleadingVariableName](pmd_rules_java_naming.html#misleadingvariablename): Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could b... +* [BooleanGetMethodName](pmd_rules_java_naming.html#booleangetmethodname): Methods that return boolean results should be named as predicate statements to denote this.I.e, '... +* [ShortClassName](pmd_rules_java_naming.html#shortclassname): Short Classnames with fewer than e.g. five characters are not recommended. +* [GenericsNaming](pmd_rules_java_naming.html#genericsnaming): Names for references to generic values should be limited to a single uppercase letter. + +## Optimization +* [LocalVariableCouldBeFinal](pmd_rules_java_optimizations.html#localvariablecouldbefinal): A local variable assigned only once can be declared final. +* [MethodArgumentCouldBeFinal](pmd_rules_java_optimizations.html#methodargumentcouldbefinal): A method argument that is never re-assigned within the method can be declared final. +* [AvoidInstantiatingObjectsInLoops](pmd_rules_java_optimizations.html#avoidinstantiatingobjectsinloops): New objects created within loops should be checked to see if they can created outside them and re... +* [UseArrayListInsteadOfVector](pmd_rules_java_optimizations.html#usearraylistinsteadofvector): ArrayList is a much better Collection implementation than Vector if thread-safe operation is not ... +* [SimplifyStartsWith](pmd_rules_java_optimizations.html#simplifystartswith): Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (st... +* [UseStringBufferForStringAppends](pmd_rules_java_optimizations.html#usestringbufferforstringappends): The use of the '+=' operator for appending strings causes the JVM to create and use an internal S... +* [UseArraysAsList](pmd_rules_java_optimizations.html#usearraysaslist): The java.util.Arrays class has a "asList" method that should be used when you want to create a ne... +* [AvoidArrayLoops](pmd_rules_java_optimizations.html#avoidarrayloops): Instead of manually copying data between two arrays, use the efficient System.arraycopy method in... +* [UnnecessaryWrapperObjectCreation](pmd_rules_java_optimizations.html#unnecessarywrapperobjectcreation): Most wrapper classes provide static conversion methods that avoid the need to create intermediate... +* [AddEmptyString](pmd_rules_java_optimizations.html#addemptystring): The conversion of literals to strings by concatenating them with empty strings is inefficient.It ... +* [RedundantFieldInitializer](pmd_rules_java_optimizations.html#redundantfieldinitializer): Java will initialize fields with known default values so any explicit initialization of those sam... +* [PrematureDeclaration](pmd_rules_java_optimizations.html#prematuredeclaration): Checks for variables that are defined before they might be used. A reference is deemed to be prem... + +## Security Code Guidelines +* [MethodReturnsInternalArray](pmd_rules_java_sunsecure.html#methodreturnsinternalarray): Exposing internal arrays to the caller violates object encapsulation since elements can be remove... +* [ArrayIsStoredDirectly](pmd_rules_java_sunsecure.html#arrayisstoreddirectly): Constructors and methods receiving arrays should clone objects and store the copy.This prevents f... + +## Strict Exceptions +* [AvoidCatchingThrowable](pmd_rules_java_strictexception.html#avoidcatchingthrowable): Catching Throwable errors is not recommended since its scope is very broad. It includes runtime i... +* [SignatureDeclareThrowsException](pmd_rules_java_strictexception.html#signaturedeclarethrowsexception): Methods that declare the generic Exception as a possible throwable are not very helpful since the... +* [ExceptionAsFlowControl](pmd_rules_java_strictexception.html#exceptionasflowcontrol): Using Exceptions as form of flow control is not recommended as they obscure true exceptions when ... +* [AvoidCatchingNPE](pmd_rules_java_strictexception.html#avoidcatchingnpe): Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide... +* [AvoidThrowingRawExceptionTypes](pmd_rules_java_strictexception.html#avoidthrowingrawexceptiontypes): Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable,Excep... +* [AvoidThrowingNullPointerException](pmd_rules_java_strictexception.html#avoidthrowingnullpointerexception): Avoid throwing NullPointerExceptions. These are confusing because most people will assume that th... +* [AvoidRethrowingException](pmd_rules_java_strictexception.html#avoidrethrowingexception): Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. +* [DoNotExtendJavaLangError](pmd_rules_java_strictexception.html#donotextendjavalangerror): Errors are system exceptions. Do not extend them. +* [DoNotThrowExceptionInFinally](pmd_rules_java_strictexception.html#donotthrowexceptioninfinally): Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions or... +* [AvoidThrowingNewInstanceOfSameException](pmd_rules_java_strictexception.html#avoidthrowingnewinstanceofsameexception): Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same typ... +* [AvoidCatchingGenericException](pmd_rules_java_strictexception.html#avoidcatchinggenericexception): Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in tr... +* [AvoidLosingExceptionInformation](pmd_rules_java_strictexception.html#avoidlosingexceptioninformation): Statements in a catch block that invoke accessors on the exception without using the informationo... + +## String and StringBuffer +* [AvoidDuplicateLiterals](pmd_rules_java_strings.html#avoidduplicateliterals): Code containing duplicate String literals can usually be improved by declaring the String as a co... +* [StringInstantiation](pmd_rules_java_strings.html#stringinstantiation): Avoid instantiating String objects; this is usually unnecessary since they are immutable and can ... +* [StringToString](pmd_rules_java_strings.html#stringtostring): Avoid calling toString() on objects already known to be string instances; this is unnecessary. +* [InefficientStringBuffering](pmd_rules_java_strings.html#inefficientstringbuffering): Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buf... +* [UnnecessaryCaseChange](pmd_rules_java_strings.html#unnecessarycasechange): Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() +* [UseStringBufferLength](pmd_rules_java_strings.html#usestringbufferlength): Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toStrin... +* [AppendCharacterWithChar](pmd_rules_java_strings.html#appendcharacterwithchar): Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. +* [ConsecutiveAppendsShouldReuse](pmd_rules_java_strings.html#consecutiveappendsshouldreuse): Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target obj... +* [ConsecutiveLiteralAppends](pmd_rules_java_strings.html#consecutiveliteralappends): Consecutively calling StringBuffer/StringBuilder.append with String literals +* [UseIndexOfChar](pmd_rules_java_strings.html#useindexofchar): Use String.indexOf(char) when checking for the index of a single character; it executes faster. +* [InefficientEmptyStringCheck](pmd_rules_java_strings.html#inefficientemptystringcheck): String.trim().length() is an inefficient way to check if a String is really empty, as itcreates a... +* [InsufficientStringBufferDeclaration](pmd_rules_java_strings.html#insufficientstringbufferdeclaration): Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times... +* [UselessStringValueOf](pmd_rules_java_strings.html#uselessstringvalueof): No need to call String.valueOf to append to a string; just use the valueOf() argument directly. +* [StringBufferInstantiationWithChar](pmd_rules_java_strings.html#stringbufferinstantiationwithchar): Individual character values provided as initialization arguments will be converted into integers.... +* [UseEqualsToCompareStrings](pmd_rules_java_strings.html#useequalstocomparestrings): Using '==' or '!=' to compare strings only works if intern version is used on both sides.Use the ... +* [AvoidStringBufferField](pmd_rules_java_strings.html#avoidstringbufferfield): StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ... + +## Unnecessary +* [UnnecessaryConversionTemporary](pmd_rules_java_unnecessary.html#unnecessaryconversiontemporary): Avoid the use temporary objects when converting primitives to Strings. Use the static conversion ... +* [UnnecessaryReturn](pmd_rules_java_unnecessary.html#unnecessaryreturn): Avoid the use of unnecessary return statements. +* [UnnecessaryFinalModifier](pmd_rules_java_unnecessary.html#unnecessaryfinalmodifier): When a class has the final modifier, all the methods are automatically final and do not need to b... +* [UselessOverridingMethod](pmd_rules_java_unnecessary.html#uselessoverridingmethod): The overriding method merely calls the same method defined in a superclass. +* [UselessOperationOnImmutable](pmd_rules_java_unnecessary.html#uselessoperationonimmutable): An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object it... +* [UnusedNullCheckInEquals](pmd_rules_java_unnecessary.html#unusednullcheckinequals): After checking an object reference for null, you should invoke equals() on that object rather tha... +* [UselessParentheses](pmd_rules_java_unnecessary.html#uselessparentheses): Useless parentheses should be removed. +* [UselessQualifiedThis](pmd_rules_java_unnecessary.html#uselessqualifiedthis): Look for qualified this usages in the same class. +* [UnnecessaryModifier](pmd_rules_java_unnecessary.html#unnecessarymodifier): Fields in interfaces and annotations are automatically 'public static final', and methods are 'pu... + +## Unused Code +* [UnusedPrivateField](pmd_rules_java_unusedcode.html#unusedprivatefield): Detects when a private field is declared and/or assigned a value, but not used. +* [UnusedLocalVariable](pmd_rules_java_unusedcode.html#unusedlocalvariable): Detects when a local variable is declared and/or assigned, but not used. +* [UnusedPrivateMethod](pmd_rules_java_unusedcode.html#unusedprivatemethod): Unused Private Method detects when a private method is declared but is unused. +* [UnusedFormalParameter](pmd_rules_java_unusedcode.html#unusedformalparameter): Avoid passing parameters to methods or constructors without actually referencing them in the meth... + diff --git a/docs/pages/pmd/rules/java/android.md b/docs/pages/pmd/rules/java/android.md new file mode 100644 index 000000000..b627bc026 --- /dev/null +++ b/docs/pages/pmd/rules/java/android.md @@ -0,0 +1,87 @@ +--- +title: Android +summary: These rules deal with the Android SDK, mostly related to best practices. To get better results, make sure that the auxclasspath is defined for type resolution to work. +permalink: pmd_rules_java_android.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/android.xml +--- +## CallSuperFirst +**Since:** 4.2.5 + +**Priority:** Medium (3) + +Super should be called at the start of the method + +**Example(s):** +``` +public class DummyActivity extends Activity { + public void onCreate(Bundle bundle) { + // missing call to super.onCreate(bundle) + foo(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CallSuperLast +**Since:** 4.2.5 + +**Priority:** Medium (3) + +Super should be called at the end of the method + +**Example(s):** +``` +public class DummyActivity extends Activity { + public void onPause() { + foo(); + // missing call to super.onPause() + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotHardCodeSDCard +**Since:** 4.2.6 + +**Priority:** Medium (3) + +Use Environment.getExternalStorageDirectory() instead of "/sdcard" + +**Example(s):** +``` +public class MyActivity extends Activity { + protected void foo() { + String storageLocation = "/sdcard/mypackage"; // hard-coded, poor approach + + storageLocation = Environment.getExternalStorageDirectory() + "/mypackage"; // preferred approach + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md new file mode 100644 index 000000000..a60e7139f --- /dev/null +++ b/docs/pages/pmd/rules/java/basic.md @@ -0,0 +1,734 @@ +--- +title: Basic +summary: The Basic ruleset contains a collection of good practices which should be followed. +permalink: pmd_rules_java_basic.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/basic.xml +--- +## JumbledIncrementer +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**Example(s):** +``` +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ForLoopShouldBeWhileLoop +**Since:** 1.02 + +**Priority:** Medium (3) + +Some for loops can be simplified to while loops, this makes them more concise. + +**Example(s):** +``` +public class Foo { + void bar() { + for (;true;) true; // No Init or Update part, may as well be: while (true) + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## OverrideBothEqualsAndHashcode +**Since:** 0.4 + +**Priority:** Medium (3) + +Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. + +**Example(s):** +``` +public class Bar { // poor, missing a hashcode() method + public boolean equals(Object o) { + // do some comparison + } +} + +public class Baz { // poor, missing an equals() method + public int hashCode() { + // return some hash value + } +} + +public class Foo { // perfect, both methods provided + public boolean equals(Object other) { + // do some comparison + } + public int hashCode() { + // return some hash value + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## DoubleCheckedLocking +**Since:** 1.04 + +**Priority:** High (1) + +Partially created objects can be returned by the Double Checked Locking pattern when used in Java. +An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the +reference points to. + +Note: With Java 5, you can make Double checked locking work, if you declare the variable to be `volatile`. + +For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html +or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html + +**Example(s):** +``` +public class Foo { + /*volatile */ Object baz = null; // fix for Java5 and later: volatile + Object bar() { + if (baz == null) { // baz may be non-null yet not fully created + synchronized(this) { + if (baz == null) { + baz = new Object(); + } + } + } + return baz; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ReturnFromFinallyBlock +**Since:** 1.05 + +**Priority:** Medium (3) + +Avoid returning from a finally block, this can discard exceptions. + +**Example(s):** +``` +public class Bar { + public String foo() { + try { + throw new Exception( "My Exception" ); + } catch (Exception e) { + throw e; + } finally { + return "A. O. K."; // return not recommended here + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnconditionalIfStatement +**Since:** 1.5 + +**Priority:** Medium (3) + +Do not use "if" statements whose conditionals are always true or always false. + +**Example(s):** +``` +public class Foo { + public void close() { + if (true) { // fixed conditional, not recommended + // ... + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## BooleanInstantiation +**Since:** 1.2 + +**Priority:** Medium High (2) + +Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. + +**Example(s):** +``` +Boolean bar = new Boolean("true"); // unnecessary creation, just reference Boolean.TRUE; +Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## CollapsibleIfStatements +**Since:** 3.1 + +**Priority:** Medium (3) + +Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. + +**Example(s):** +``` +void bar() { + if (x) { // original implementation + if (y) { + // do stuff + } + } +} + +void bar() { + if (x && y) { // optimized implementation + // do stuff + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ClassCastExceptionWithToArray +**Since:** 3.4 + +**Priority:** Medium (3) + +When deriving an array of a specific class from your Collection, one should provide an array of +the same class as the parameter of the toArray() method. Doing otherwise you will will result +in a ClassCastException. + +**Example(s):** +``` +Collection c = new ArrayList(); +Integer obj = new Integer(1); +c.add(obj); + + // this would trigger the rule (and throw a ClassCastException if executed) +Integer[] a = (Integer [])c.toArray(); + + // this is fine and will not trigger the rule +Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidDecimalLiteralsInBigDecimalConstructor +**Since:** 3.4 + +**Priority:** Medium (3) + +One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actually +equal to .1000000000000000055511151231257827021181583404541015625. +This is because 0.1 cannot be represented exactly as a double (or as a binary fraction of any finite +length). Thus, the long value that is being passed in to the constructor is not exactly equal to 0.1, +appearances notwithstanding. + +The (String) constructor, on the other hand, is perfectly predictable: 'new BigDecimal("0.1")' is +exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the +(String) constructor be used in preference to this one. + +**Example(s):** +``` +BigDecimal bd = new BigDecimal(1.123); // loss of precision, this would trigger the rule + +BigDecimal bd = new BigDecimal("1.123"); // preferred approach + +BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer values +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## MisplacedNullCheck +**Since:** 3.5 + +**Priority:** Medium (3) + +The null check here is misplaced. If the variable is null a NullPointerException will be thrown. +Either the check is useless (the variable will never be "null") or it is incorrect. + +**Example(s):** +``` +public class Foo { + void bar() { + if (a.equals(baz) && a != null) {} + } +} +``` + +``` +public class Foo { + void bar() { + if (a.equals(baz) || a == null) {} + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidThreadGroup +**Since:** 3.6 + +**Priority:** Medium (3) + +Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment +it contains methods that are not thread-safe. + +**Example(s):** +``` +public class Bar { + void buz() { + ThreadGroup tg = new ThreadGroup("My threadgroup") ; + tg = new ThreadGroup(tg, "my thread group"); + tg = Thread.currentThread().getThreadGroup(); + tg = System.getSecurityManager().getThreadGroup(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## BrokenNullCheck +**Since:** 3.8 + +**Priority:** Medium High (2) + +The null check is broken since it will throw a NullPointerException itself. +It is likely that you used || instead of && or vice versa. + +**Example(s):** +``` +public String bar(String string) { + // should be && + if (string!=null || !string.equals("")) + return string; + // should be || + if (string==null && string.equals("")) + return string; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## BigIntegerInstantiation +**Since:** 3.9 + +**Priority:** Medium (3) + +Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and +for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN) + +**Example(s):** +``` +BigInteger bi = new BigInteger(1); // reference BigInteger.ONE instead +BigInteger bi2 = new BigInteger("0"); // reference BigInteger.ZERO instead +BigInteger bi3 = new BigInteger(0.0); // reference BigInteger.ZERO instead +BigInteger bi4; +bi4 = new BigInteger(0); // reference BigInteger.ZERO instead +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidUsingOctalValues +**Since:** 3.9 + +**Priority:** Medium (3) + +Integer literals should not start with zero since this denotes that the rest of literal will be +interpreted as an octal value. + +**Example(s):** +``` +int i = 012; // set i with 10 not 12 +int j = 010; // set j with 8 not 10 +k = i * j; // set k with 80 not 120 +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|strict|false|Detect violations between 00 and 07| + +## AvoidUsingHardCodedIP +**Since:** 4.1 + +**Priority:** Medium (3) + +Application with hard-coded IP addresses can become impossible to deploy in some cases. +Externalizing IP adresses is preferable. + +**Example(s):** +``` +public class Foo { + private String ip = "127.0.0.1"; // not recommended +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkAddressTypes|[IPv4, IPv6, IPv4 mapped IPv6]|Check for IP address types.| +|pattern|^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$|Regular Expression| + +## CheckResultSet +**Since:** 4.1 + +**Priority:** Medium (3) + +Always check the return values of navigation methods (next, previous, first, last) of a ResultSet. +If the value return is 'false', it should be handled properly. + +**Example(s):** +``` +Statement stat = conn.createStatement(); +ResultSet rst = stat.executeQuery("SELECT name FROM person"); +rst.next(); // what if it returns false? bad form +String firstName = rst.getString(1); + +Statement stat = conn.createStatement(); +ResultSet rst = stat.executeQuery("SELECT name FROM person"); +if (rst.next()) { // result is properly examined and used + String firstName = rst.getString(1); + } else { + // handle missing data +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidMultipleUnaryOperators +**Since:** 4.2 + +**Priority:** Medium High (2) + +The use of multiple unary operators may be problematic, and/or confusing. +Ensure that the intended usage is not a bug, or consider simplifying the expression. + +**Example(s):** +``` +// These are typo bugs, or at best needlessly complex and confusing: +int i = - -1; +int j = + - +1; +int z = ~~2; +boolean b = !!true; +boolean c = !!!true; + +// These are better: +int i = 1; +int j = -1; +int z = 2; +boolean b = true; +boolean c = false; + +// And these just make your brain hurt: +int i = ~-2; +int j = -~7; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ExtendsObject +**Since:** 5.0 + +**Priority:** Medium Low (4) + +No need to explicitly extend Object. + +**Example(s):** +``` +public class Foo extends Object { // not required +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CheckSkipResult +**Since:** 5.0 + +**Priority:** Medium (3) + +The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not. + +**Example(s):** +``` +public class Foo { + + private FileInputStream _s = new FileInputStream("file"); + + public void skip(int n) throws IOException { + _s.skip(n); // You are not sure that exactly n bytes are skipped + } + + public void skipExactly(int n) throws IOException { + while (n != 0) { + long skipped = _s.skip(n); + if (skipped == 0) + throw new EOFException(); + n -= skipped; + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidBranchingStatementAsLastInLoop +**Since:** 5.0 + +**Priority:** Medium High (2) + +Using a branching statement as the last part of a loop may be a bug, and/or is confusing. +Ensure that the usage is not a bug, or consider using another approach. + +**Example(s):** +``` +// unusual use of branching statement in a loop +for (int i = 0; i < 10; i++) { + if (i*i <= 25) { + continue; + } + break; +} + + // this makes more sense... +for (int i = 0; i < 10; i++) { + if (i*i > 25) { + break; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkReturnLoopTypes|[for, do, while]|Check for return statements in loop types| +|checkContinueLoopTypes|[for, do, while]|Check for continue statements in loop types| +|checkBreakLoopTypes|[for, do, while]|Check for break statements in loop types| + +## DontCallThreadRun +**Since:** 4.3 + +**Priority:** Medium Low (4) + +Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior. + +**Example(s):** +``` +Thread t = new Thread(); +t.run(); // use t.start() instead +new Thread().run(); // same violation +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DontUseFloatTypeForLoopIndices +**Since:** 4.3 + +**Priority:** Medium (3) + +Don't use floating point for loop indices. If you must use floating point, use double +unless you're certain that float provides enough precision and you have a compelling +performance need (space or time). + +**Example(s):** +``` +public class Count { + public static void main(String[] args) { + final int START = 2000000000; + int count = 0; + for (float f = START; f < START + 50; f++) + count++; + //Prints 0 because (float) START == (float) (START + 50). + System.out.println(count); + //The termination test misbehaves due to floating point granularity. + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SimplifiedTernary +**Since:** 5.4.0 + +**Priority:** Medium (3) + +Look for ternary operators with the form `condition ? literalBoolean : foo` +or `condition ? foo : literalBoolean`. + +These expressions can be simplified respectively to +`condition || foo` when the literalBoolean is true +`!condition && foo` when the literalBoolean is false +or +`!condition || foo` when the literalBoolean is true +`condition && foo` when the literalBoolean is false + +**Example(s):** +``` +public class Foo { + public boolean test() { + return condition ? true : something(); // can be as simple as return condition || something(); + } + + public void test2() { + final boolean value = condition ? false : something(); // can be as simple as value = !condition && something(); + } + + public boolean test3() { + return condition ? something() : true; // can be as simple as return !condition || something(); + } + + public void test4() { + final boolean otherValue = condition ? something() : false; // can be as simple as condition && something(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/braces.md b/docs/pages/pmd/rules/java/braces.md new file mode 100644 index 000000000..e4e7b8656 --- /dev/null +++ b/docs/pages/pmd/rules/java/braces.md @@ -0,0 +1,118 @@ +--- +title: Braces +summary: The Braces ruleset contains rules regarding the use and placement of braces. +permalink: pmd_rules_java_braces.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/braces.xml +--- +## IfStmtsMustUseBraces +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. + +**Example(s):** +``` +if (foo) // not recommended + x++; + +if (foo) { // preferred approach + x++; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## WhileLoopsMustUseBraces +**Since:** 0.7 + +**Priority:** Medium (3) + +Avoid using 'while' statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. + +**Example(s):** +``` +while (true) // not recommended + x++; + +while (true) { // preferred approach + x++; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## IfElseStmtsMustUseBraces +**Since:** 0.2 + +**Priority:** Medium (3) + +Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest. + +**Example(s):** +``` +// this is OK +if (foo) x++; + + // but this is not +if (foo) + x = x+1; + else + x = x-1; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ForLoopsMustUseBraces +**Since:** 0.7 + +**Priority:** Medium (3) + +Avoid using 'for' statements without using curly braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest. + +**Example(s):** +``` +for (int i = 0; i < 42; i++) + foo(); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md new file mode 100644 index 000000000..afb2348ed --- /dev/null +++ b/docs/pages/pmd/rules/java/clone.md @@ -0,0 +1,155 @@ +--- +title: Clone Implementation +summary: The Clone Implementation ruleset contains a collection of rules that find questionable usages of the clone() method. +permalink: pmd_rules_java_clone.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/clone.xml +--- +## ProperCloneImplementation +**Since:** 1.4 + +**Priority:** Medium High (2) + +Object clone() should be implemented with super.clone(). + +**Example(s):** +``` +class Foo{ + public Object clone(){ + return new Foo(); // This is bad + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CloneThrowsCloneNotSupportedException +**Since:** 1.9 + +**Priority:** Medium (3) + +The method clone() should throw a CloneNotSupportedException. + +**Example(s):** +``` +public class MyClass implements Cloneable{ + public Object clone() { // will cause an error + MyClass clone = (MyClass)super.clone(); + return clone; + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CloneMethodMustImplementCloneable +**Since:** 1.9 + +**Priority:** Medium (3) + +The method clone() should only be implemented if the class implements the Cloneable interface with the exception of a final method that only throws CloneNotSupportedException. + +**Example(s):** +``` +public class MyClass { + public Object clone() throws CloneNotSupportedException { + return foo; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CloneMethodReturnTypeMustMatchClassName +**Since:** 5.4.0 + +**Priority:** Medium (3) + +If a class implements cloneable the return type of the method clone() must be the class name. That way, the caller +of the clone method doesn't need to cast the returned clone to the correct type. + +Note: This is only possible with Java 1.5 or higher. + +**Example(s):** +``` +public class Foo implements Cloneable { + @Override + protected Object clone() { // Violation, Object must be Foo + } +} + +public class Foo implements Cloneable { + @Override + public Foo clone() { //Ok + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CloneMethodMustBePublic +**Since:** 5.4.0 + +**Priority:** Medium (3) + +The java Manual says "By convention, classes that implement this interface should override +Object.clone (which is protected) with a public method." + +**Example(s):** +``` +public class Foo implements Cloneable { + @Override + protected Object clone() throws CloneNotSupportedException { // Violation, must be public + } +} + +public class Foo implements Cloneable { + @Override + protected Foo clone() { // Violation, must be public + } +} + +public class Foo implements Cloneable { + @Override + public Object clone() // Ok +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md new file mode 100644 index 000000000..169b2115a --- /dev/null +++ b/docs/pages/pmd/rules/java/codesize.md @@ -0,0 +1,532 @@ +--- +title: Code Size +summary: The Code Size ruleset contains rules that find problems related to code size or complexity. +permalink: pmd_rules_java_codesize.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/codesize.xml +--- +## NPathComplexity +**Since:** 3.9 + +**Priority:** Medium (3) + +The NPath complexity of a method is the number of acyclic execution paths through that method. +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability. + +**Example(s):** +``` +void bar() { // this is something more complex than it needs to be, + if (y) { // it should be broken down into smaller methods or functions + for (j = 0; j < m; j++) { + if (j > r) { + doSomething(); + while (f < 5 ) { + anotherThing(); + f -= 27; + } + } else { + tryThis(); + } + } + } + if ( r - n > 45) { + while (doMagic()) { + findRabbits(); + } + } + try { + doSomethingDangerous(); + } catch (Exception ex) { + makeAmends(); + } finally { + dontDoItAgain(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveMethodLength +**Since:** 0.6 + +**Priority:** Medium (3) + +When methods are excessively long this usually indicates that the method is doing more than its +name/signature might suggest. They also become challenging for others to digest since excessive +scrolling causes readers to lose focus. +Try to reduce the method length by creating helper methods and removing any copy/pasted code. + +**Example(s):** +``` +public void doSomething() { + System.out.println("Hello world!"); + System.out.println("Hello world!"); + // 98 copies omitted for brevity. +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveParameterList +**Since:** 0.9 + +**Priority:** Medium (3) + +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. + +**Example(s):** +``` +public void addPerson( // too many arguments liable to be mixed up + int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { + + . . . . +} + +public void addPerson( // preferred approach + Date birthdate, BodyMeasurements measurements, int ssn) { + + . . . . +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveClassLength +**Since:** 0.6 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +public class Foo { + public void bar1() { + // 1000 lines of code + } + public void bar2() { + // 1000 lines of code + } + public void bar3() { + // 1000 lines of code + } + + + public void barN() { + // 1000 lines of code + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## CyclomaticComplexity +**Since:** 1.03 + +**Priority:** Medium (3) + +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. + +**Example(s):** +``` +public class Foo { // This has a Cyclomatic Complexity = 12 +1 public void example() { +2 if (a == b) { +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else{ + switch (z) { +9 case 1: + fiddle(); + break; +10 case 2: + fiddle(); + break; +11 case 3: + fiddle(); + break; +12 default: + fiddle(); + break; + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## StdCyclomaticComplexity +**Since:** 5.1.2 + +**Priority:** Medium (3) + +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. + +**Example(s):** +``` +public class Foo { // This has a Cyclomatic Complexity = 12 +1 public void example() { +2 if (a == b || (c == d && e == f)) { // Only one +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else{ + switch (z) { +9 case 1: + fiddle(); + break; +10 case 2: + fiddle(); + break; +11 case 3: + fiddle(); + break; +12 default: + fiddle(); + break; + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## ModifiedCyclomaticComplexity +**Since:** 5.1.2 + +**Priority:** Medium (3) + +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. Modified complexity treats switch statements as a single +decision point. + +**Example(s):** +``` +public class Foo { // This has a Cyclomatic Complexity = 9 +1 public void example() { +2 if (a == b) { +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else{ +9 switch (z) { + case 1: + fiddle(); + break; + case 2: + fiddle(); + break; + case 3: + fiddle(); + break; + default: + fiddle(); + break; + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## ExcessivePublicCount +**Since:** 1.04 + +**Priority:** Medium (3) + +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily. + +**Example(s):** +``` +public class Foo { + public String value; + public Bar something; + public Variable var; + // [... more more public attributes ...] + + public void doWork() {} + public void doMoreWork() {} + public void doWorkAgain() {} + // [... more more public methods ...] +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## TooManyFields +**Since:** 3.0 + +**Priority:** Medium (3) + +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field. + +**Example(s):** +``` +public class Person { // too many separate fields + int birthYear; + int birthMonth; + int birthDate; + float height; + float weight; +} + +public class Person { // this is more manageable + Date birthDate; + BodyMeasurements measurements; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|maxfields|15|Max allowable fields| + +## NcssMethodCount +**Since:** 3.9 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +public class Foo extends Bar { + public int methd() { + super.methd(); + + + + + + //this method only has 1 NCSS lines + return 1; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## NcssTypeCount +**Since:** 3.9 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +public class Foo extends Bar { + public Foo() { + //this class only has 6 NCSS lines + super(); + + + + + + super.foo(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## NcssConstructorCount +**Since:** 3.9 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +public class Foo extends Bar { + public Foo() { + super(); + + + + + + //this constructor only has 1 NCSS lines + super.foo(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## TooManyMethods +**Since:** 4.2 + +**Priority:** Medium (3) + +A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to +have more fine grained objects. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|maxmethods|10|The method count reporting threshold| + diff --git a/docs/pages/pmd/rules/java/comments.md b/docs/pages/pmd/rules/java/comments.md new file mode 100644 index 000000000..e1b75f33d --- /dev/null +++ b/docs/pages/pmd/rules/java/comments.md @@ -0,0 +1,136 @@ +--- +title: Comments +summary: Rules intended to catch errors related to code comments +permalink: pmd_rules_java_comments.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/comments.xml +--- +## CommentRequired +**Since:** 5.1 + +**Priority:** Medium (3) + +Denotes whether comments are required (or unwanted) for specific language elements. + +**Example(s):** +``` +/** +* +* +* @author George Bush +*/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|serialVersionUIDCommentRequired|Ignored|serial version UID commts. Possible values: [Required, Ignored, Unwanted]| +|enumCommentRequirement|Required|Enum comments. Possible values: [Required, Ignored, Unwanted]| +|protectedMethodCommentRequirement|Required|Protected method constructor comments. Possible values: [Required, Ignored, Unwanted]| +|publicMethodCommentRequirement|Required|Public method and constructor comments. Possible values: [Required, Ignored, Unwanted]| +|fieldCommentRequirement|Required|Field comments. Possible values: [Required, Ignored, Unwanted]| +|headerCommentRequirement|Required|Header comments. Possible values: [Required, Ignored, Unwanted]| + +## CommentSize +**Since:** 5.0 + +**Priority:** Medium (3) + +Determines whether the dimensions of non-header comments found are within the specified limits. + +**Example(s):** +``` +/** +* +* too many lines! +* +* +* +* +* +* +* +* +* +* +* +* +*/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|maxLines|6|Maximum lines| +|maxLineLength|80|Maximum line length| + +## CommentContent +**Since:** 5.0 + +**Priority:** Medium (3) + +A rule for the politically correct... we don't want to offend anyone. + +**Example(s):** +``` +// OMG, this is horrible, Bob is an idiot !!! +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|disallowedTerms|[idiot, jerk]|Illegal terms or phrases| +|caseSensitive|false|Case sensitive| +|wordsAreRegex|false|Use regular expressions| + +## CommentDefaultAccessModifier +**Since:** 5.4.0 + +**Priority:** Medium (3) + +To avoid mistakes if we want that a Method, Field or Nested class have a default access modifier + we must add a comment at the beginning of the Method, Field or Nested class. + By default the comment must be /* default */, if you want another, you have to provide a regex. + +**Example(s):** +``` +public class Foo { + final String stringValue = "some string"; + String getString() { + return stringValue; + } + + class NestedFoo { + } + } + + // should be + public class Foo { + /* default */ final String stringValue = "some string"; + /* default */ String getString() { + return stringValue; + } + + /* default */ class NestedFoo { + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|regex||Regular expression| + diff --git a/docs/pages/pmd/rules/java/controversial.md b/docs/pages/pmd/rules/java/controversial.md new file mode 100644 index 000000000..f661a0da6 --- /dev/null +++ b/docs/pages/pmd/rules/java/controversial.md @@ -0,0 +1,690 @@ +--- +title: Controversial +summary: The Controversial ruleset contains rules that, for whatever reason, are considered controversial. They are held here to allow people to include them as they see fit within their custom rulesets. +permalink: pmd_rules_java_controversial.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/controversial.xml +--- +## UnnecessaryConstructor +**Since:** 1.0 + +**Priority:** Medium (3) + +This rule detects when a constructor is not necessary; i.e., when there is only one constructor, +its public, has an empty body, and takes no arguments. + +**Example(s):** +``` +public class Foo { + public Foo() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NullAssignment +**Since:** 1.02 + +**Priority:** Medium (3) + +Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type +of assignment is an indication that the programmer doesn't completely understand what is going on in the code. + +NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. + +**Example(s):** +``` +public void bar() { + Object x = null; // this is OK + x = new Object(); + // big, complex piece of code here + x = null; // this is not required + // big, complex piece of code here +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## OnlyOneReturn +**Since:** 1.0 + +**Priority:** Medium (3) + +A method should have only one exit point, and that should be the last statement in the method. + +**Example(s):** +``` +public class OneReturnOnly1 { + public void foo(int x) { + if (x > 0) { + return "hey"; // first exit + } + return "hi"; // second exit + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AssignmentInOperand +**Since:** 1.03 + +**Priority:** Medium (3) + +Avoid assignments in operands; this can make code more complicated and harder to read. + +**Example(s):** +``` +public void bar() { + int x = 2; + if ((x = getX()) == 3) { + System.out.println("3!"); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| +|allowWhile|false|Allow assignment within the conditional expression of a while statement| +|allowFor|false|Allow assignment within the conditional expression of a for statement| +|allowIf|false|Allow assignment within the conditional expression of an if statement| + +## AtLeastOneConstructor +**Since:** 1.04 + +**Priority:** Medium (3) + +Each class should declare at least one constructor. + +**Example(s):** +``` +public class Foo { + // missing constructor + public void doSomething() { ... } + public void doOtherThing { ... } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DontImportSun +**Since:** 1.5 + +**Priority:** Medium Low (4) + +Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. + +**Example(s):** +``` +import sun.misc.foo; +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SuspiciousOctalEscape +**Since:** 1.5 + +**Priority:** Medium (3) + +A suspicious octal escape sequence was found inside a String literal. +The Java language specification (section 3.10.6) says an octal +escape sequence inside a literal String shall consist of a backslash +followed by: + + OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit + +Any octal escape sequence followed by non-octal digits can be confusing, +e.g. "\038" is interpreted as the octal escape sequence "\03" followed by +the literal character "8". + +**Example(s):** +``` +public void foo() { + // interpreted as octal 12, followed by character '8' + System.out.println("suspicious: \128"); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## CallSuperInConstructor +**Since:** 3.0 + +**Priority:** Medium (3) + +It is a good practice to call super() in a constructor. If super() is not called but +another constructor (such as an overloaded constructor) is called, this rule will not report it. + +**Example(s):** +``` +public class Foo extends Bar{ + public Foo() { + // call the constructor of Bar + super(); + } + public Foo(int code) { + // do something with code + this(); + // no problem with this + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnnecessaryParentheses +**Since:** 3.1 + +**Priority:** Medium (3) + +Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. + +**Example(s):** +``` +public class Foo { + boolean bar() { + return (true); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DefaultPackage +**Since:** 3.4 + +**Priority:** Medium (3) + +Use explicit scoping instead of accidental usage of default package private level. +The rule allows methods and fields annotated with Guava's @VisibleForTesting. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DataflowAnomalyAnalysis +**Since:** 3.9 + +**Priority:** Low (5) + +The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow. +From those informations there can be found various problems. + +1. UR - Anomaly: There is a reference to a variable that was not defined before. This is a bug and leads to an error. +2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text. +3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug. + +**Example(s):** +``` +public void foo() { + int buz = 5; + buz = 6; // redefinition of buz -> dd-anomaly + foo(buz); + buz = 2; +} // buz is undefined when leaving scope -> du-anomaly +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|maxViolations|100|Maximum number of anomalies per class| +|maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.| + +## AvoidFinalLocalVariable +**Since:** 4.1 + +**Priority:** Medium (3) + +Avoid using final local variables, turn them into fields. + +**Example(s):** +``` +public class MyClass { + public void foo() { + final String finalLocalVariable; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidUsingShortType +**Since:** 4.1 + +**Priority:** High (1) + +Java uses the 'short' type to reduce memory usage, not to optimize calculation. In fact, the JVM does not have any +arithmetic capabilities for the short type: the JVM must convert the short into an int, do the proper calculation +and convert the int back to a short. Thus any storage gains found through use of the 'short' type may be offset by +adverse impacts on performance. + +**Example(s):** +``` +public class UsingShort { + private short doNotUseShort = 0; + + public UsingShort() { + short shouldNotBeUsed = 1; + doNotUseShort += shouldNotBeUsed; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidUsingVolatile +**Since:** 4.1 + +**Priority:** Medium High (2) + +Use of the keyword 'volatile' is generally used to fine tune a Java application, and therefore, requires +a good expertise of the Java Memory Model. Moreover, its range of action is somewhat misknown. Therefore, +the volatile keyword should not be used for maintenance purpose and portability. + +**Example(s):** +``` +public class ThrDeux { + private volatile String var1; // not suggested + private String var2; // preferred +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidUsingNativeCode +**Since:** 4.1 + +**Priority:** Medium High (2) + +Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability +and increases the maintenance burden. + +**Example(s):** +``` +public class SomeJNIClass { + + public SomeJNIClass() { + System.loadLibrary("nativelib"); + } + + static { + System.loadLibrary("nativelib"); + } + + public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { + System.loadLibrary("nativelib"); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidAccessibilityAlteration +**Since:** 4.1 + +**Priority:** Medium (3) + +Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(), +as the interface PrivilegedAction, allows for the runtime alteration of variable, class, or +method visibility, even if they are private. This violates the principle of encapsulation. + +**Example(s):** +``` +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.security.PrivilegedAction; + +public class Violation { + public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { + // Possible call to forbidden getDeclaredConstructors + Class[] arrayOfClass = new Class[1]; + this.getClass().getDeclaredConstructors(); + this.getClass().getDeclaredConstructor(arrayOfClass); + Class clazz = this.getClass(); + clazz.getDeclaredConstructor(arrayOfClass); + clazz.getDeclaredConstructors(); + // Possible call to forbidden setAccessible + clazz.getMethod("", arrayOfClass).setAccessible(false); + AccessibleObject.setAccessible(null, false); + Method.setAccessible(null, false); + Method[] methodsArray = clazz.getMethods(); + int nbMethod; + for ( nbMethod = 0; nbMethod < methodsArray.length; nbMethod++ ) { + methodsArray[nbMethod].setAccessible(false); + } + + // Possible call to forbidden PrivilegedAction + PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotCallGarbageCollectionExplicitly +**Since:** 4.2 + +**Priority:** Medium High (2) + +Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Code should have the +same behavior whether the garbage collection is disabled using the option -Xdisableexplicitgc or not. +Moreover, "modern" jvms do a very good job handling garbage collections. If memory usage issues unrelated to memory +leaks develop within an application, it should be dealt with JVM options rather than within the code itself. + +**Example(s):** +``` +public class GCCall { + public GCCall() { + // Explicit gc call ! + System.gc(); + } + + public void doSomething() { + // Explicit gc call ! + Runtime.getRuntime().gc(); + } + + public explicitGCcall() { + // Explicit gc call ! + System.gc(); + } + + public void doSomething() { + // Explicit gc call ! + Runtime.getRuntime().gc(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## OneDeclarationPerLine +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Java allows the use of several variables declaration of the same type on one line. However, it +can lead to quite messy code. This rule looks for several declarations on the same line. + +**Example(s):** +``` +String name; // separate declarations +String lastname; + +String name, lastname; // combined declaration, a violation + +String name, + lastname; // combined declaration on multiple lines, no violation by default. + // Set property strictMode to true to mark this as violation. +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.| + +## AvoidPrefixingMethodParameters +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readability. +To indicate whether or not a parameter will be modify in a method, its better to document method +behavior with Javadoc. + +**Example(s):** +``` +// Not really clear +public class Foo { + public void bar( + int inLeftOperand, + Result outRightOperand) { + outRightOperand.setValue(inLeftOperand * outRightOperand.getValue()); + } +} +``` + +``` +// Far more useful +public class Foo { + /** + * + * @param leftOperand, (purpose), not modified by method. + * @param rightOperand (purpose), will be modified by the method: contains the result. + */ + public void bar( + int leftOperand, + Result rightOperand) { + rightOperand.setValue(leftOperand * rightOperand.getValue()); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidLiteralsInIfCondition +**Since:** 4.2.6 + +**Priority:** Medium (3) + +Avoid using hard-coded literals in conditional statements. By declaring them as static variables +or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. +More exceptions can be defined with the property "ignoreMagicNumbers". + +**Example(s):** +``` +private static final int MAX_NUMBER_OF_REQUESTS = 10; + +public void checkRequests() { + + if (i == 10) { // magic number, buried in a method + doSomething(); + } + + if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach + doSomething(); + } + + if (aString.indexOf('.') != -1) {} // magic number -1, by default ignored + if (aString.indexOf('.') >= 0) { } // alternative approach + + if (aDouble > 0.0) {} // magic number 0.0 + if (aDouble >= Double.MIN_VALUE) {} // preferred approach +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored| + +## UseObjectForClearerAPI +**Since:** 4.2.6 + +**Priority:** Medium (3) + +When you write a public method, you should be thinking in terms of an API. If your method is public, it means other class +will use it, therefore, you want (or need) to offer a comprehensive and evolutive API. If you pass a lot of information +as a simple series of Strings, you may think of using an Object to represent all those information. You'll get a simpler +API (such as doWork(Workload workload), rather than a tedious series of Strings) and more importantly, if you need at some +point to pass extra data, you'll be able to do so by simply modifying or extending Workload without any modification to +your API. + +**Example(s):** +``` +public class MyClass { + public void connect(String username, + String pssd, + String databaseName, + String databaseAdress) + // Instead of those parameters object + // would ensure a cleaner API and permit + // to add extra data transparently (no code change): + // void connect(UserData data); + { + + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseConcurrentHashMap +**Since:** 4.2.6 + +**Priority:** Medium (3) + +Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can +perform efficient map reads without blocking other threads. + +**Example(s):** +``` +public class ConcurrentApp { + public void getMyInstance() { + Map map1 = new HashMap(); // fine for single-threaded access + Map map2 = new ConcurrentHashMap(); // preferred for use with multiple threads + + // the following case will be ignored by this rule + Map map3 = someModule.methodThatReturnMap(); // might be OK, if the returned map is already thread-safe + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/coupling.md b/docs/pages/pmd/rules/java/coupling.md new file mode 100644 index 000000000..4540940aa --- /dev/null +++ b/docs/pages/pmd/rules/java/coupling.md @@ -0,0 +1,178 @@ +--- +title: Coupling +summary: Rules which find instances of high or inappropriate coupling between objects and packages. +permalink: pmd_rules_java_coupling.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/coupling.xml +--- +## CouplingBetweenObjects +**Since:** 1.04 + +**Priority:** Medium (3) + +This rule counts the number of unique attributes, local variables, and return types within an object. +A number higher than the specified threshold can indicate a high degree of coupling. + +**Example(s):** +``` +import com.Blah; +import org.Bar; +import org.Bardo; + +public class Foo { + private Blah var1; + private Bar var2; + + //followed by many imports of unique objects + void ObjectC doWork() { + Bardo var55; + ObjectA var44; + ObjectZ var93; + return something; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|threshold|20|Unique type reporting threshold| + +## ExcessiveImports +**Since:** 1.04 + +**Priority:** Medium (3) + +A high number of imports can indicate a high degree of coupling within an object. This rule +counts the number of unique imports and reports a violation if the count is above the +user-specified threshold. + +**Example(s):** +``` +import blah.blah.Baz; +import blah.blah.Bif; +// 18 others from the same package elided +public class Foo { + public void doWork() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## LooseCoupling +**Since:** 0.7 + +**Priority:** Medium (3) + +The use of implementation types as object references limits your ability to use alternate +implementations in the future as requirements change. Whenever available, referencing objects +by their interface types provides much more flexibility. + +**Example(s):** +``` +// sub-optimal approach +private ArrayList list = new ArrayList(); + +public HashSet getFoo() { + return new HashSet(); +} + + // preferred approach +private List list = new ArrayList(); + +public Set getFoo() { + return new HashSet(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## LoosePackageCoupling +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using classes from the configured package hierarchy outside of the package hierarchy, +except when using one of the configured allowed classes. + +**Example(s):** +``` +package some.package; + +import some.other.package.subpackage.subsubpackage.DontUseThisClass; + +public class Bar { + DontUseThisClass boo = new DontUseThisClass(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|classes|[]|Allowed classes| +|packages|[]|Restricted packages| + +## LawOfDemeter +**Since:** 5.0 + +**Priority:** Medium (3) + +The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes or objects. +See also the references: +Andrew Hunt, David Thomas, and Ward Cunningham. The Pragmatic Programmer. From Journeyman to Master. Addison-Wesley Longman, Amsterdam, October 1999.; +K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented programs. Software, IEEE, 6(5):38–48, 1989.; +http://www.ccs.neu.edu/home/lieber/LoD.html; +http://en.wikipedia.org/wiki/Law_of_Demeter + +**Example(s):** +``` +public class Foo { + /** + * This example will result in two violations. + */ + public void example(Bar b) { + // this method call is ok, as b is a parameter of "example" + C c = b.getC(); + + // this method call is a violation, as we are using c, which we got from B. + // We should ask b directly instead, e.g. "b.doItOnC();" + c.doIt(); + + // this is also a violation, just expressed differently as a method chain without temporary variables. + b.getC().doIt(); + + // a constructor call, not a method call. + D d = new D(); + // this method call is ok, because we have create the new instance of D locally. + d.doSomethingElse(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md new file mode 100644 index 000000000..ef6050c9f --- /dev/null +++ b/docs/pages/pmd/rules/java/design.md @@ -0,0 +1,1708 @@ +--- +title: Design +summary: The Design ruleset contains rules that flag suboptimal code implementations. Alternate approaches are suggested. +permalink: pmd_rules_java_design.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/design.xml +--- +## UseUtilityClass +**Since:** 0.3 + +**Priority:** Medium (3) + +For classes that only have static methods, consider making them utility classes. +Note that this doesn't apply to abstract classes, since their subclasses may +well include non-static methods. Also, if you want this class to be a utility class, +remember to add a private constructor to prevent instantiation. +(Note, that this use was known before PMD 5.1.0 as UseSingleton). + +**Example(s):** +``` +public class MaybeAUtility { + public static void foo() {} + public static void bar() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SimplifyBooleanReturns +**Since:** 0.9 + +**Priority:** Medium (3) + +Avoid unnecessary if-then-else statements when returning a boolean. The result of +the conditional test can be returned instead. + +**Example(s):** +``` +public boolean isBarEqualTo(int x) { + + if (bar == x) { // this bit of code... + return true; + } else { + return false; + } +} + +public boolean isBarEqualTo(int x) { + + return bar == x; // can be replaced with this +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SimplifyBooleanExpressions +**Since:** 1.05 + +**Priority:** Medium (3) + +Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. + +**Example(s):** +``` +public class Bar { + // can be simplified to + // bar = isFoo(); + private boolean bar = (isFoo() == true); + + public isFoo() { return false;} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SwitchStmtsShouldHaveDefault +**Since:** 1.0 + +**Priority:** Medium (3) + +All switch statements should include a default option to catch any unspecified values. + +**Example(s):** +``` +public void bar() { + int x = 2; + switch (x) { + case 1: int j = 6; + case 2: int j = 8; + // missing default: here + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidDeeplyNestedIfStmts +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. + +**Example(s):** +``` +public class Foo { + public void bar(int x, int y, int z) { + if (x>y) { + if (y>z) { + if (z==x) { + // !! too deep + } + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|problemDepth|3|The if statement depth reporting threshold| + +## AvoidReassigningParameters +**Since:** 1.0 + +**Priority:** Medium High (2) + +Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. + +**Example(s):** +``` +public class Foo { + private void foo(String bar) { + bar = "something else"; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SwitchDensity +**Since:** 1.02 + +**Priority:** Medium (3) + +A high ratio of statements to labels in a switch statement implies that the switch statement +is overloaded. Consider moving the statements into new methods or creating subclasses based +on the switch variable. + +**Example(s):** +``` +public class Foo { + public void bar(int x) { + switch (x) { + case 1: { + // lots of statements + break; + } case 2: { + // lots of statements + break; + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ConstructorCallsOverridableMethod +**Since:** 1.04 + +**Priority:** High (1) + +Calling overridable methods during construction poses a risk of invoking methods on an incompletely +constructed object and can be difficult to debug. +It may leave the sub-class unable to construct its superclass or forced to replicate the construction +process completely within itself, losing the ability to call super(). If the default constructor +contains a call to an overridable method, the subclass may be completely uninstantiable. Note that +this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a +private method bar() that calls a public method buz(), this denotes a problem. + +**Example(s):** +``` +public class SeniorClass { + public SeniorClass(){ + toString(); //may throw NullPointerException if overridden + } + public String toString(){ + return "IAmSeniorClass"; + } +} +public class JuniorClass extends SeniorClass { + private String name; + public JuniorClass(){ + super(); //Automatic call leads to NullPointerException + name = "JuniorClass"; + } + public String toString(){ + return name.toUpperCase(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AccessorClassGeneration +**Since:** 1.04 + +**Priority:** Medium (3) + +Instantiation by way of private constructors from outside of the constructor's class often causes the +generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this +situation. The generated class file is actually an interface. It gives the accessing class the ability +to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. +This turns a private constructor effectively into one with package scope, and is challenging to discern. + +**Example(s):** +``` +public class Outer { + void method(){ + Inner ic = new Inner();//Causes generation of accessor class + } + public class Inner { + private Inner(){} + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## FinalFieldCouldBeStatic +**Since:** 1.1 + +**Priority:** Medium (3) + +If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead +in each object at runtime. + +**Example(s):** +``` +public class Foo { + public final int BAR = 42; // this could be static and save some space +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CloseResource +**Since:** 1.2.2 + +**Priority:** Medium (3) + +Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use. + +**Example(s):** +``` +public class Bar { + public void foo() { + Connection c = pool.getConnection(); + try { + // do stuff + } catch (SQLException ex) { + // handle exception + } finally { + // oops, should close the connection using 'close'! + // c.close(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|closeAsDefaultTarget|true|Consider 'close' as a target by default| +|types|[java.sql.Connection, java.sql.Statement, java.sql.ResultSet]|Affected types| +|closeTargets|[]|Methods which may close this resource| + +## NonStaticInitializer +**Since:** 1.5 + +**Priority:** Medium (3) + +A non-static initializer block will be called any time a constructor is invoked (just prior to +invoking the constructor). While this is a valid language construct, it is rarely used and is +confusing. + +**Example(s):** +``` +public class MyClass { + // this block gets run before any call to a constructor + { + System.out.println("I am about to construct myself"); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DefaultLabelNotLastInSwitchStmt +**Since:** 1.5 + +**Priority:** Medium (3) + +By convention, the default label should be the last label in a switch statement. + +**Example(s):** +``` +public class Foo { + void bar(int a) { + switch (a) { + case 1: // do something + break; + default: // the default case should be last, by convention + break; + case 2: + break; + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NonCaseLabelInSwitchStatement +**Since:** 1.5 + +**Priority:** Medium (3) + +A non-case label (e.g. a named break/continue label) was present in a switch statement. +This legal, but confusing. It is easy to mix up the case labels and the non-case labels. + +**Example(s):** +``` +public class Foo { + void bar(int a) { + switch (a) { + case 1: + // do something + break; + mylabel: // this is legal, but confusing! + break; + default: + break; + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## OptimizableToArrayCall +**Since:** 1.8 + +**Priority:** Medium (3) + +Calls to a collection's toArray() method should specify target arrays sized to match the size of the +collection. Initial arrays that are too small are discarded in favour of new ones that have to be created +that are the proper size. + +**Example(s):** +``` +List foos = getFoos(); + + // inefficient, the array will be discarded +Foo[] fooArray = foos.toArray(new Foo[0]); + + // much better; this one sizes the destination array, + // avoiding of a new one via reflection +Foo[] fooArray = foos.toArray(new Foo[foos.size()]); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## BadComparison +**Since:** 1.8 + +**Priority:** Medium (3) + +Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation +precision when comparing floating point numbers these are likely to cause logic errors. + +**Example(s):** +``` +boolean x = (y == Double.NaN); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EqualsNull +**Since:** 1.9 + +**Priority:** High (1) + +Tests for null should not use the equals() method. The '==' operator should be used instead. + +**Example(s):** +``` +String x = "foo"; + +if (x.equals(null)) { // bad form + doSomething(); + } + +if (x == null) { // preferred + doSomething(); + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ConfusingTernary +**Since:** 1.9 + +**Priority:** Medium (3) + +Avoid negation within an "if" expression with an "else" clause. For example, rephrase: + + if (x != y) diff(); else same(); +as: + if (x == y) same(); else diff(); + +Most "if (x != y)" cases without an "else" are often return cases, so consistent use of this +rule makes the code easier to read. Also, this resolves trivial ordering problems, such +as "does the error case go first?" or "does the common case go first?". + +**Example(s):** +``` +boolean bar(int x, int y) { + return (x != y) ? diff : same; + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|ignoreElseIf|false|Ignore conditions with an else-if case| + +## InstantiationToGetClass +**Since:** 2.0 + +**Priority:** Medium Low (4) + +Avoid instantiating an object just to call getClass() on it; use the .class public member instead. + +**Example(s):** +``` +// replace this +Class c = new String().getClass(); + + // with this: +Class c = String.class; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## IdempotentOperations +**Since:** 2.0 + +**Priority:** Medium (3) + +Avoid idempotent operations - they have no effect. + +**Example(s):** +``` +public class Foo { + public void bar() { + int x = 2; + x = x; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SimpleDateFormatNeedsLocale +**Since:** 2.0 + +**Priority:** Medium (3) + +Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate +formatting is used. + +**Example(s):** +``` +public class Foo { + // Should specify Locale.US (or whatever) + private SimpleDateFormat sdf = new SimpleDateFormat("pattern"); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ImmutableField +**Since:** 2.0 + +**Priority:** Medium (3) + +Identifies private fields whose values never change once they are initialized either in the declaration +of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. + +**Example(s):** +``` +public class Foo { + private int x; // could be final + public Foo() { + x = 7; + } + public void foo() { + int a = x + 2; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UseLocaleWithCaseConversions +**Since:** 2.0 + +**Priority:** Medium (3) + +When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that +have unusual conventions, i.e. Turkish. + +**Example(s):** +``` +class Foo { + // BAD + if (x.toLowerCase().equals("list")) { } + /* + This will not match "LIST" when in Turkish locale + The above could be + if (x.toLowerCase(Locale.US).equals("list")) { } + or simply + if (x.equalsIgnoreCase("list")) { } + */ + // GOOD + String z = a.toLowerCase(Locale.EN); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidProtectedFieldInFinalClass +**Since:** 2.1 + +**Priority:** Medium (3) + +Do not use protected fields in final classes since they cannot be subclassed. +Clarify your intent by using private or package access modifiers instead. + +**Example(s):** +``` +public final class Bar { + private int x; + protected int y; // bar cannot be subclassed, so is y really private or package visible? + Bar() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AssignmentToNonFinalStatic +**Since:** 2.2 + +**Priority:** Medium (3) + +Identifies a possible unsafe usage of a static field. + +**Example(s):** +``` +public class StaticField { + static int x; + public FinalFields(int y) { + x = y; // unsafe + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## MissingStaticMethodInNonInstantiatableClass +**Since:** 3.0 + +**Priority:** Medium (3) + +A class that has private constructors and does not have any static methods or fields cannot be used. + +**Example(s):** +``` +// This class is unusable, since it cannot be +// instantiated (private constructor), +// and no static method can be called. + +public class Foo { + private Foo() {} + void foo() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidSynchronizedAtMethodLevel +**Since:** 3.0 + +**Priority:** Medium (3) + +Method-level synchronization can cause problems when new code is added to the method. +Block-level synchronization helps to ensure that only the code that needs synchronization +gets it. + +**Example(s):** +``` +public class Foo { + // Try to avoid this: + synchronized void foo() { + } + // Prefer this: + void bar() { + synchronized(this) { + } + } + + // Try to avoid this for static methods: + static synchronized void fooStatic() { + } + + // Prefer this: + static void barStatic() { + synchronized(Foo.class) { + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## MissingBreakInSwitch +**Since:** 3.0 + +**Priority:** Medium (3) + +Switch statements without break or return statements for each case option +may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. + +**Example(s):** +``` +public void bar(int status) { + switch(status) { + case CANCELLED: + doCancelled(); + // break; hm, should this be commented out? + case NEW: + doNew(); + // is this really a fall-through? + case REMOVED: + doRemoved(); + // what happens if you add another case after this one? + case OTHER: // empty case - this is interpreted as an intentional fall-through + case ERROR: + doErrorHandling(); + break; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseNotifyAllInsteadOfNotify +**Since:** 3.0 + +**Priority:** Medium (3) + +Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only +one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. + +**Example(s):** +``` +void bar() { + x.notify(); + // If many threads are monitoring x, only one (and you won't know which) will be notified. + // use instead: + x.notifyAll(); + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidInstanceofChecksInCatchClause +**Since:** 3.0 + +**Priority:** Medium (3) + +Each caught exception type should be handled in its own catch clause. + +**Example(s):** +``` +try { // Avoid this + // do something +} catch (Exception ee) { + if (ee instanceof IOException) { + cleanup(); + } +} +try { // Prefer this: + // do something +} catch (IOException ee) { + cleanup(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AbstractClassWithoutAbstractMethod +**Since:** 3.0 + +**Priority:** Medium (3) + +The abstract class does not contain any abstract methods. An abstract class suggests +an incomplete implementation, which is to be completed by subclasses implementing the +abstract methods. If the class is intended to be used as a base class only (not to be instantiated +directly) a protected constructor can be provided prevent direct instantiation. + +**Example(s):** +``` +public abstract class Foo { + void int method1() { ... } + void int method2() { ... } + // consider using abstract methods or removing + // the abstract modifier and adding protected constructors +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SimplifyConditional +**Since:** 3.1 + +**Priority:** Medium (3) + +No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. + +**Example(s):** +``` +class Foo { + void bar(Object x) { + if (x != null && x instanceof Bar) { + // just drop the "x != null" check + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## CompareObjectsWithEquals +**Since:** 3.2 + +**Priority:** Medium (3) + +Use equals() to compare object references; avoid comparing them with ==. + +**Example(s):** +``` +class Foo { + boolean bar(String a, String b) { + return a == b; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## PositionLiteralsFirstInComparisons +**Since:** 3.3 + +**Priority:** Medium (3) + +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false. + +**Example(s):** +``` +class Foo { + boolean bar(String x) { + return x.equals("2"); // should be "2".equals(x) + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## PositionLiteralsFirstInCaseInsensitiveComparisons +**Since:** 5.1 + +**Priority:** Medium (3) + +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false. + +**Example(s):** +``` +class Foo { + boolean bar(String x) { + return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x) + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnnecessaryLocalBeforeReturn +**Since:** 3.3 + +**Priority:** Medium (3) + +Avoid the creation of unnecessary local variables + +**Example(s):** +``` +public class Foo { + public int foo() { + int x = doSomething(); + return x; // instead, just 'return doSomething();' + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|statementOrderMatters|true|If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.| + +## NonThreadSafeSingleton +**Since:** 3.4 + +**Priority:** Medium (3) + +Non-thread safe singletons can result in bad state changes. Eliminate +static singletons if possible by instantiating the object directly. Static +singletons are usually not needed as only a single instance exists anyway. +Other possible fixes are to synchronize the entire method or to use an +[initialize-on-demand holder class](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom). + +Refrain from using the double-checked locking pattern. The Java Memory Model doesn't +guarantee it to work unless the variable is declared as `volatile`, adding an uneeded +performance penalty. [Reference](http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html) + +See Effective Java, item 48. + +**Example(s):** +``` +private static Foo foo = null; + +//multiple simultaneous callers may see partially initialized objects +public static Foo getFoo() { + if (foo==null) { + foo = new Foo(); + } + return foo; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.| +|checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.| + +## SingleMethodSingleton +**Since:** 5.4 + +**Priority:** Medium High (2) + +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, + for each call and new objects will be created for every invocation. + +**Example(s):** +``` +public class Singleton { + + private static Singleton singleton = new Singleton( ); + + private Singleton(){ } + +public static Singleton getInstance( ) { + return singleton; +} +public static Singleton getInstance(Object obj){ + Singleton singleton = (Singleton) obj; + return singleton; //violation +} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SingletonClassReturningNewInstance +**Since:** 5.4 + +**Priority:** Medium High (2) + +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, + for each call and new objects will be created for every invocation. + +**Example(s):** +``` +class Singleton { + private static Singleton instance = null; + public static Singleton getInstance() { + synchronized(Singleton.class){ + return new Singleton(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UncommentedEmptyMethodBody +**Since:** 3.4 + +**Priority:** Medium (3) + +Uncommented Empty Method Body finds instances where a method body does not contain +statements, but there is no comment. By explicitly commenting empty method bodies +it is easier to distinguish between intentional (commented) and unintentional +empty methods. + +**Example(s):** +``` +public void doSomething() { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UncommentedEmptyConstructor +**Since:** 3.4 + +**Priority:** Medium (3) + +Uncommented Empty Constructor finds instances where a constructor does not +contain statements, but there is no comment. By explicitly commenting empty +constructors it is easier to distinguish between intentional (commented) +and unintentional empty constructors. + +**Example(s):** +``` +public Foo() { + // This constructor is intentionally empty. Nothing special is needed here. +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not| + +## UnsynchronizedStaticDateFormatter +**Since:** 3.6 + +**Priority:** Medium (3) + +SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances +for each thread. If multiple threads must access a static formatter, the formatter must be +synchronized either on method or block level. + +**Example(s):** +``` +public class Foo { + private static final SimpleDateFormat sdf = new SimpleDateFormat(); + void bar() { + sdf.format(); // poor, no thread-safety + } + synchronized void foo() { + sdf.format(); // preferred + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## PreserveStackTrace +**Since:** 3.7 + +**Priority:** Medium (3) + +Throwing a new exception from a catch block without passing the original exception into the +new exception will cause the original stack trace to be lost making it difficult to debug +effectively. + +**Example(s):** +``` +public class Foo { + void good() { + try{ + Integer.parseInt("a"); + } catch (Exception e) { + throw new Exception(e); // first possibility to create exception chain + } + try { + Integer.parseInt("a"); + } catch (Exception e) { + throw (IllegalStateException)new IllegalStateException().initCause(e); // second possibility to create exception chain. + } + } + void bad() { + try{ + Integer.parseInt("a"); + } catch (Exception e) { + throw new Exception(e.getMessage()); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UseCollectionIsEmpty +**Since:** 3.9 + +**Priority:** Medium (3) + +The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. +Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. + +**Example(s):** +``` +public class Foo { + void good() { + List foo = getList(); + if (foo.isEmpty()) { + // blah + } + } + + void bad() { + List foo = getList(); + if (foo.size() == 0) { + // blah + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ClassWithOnlyPrivateConstructorsShouldBeFinal +**Since:** 4.1 + +**Priority:** High (1) + +A class with only private constructors should be final, unless the private constructor +is invoked by a inner class. + +**Example(s):** +``` +public class Foo { //Should be final + private Foo() { } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyMethodInAbstractClassShouldBeAbstract +**Since:** 4.1 + +**Priority:** High (1) + +Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate +usage by developers who should be implementing their own versions in the concrete subclasses. + +**Example(s):** +``` +public abstract class ShouldBeAbstract { + public Object couldBeAbstract() { + // Should be abstract method ? + return null; + } + + public void couldBeAbstract() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SingularField +**Since:** 3.1 + +**Priority:** Medium (3) + +Fields whose scopes are limited to just single methods do not rely on the containing +object to provide them to other methods. They may be better implemented as local variables +within those methods. + +**Example(s):** +``` +public class Foo { + private int x; // no reason to exist at the Foo instance level + public void foo(int y) { + x = y + 5; + return x; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|disallowNotAssignment|false|Disallow violations where the first usage is not an assignment| +|checkInnerClasses|false|Check inner classes| + +## ReturnEmptyArrayRatherThanNull +**Since:** 4.2 + +**Priority:** High (1) + +For any method that returns an array, it is a better to return an empty array rather than a +null reference. This removes the need for null checking all results and avoids inadvertent +NullPointerExceptions. + +**Example(s):** +``` +public class Example { + // Not a good idea... + public int[] badBehavior() { + // ... + return null; + } + + // Good behavior + public String[] bonnePratique() { + //... + return new String[0]; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AbstractClassWithoutAnyMethod +**Since:** 4.2 + +**Priority:** High (1) + +If an abstract class does not provides any methods, it may be acting as a simple data container +that is not meant to be instantiated. In this case, it is probably better to use a private or +protected constructor in order to prevent instantiation than make the class misleadingly abstract. + +**Example(s):** +``` +public class abstract Example { + String field; + int otherField; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## TooFewBranchesForASwitchStatement +**Since:** 4.2 + +**Priority:** Medium (3) + +Switch statements are indended to be used to support complex branching behaviour. Using a switch for only a few +cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the +if-then statement to increase code readability. + +**Example(s):** +``` +// With a minimumNumberCaseForASwitch of 3 +public class Foo { + public void bar() { + switch (condition) { + case ONE: + instruction; + break; + default: + break; // not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|minimumNumberCaseForASwitch|3|Minimum number of branches for a switch| + +## LogicInversion +**Since:** 5.0 + +**Priority:** Medium (3) + +Use opposite operator instead of negating the whole expression with a logic complement operator. + +**Example(s):** +``` +public boolean bar(int a, int b) { + + if (!(a == b)) { // use != + return false; + } + + if (!(a < b)) { // use >= + return false; + } + + return true; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseVarargs +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic +sugar provides flexibility for users of these methods and constructors, allowing them to avoid +having to deal with the creation of an array. + +**Example(s):** +``` +public class Foo { + public void foo(String s, Object[] args) { + // Do something here... + } + + public void bar(String s, Object... args) { + // Ahh, varargs tastes much better... + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## FieldDeclarationsShouldBeAtStartOfClass +**Since:** 5.0 + +**Priority:** Medium (3) + +Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. + +**Example(s):** +``` +public class HelloWorldBean { + + // Field declared before methods / inner classes - OK + private String _thing; + + public String getMessage() { + return "Hello World!"; + } + + // Field declared after methods / inner classes - avoid this + private String _fieldInWrongLocation; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.| +|ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations| +|ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.| + +## GodClass +**Since:** 5.0 + +**Priority:** Medium (3) + +The God Class rule detects the God Class design flaw using metrics. God classes do too many things, +are very big and overly complex. They should be split apart to be more object-oriented. +The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". +The violations are reported against the entire class. See also the references: +Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: +Using Software Metrics to Characterize, Evaluate, and Improve the Design +of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidProtectedMethodInFinalClassNotExtending +**Since:** 5.1 + +**Priority:** Medium (3) + +Do not use protected methods in most final classes since they cannot be subclassed. This should +only be allowed in final classes that extend other classes with protected methods (whose +visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead. + +**Example(s):** +``` +public final class Foo { + private int bar() {} + protected int baz() {} // Foo cannot be subclassed, and doesn't extend anything, so is baz() really private or package visible? +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ConstantsInInterface +**Since:** 5.5 + +**Priority:** Medium (3) + +Avoid constants in interfaces. Interfaces should define types, constants are implementation details +better placed in classes or enums. See Effective Java, item 19. + +**Example(s):** +``` +public interface ConstantInterface { + public static final int CONST1 = 1; // violation, no fields allowed in interface! + static final int CONST2 = 1; // violation, no fields allowed in interface! + final int CONST3 = 1; // violation, no fields allowed in interface! + int CONST4 = 1; // violation, no fields allowed in interface! +} + +// with ignoreIfHasMethods = false +public interface AnotherConstantInterface { + public static final int CONST1 = 1; // violation, no fields allowed in interface! + + int anyMethod(); +} + +// with ignoreIfHasMethods = true +public interface YetAnotherConstantInterface { + public static final int CONST1 = 1; // no violation + + int anyMethod(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods| + +## AccessorMethodGeneration +**Since:** 5.5.4 + +**Priority:** Medium (3) + +When accessing a private field / method from another class, the Java compiler will generate a accessor methods +with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can +be avoided by changing the visibility of the field / method from private to package-private. + +**Example(s):** +``` +public class OuterClass { + private int counter; + /* package */ int id; + + public class InnerClass { + InnerClass() { + OuterClass.this.counter++; // wrong accessor method will be generated + } + + public int getOuterClassId() { + return OuterClass.this.id; // id is package-private, no accessor method needed + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/empty.md b/docs/pages/pmd/rules/java/empty.md new file mode 100644 index 000000000..ad906487c --- /dev/null +++ b/docs/pages/pmd/rules/java/empty.md @@ -0,0 +1,314 @@ +--- +title: Empty Code +summary: The Empty Code ruleset contains rules that find empty statements of any kind (empty method, empty block statement, empty try or catch block,...). +permalink: pmd_rules_java_empty.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/empty.xml +--- +## EmptyCatchBlock +**Since:** 0.1 + +**Priority:** Medium (3) + +Empty Catch Block finds instances where an exception is caught, but nothing is done. +In most circumstances, this swallows an exception which should either be acted on +or reported. + +**Example(s):** +``` +public void doSomething() { + try { + FileInputStream fis = new FileInputStream("/tmp/bugger"); + } catch (IOException ioe) { + // not good + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|allowCommentedBlocks|false|Empty blocks containing comments will be skipped| +|allowExceptionNameRegex|^$|Empty blocks catching exceptions with names matching this regular expression will be skipped| + +## EmptyIfStmt +**Since:** 0.1 + +**Priority:** Medium (3) + +Empty If Statement finds instances where a condition is checked but nothing is done about it. + +**Example(s):** +``` +public class Foo { + void bar(int x) { + if (x == 0) { + // empty! + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyWhileStmt +**Since:** 0.2 + +**Priority:** Medium (3) + +Empty While Statement finds all instances where a while statement does nothing. +If it is a timing loop, then you should use Thread.sleep() for it; if it is +a while loop that does a lot in the exit expression, rewrite it to make it clearer. + +**Example(s):** +``` +void bar(int a, int b) { + while (a == b) { + // empty! + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyTryBlock +**Since:** 0.4 + +**Priority:** Medium (3) + +Avoid empty try blocks - what's the point? + +**Example(s):** +``` +public class Foo { + public void bar() { + try { + } catch (Exception e) { + e.printStackTrace(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyFinallyBlock +**Since:** 0.4 + +**Priority:** Medium (3) + +Empty finally blocks serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + public void bar() { + try { + int x=2; + } finally { + // empty! + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptySwitchStatements +**Since:** 1.0 + +**Priority:** Medium (3) + +Empty switch statements serve no purpose and should be removed. + +**Example(s):** +``` +public void bar() { + int x = 2; + switch (x) { + // once there was code here + // but it's been commented out or something + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptySynchronizedBlock +**Since:** 1.3 + +**Priority:** Medium (3) + +Empty synchronized blocks serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + public void bar() { + synchronized (this) { + // empty! + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyStatementNotInLoop +**Since:** 1.5 + +**Priority:** Medium (3) + +An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' +or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose +and should be removed. + +**Example(s):** +``` +public void doit() { + // this is probably not what you meant to do + ; + // the extra semicolon here this is not necessary + System.out.println("look at the extra semicolon");; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyInitializer +**Since:** 5.0 + +**Priority:** Medium (3) + +Empty initializers serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + + static {} // Why ? + + {} // Again, why ? + +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyStatementBlock +**Since:** 5.0 + +**Priority:** Medium (3) + +Empty block statements serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + + private int _bar; + + public void setBar(int bar) { + { _bar = bar; } // Why not? + {} // But remove this. + } + +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## EmptyStaticInitializer +**Since:** 1.5 + +**Priority:** Medium (3) + +An empty static initializer serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + static { + // empty + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/finalizers.md b/docs/pages/pmd/rules/java/finalizers.md new file mode 100644 index 000000000..ae09ccf33 --- /dev/null +++ b/docs/pages/pmd/rules/java/finalizers.md @@ -0,0 +1,151 @@ +--- +title: Finalizer +summary: These rules deal with different problems that can occur with finalizers. +permalink: pmd_rules_java_finalizers.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/finalizers.xml +--- +## EmptyFinalizer +**Since:** 1.5 + +**Priority:** Medium (3) + +Empty finalize methods serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + protected void finalize() {} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## FinalizeOnlyCallsSuperFinalize +**Since:** 1.5 + +**Priority:** Medium (3) + +If the finalize() is implemented, it should do something besides just calling super.finalize(). + +**Example(s):** +``` +protected void finalize() { + super.finalize(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## FinalizeOverloaded +**Since:** 1.5 + +**Priority:** Medium (3) + +Methods named finalize() should not have parameters. It is confusing and most likely an attempt to +overload Object.finalize(). It will not be called by the VM. + +**Example(s):** +``` +public class Foo { + // this is confusing and probably a bug + protected void finalize(int a) { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## FinalizeDoesNotCallSuperFinalize +**Since:** 1.5 + +**Priority:** Medium (3) + +If the finalize() is implemented, its last action should be to call super.finalize. + +**Example(s):** +``` +protected void finalize() { + something(); + // neglected to call super.finalize() +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## FinalizeShouldBeProtected +**Since:** 1.1 + +**Priority:** Medium (3) + +When overriding the finalize(), the new method should be set as protected. If made public, +other classes may invoke it at inappropriate times. + +**Example(s):** +``` +public void finalize() { + // do something +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidCallingFinalize +**Since:** 3.0 + +**Priority:** Medium (3) + +The method Object.finalize() is called by the garbage collector on an object when garbage collection determines +that there are no more references to the object. It should not be invoked by application logic. + +**Example(s):** +``` +void foo() { + Bar b = new Bar(); + b.finalize(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/imports.md b/docs/pages/pmd/rules/java/imports.md new file mode 100644 index 000000000..1bcbc5328 --- /dev/null +++ b/docs/pages/pmd/rules/java/imports.md @@ -0,0 +1,155 @@ +--- +title: Import Statements +summary: These rules deal with different problems that can occur with import statements. +permalink: pmd_rules_java_imports.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/imports.xml +--- +## DuplicateImports +**Since:** 0.5 + +**Priority:** Medium Low (4) + +Duplicate or overlapping import statements should be avoided. + +**Example(s):** +``` +import java.lang.String; +import java.lang.*; +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## DontImportJavaLang +**Since:** 0.5 + +**Priority:** Medium Low (4) + +Avoid importing anything from the package 'java.lang'. These classes are automatically imported (JLS 7.5.3). + +**Example(s):** +``` +import java.lang.String; // this is unnecessary + +public class Foo {} + +// --- in another source code file... + +import java.lang.*; // this is bad + +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedImports +**Since:** 1.0 + +**Priority:** Medium Low (4) + +Avoid the use of unused import statements to prevent unwanted dependencies. + +**Example(s):** +``` +// this is bad +import java.io.File; +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ImportFromSamePackage +**Since:** 1.02 + +**Priority:** Medium (3) + +There is no need to import a type that lives in the same package. + +**Example(s):** +``` +package foo; + + import foo.Buz; // no need for this + import foo.*; // or this + + public class Bar{} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## TooManyStaticImports +**Since:** 4.1 + +**Priority:** Medium (3) + +If you overuse the static import feature, it can make your program unreadable and +unmaintainable, polluting its namespace with all the static members you import. +Readers of your code (including you, a few months after you wrote it) will not know +which class a static member comes from (Sun 1.5 Language Guide). + +**Example(s):** +``` +import static Lennon; +import static Ringo; +import static George; +import static Paul; +import static Yoko; // Too much ! +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|maximumStaticImports|4|All static imports can be disallowed by setting this to 0| + +## UnnecessaryFullyQualifiedName +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Import statements allow the use of non-fully qualified names. The use of a fully qualified name +which is covered by an import statement is redundant. Consider using the non-fully qualified name. + +**Example(s):** +``` +import java.util.List; + +public class Foo { + private java.util.List list1; // Unnecessary FQN + private List list2; // More appropriate given import of 'java.util.List' +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/j2ee.md b/docs/pages/pmd/rules/java/j2ee.md new file mode 100644 index 000000000..257f2d3fd --- /dev/null +++ b/docs/pages/pmd/rules/java/j2ee.md @@ -0,0 +1,238 @@ +--- +title: J2EE +summary: Rules specific to the use of J2EE implementations. +permalink: pmd_rules_java_j2ee.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/j2ee.xml +--- +## UseProperClassLoader +**Since:** 3.7 + +**Priority:** Medium (3) + +In J2EE, the getClassLoader() method might not work as expected. Use +Thread.currentThread().getContextClassLoader() instead. + +**Example(s):** +``` +public class Foo { + ClassLoader cl = Bar.class.getClassLoader(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## MDBAndSessionBeanNamingConvention +**Since:** 4.0 + +**Priority:** Medium Low (4) + +The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. + +**Example(s):** +``` +public class SomeBean implements SessionBean{} // proper name + +public class MissingTheProperSuffix implements SessionBean {} // non-standard name +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## RemoteSessionInterfaceNamingConvention +**Since:** 4.0 + +**Priority:** Medium Low (4) + +A Remote Home interface type of a Session EJB should be suffixed by 'Home'. + +**Example(s):** +``` +public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper name + +public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standard name +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## LocalInterfaceSessionNamingConvention +**Since:** 4.0 + +**Priority:** Medium Low (4) + +The Local Interface of a Session EJB should be suffixed by 'Local'. + +**Example(s):** +``` +public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name + + public interface MissingProperSuffix extends javax.ejb.EJBLocalObject {} // non-standard name +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## LocalHomeNamingConvention +**Since:** 4.0 + +**Priority:** Medium Low (4) + +The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. + +**Example(s):** +``` +public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper name + + public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-standard name +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## RemoteInterfaceNamingConvention +**Since:** 4.0 + +**Priority:** Medium Low (4) + +Remote Interface of a Session EJB should not have a suffix. + +**Example(s):** +``` +/* Poor Session suffix */ + public interface BadSuffixSession extends javax.ejb.EJBObject {} + + /* Poor EJB suffix */ + public interface BadSuffixEJB extends javax.ejb.EJBObject {} + + /* Poor Bean suffix */ + public interface BadSuffixBean extends javax.ejb.EJBObject {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotCallSystemExit +**Since:** 4.1 + +**Priority:** Medium (3) + +Web applications should not call System.exit(), since only the web container or the +application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). + +**Example(s):** +``` +public void bar() { + System.exit(0); // never call this when running in an application server! +} +public void foo() { + Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this. +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## StaticEJBFieldShouldBeFinal +**Since:** 4.1 + +**Priority:** Medium (3) + +According to the J2EE specification, an EJB should not have any static fields +with write access. However, static read-only fields are allowed. This ensures proper +behavior especially when instances are distributed by the container on several JREs. + +**Example(s):** +``` +public class SomeEJB extends EJBObject implements EJBLocalHome { + + private static int CountA; // poor, field can be edited + + private static final int CountB; // preferred, read-only access +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotUseThreads +**Since:** 4.1 + +**Priority:** Medium (3) + +The J2EE specification explicitly forbids the use of threads. + +**Example(s):** +``` +// This is not allowed +public class UsingThread extends Thread { + + } + // Neither this, +public class OtherThread implements Runnable { + // Nor this ... + public void methode() { + Runnable thread = new Thread(); thread.run(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/javabeans.md b/docs/pages/pmd/rules/java/javabeans.md new file mode 100644 index 000000000..3bb0a891f --- /dev/null +++ b/docs/pages/pmd/rules/java/javabeans.md @@ -0,0 +1,67 @@ +--- +title: JavaBeans +summary: The JavaBeans Ruleset catches instances of bean rules not being followed. +permalink: pmd_rules_java_javabeans.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/javabeans.xml +--- +## BeanMembersShouldSerialize +**Since:** 1.1 + +**Priority:** Medium (3) + +If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializable. +Member variables need to be marked as transient, static, or have accessor methods in the class. Marking +variables as transient is the safest and easiest modification. Accessor methods should follow the Java +naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided. + +**Example(s):** +``` +private transient int someFoo; // good, it's transient +private static int otherFoo; // also OK +private int moreFoo; // OK, has proper accessors, see below +private int badFoo; // bad, should be marked transient + +private void setMoreFoo(int moreFoo){ + this.moreFoo = moreFoo; +} + +private int getMoreFoo(){ + return this.moreFoo; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|prefix||A variable prefix to skip, i.e., m_| + +## MissingSerialVersionUID +**Since:** 3.0 + +**Priority:** Medium (3) + +Serializable classes should provide a serialVersionUID field. + +**Example(s):** +``` +public class Foo implements java.io.Serializable { + String name; + // Define serialization id to avoid serialization related bugs + // i.e., public static final long serialVersionUID = 4328743; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/junit.md b/docs/pages/pmd/rules/java/junit.md new file mode 100644 index 000000000..dec705c3f --- /dev/null +++ b/docs/pages/pmd/rules/java/junit.md @@ -0,0 +1,360 @@ +--- +title: JUnit +summary: These rules deal with different problems that can occur with JUnit tests. +permalink: pmd_rules_java_junit.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/junit.xml +--- +## JUnitStaticSuite +**Since:** 1.0 + +**Priority:** Medium (3) + +The suite() method in a JUnit test needs to be both public and static. + +**Example(s):** +``` +import junit.framework.*; + +public class Foo extends TestCase { + public void suite() {} // oops, should be static + private static void suite() {} // oops, should be public +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnitSpelling +**Since:** 1.0 + +**Priority:** Medium (3) + +Some JUnit framework methods are easy to misspell. + +**Example(s):** +``` +import junit.framework.*; + +public class Foo extends TestCase { + public void setup() {} // oops, should be setUp + public void TearDown() {} // oops, should be tearDown +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnitAssertionsShouldIncludeMessage +**Since:** 1.04 + +**Priority:** Medium (3) + +JUnit assertions should include an informative message - i.e., use the three-argument version of +assertEquals(), not the two-argument version. + +**Example(s):** +``` +public class Foo extends TestCase { + public void testSomething() { + assertEquals("foo", "bar"); + // Use the form: + // assertEquals("Foo does not equals bar", "foo", "bar"); + // instead + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## JUnitTestsShouldIncludeAssert +**Since:** 2.0 + +**Priority:** Medium (3) + +JUnit tests should include at least one assertion. This makes the tests more robust, and using assert +with messages provide the developer a clearer idea of what the test does. + +**Example(s):** +``` +public class Foo extends TestCase { + public void testSomething() { + Bar b = findBar(); + // This is better than having a NullPointerException + // assertNotNull("bar not found", b); + b.work(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## TestClassWithoutTestCases +**Since:** 3.0 + +**Priority:** Medium (3) + +Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, +since most people will assume it is a test case. Test classes have test methods named testXXX. + +**Example(s):** +``` +//Consider changing the name of the class if it is not a test +//Consider adding test methods if it is a test +public class CarTest { + public static void main(String[] args) { + // do something + } + // code +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnnecessaryBooleanAssertion +**Since:** 3.0 + +**Priority:** Medium (3) + +A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the same thing. +Consider using flow control (in case of assertTrue(false) or similar) or simply removing +statements like assertTrue(true) and assertFalse(false). If you just want a test to halt after finding +an error, use the fail() method and provide an indication message of why it did. + +**Example(s):** +``` +public class SimpleTest extends TestCase { + public void testX() { + assertTrue(true); // serves no real purpose + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseAssertEqualsInsteadOfAssertTrue +**Since:** 3.1 + +**Priority:** Medium (3) + +This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals. + +**Example(s):** +``` +public class FooTest extends TestCase { + void testCode() { + Object a, b; + assertTrue(a.equals(b)); // bad usage + assertEquals(?a should equals b?, a, b); // good usage + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseAssertSameInsteadOfAssertTrue +**Since:** 3.1 + +**Priority:** Medium (3) + +This rule detects JUnit assertions in object references equality. These assertions should be made +by more specific methods, like assertSame, assertNotSame. + +**Example(s):** +``` +public class FooTest extends TestCase { + void testCode() { + Object a, b; + assertTrue(a == b); // bad usage + assertSame(a, b); // good usage + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseAssertNullInsteadOfAssertTrue +**Since:** 3.5 + +**Priority:** Medium (3) + +This rule detects JUnit assertions in object references equality. These assertions should be made by +more specific methods, like assertNull, assertNotNull. + +**Example(s):** +``` +public class FooTest extends TestCase { + void testCode() { + Object a = doSomething(); + assertTrue(a==null); // bad usage + assertNull(a); // good usage + assertTrue(a != null); // bad usage + assertNotNull(a); // good usage + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SimplifyBooleanAssertion +**Since:** 3.6 + +**Priority:** Medium (3) + +Avoid negation in an assertTrue or assertFalse test. + +For example, rephrase: + + assertTrue(!expr); + +as: + + assertFalse(expr); + +**Example(s):** +``` +public class SimpleTest extends TestCase { + public void testX() { + assertTrue("not empty", !r.isEmpty()); // replace with assertFalse("not empty", r.isEmpty()) + assertFalse(!r.isEmpty()); // replace with assertTrue(r.isEmpty()) + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnitTestContainsTooManyAsserts +**Since:** 5.0 + +**Priority:** Medium (3) + +JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which +it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios. +Customize the maximum number of assertions used by this Rule to suit your needs. + +**Example(s):** +``` +public class MyTestCase extends TestCase { + // Ok + public void testMyCaseWithOneAssert() { + boolean myVar = false; + assertFalse("should be false", myVar); + } + + // Bad, too many asserts (assuming max=1) + public void testMyCaseWithMoreAsserts() { + boolean myVar = false; + assertFalse("myVar should be false", myVar); + assertEquals("should equals false", false, myVar); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|maximumAsserts|1|Maximum number of Asserts in a test method| + +## UseAssertTrueInsteadOfAssertEquals +**Since:** 5.0 + +**Priority:** Medium (3) + +When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, instead of assertEquals. + +**Example(s):** +``` +public class MyTestCase extends TestCase { + public void testMyCase() { + boolean myVar = true; + // Ok + assertTrue("myVar is true", myVar); + // Bad + assertEquals("myVar is true", true, myVar); + // Bad + assertEquals("myVar is false", false, myVar); + // Bad + assertEquals("myVar is true", Boolean.TRUE, myVar); + // Bad + assertEquals("myVar is false", Boolean.FALSE, myVar); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/logging-jakarta-commons.md b/docs/pages/pmd/rules/java/logging-jakarta-commons.md new file mode 100644 index 000000000..2250bb325 --- /dev/null +++ b/docs/pages/pmd/rules/java/logging-jakarta-commons.md @@ -0,0 +1,134 @@ +--- +title: Jakarta Commons Logging +summary: The Jakarta Commons Logging ruleset contains a collection of rules that find questionable usages of that framework. +permalink: pmd_rules_java_logging-jakarta-commons.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-jakarta-commons.xml +--- +## UseCorrectExceptionLogging +**Since:** 3.2 + +**Priority:** Medium (3) + +To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. + +**Example(s):** +``` +public class Main { + private static final Log _LOG = LogFactory.getLog( Main.class ); + void bar() { + try { + } catch( Exception e ) { + _LOG.error( e ); //Wrong! + } catch( OtherException oe ) { + _LOG.error( oe.getMessage(), oe ); //Correct + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ProperLogger +**Since:** 3.3 + +**Priority:** Medium (3) + +A logger should normally be defined private static final and be associated with the correct class. +Private final Log log; is also allowed for rare cases where loggers need to be passed around, +with the restriction that the logger needs to be passed into the constructor. + +**Example(s):** +``` +public class Foo { + + private static final Log LOG = LogFactory.getLog(Foo.class); // proper way + + protected Log LOG = LogFactory.getLog(Testclass.class); // wrong approach +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|staticLoggerName|LOG|Name of the static Logger variable| + +## GuardDebugLogging +**Since:** 4.3 + +**Priority:** Medium (3) + +When log messages are composed by concatenating strings, the whole section should be guarded + by a isDebugEnabled() check to avoid performance and memory issues. + +**Example(s):** +``` +public class Test { + private static final Log __log = LogFactory.getLog(Test.class); + public void test() { + // okay: + __log.debug("log something"); + + // okay: + __log.debug("log something with exception", e); + + // bad: + __log.debug("log something" + " and " + "concat strings"); + + // bad: + __log.debug("log something" + " and " + "concat strings", e); + + // good: + if (__log.isDebugEnabled()) { + __log.debug("bla" + "",e ); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|guardsMethods|[]|method use to guard the log statement| +|logLevels|[]|LogLevels to guard| + +## GuardLogStatement +**Since:** 5.1.0 + +**Priority:** Medium High (2) + +Whenever using a log level, one should check if the loglevel is actually enabled, or +otherwise skip the associate String creation and manipulation. + +**Example(s):** +``` +// Add this for performance + if (log.isDebugEnabled() { ... + log.debug("log something" + " and " + "concat strings"); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|guardsMethods|[]|method use to guard the log statement| +|logLevels|[]|LogLevels to guard| + diff --git a/docs/pages/pmd/rules/java/logging-java.md b/docs/pages/pmd/rules/java/logging-java.md new file mode 100644 index 000000000..1f3dc02fe --- /dev/null +++ b/docs/pages/pmd/rules/java/logging-java.md @@ -0,0 +1,161 @@ +--- +title: Java Logging +summary: The Java Logging ruleset contains a collection of rules that find questionable usages of the logger. +permalink: pmd_rules_java_logging-java.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-java.xml +--- +## MoreThanOneLogger +**Since:** 2.0 + +**Priority:** Medium High (2) + +Normally only one logger is used in each class. + +**Example(s):** +``` +public class Foo { + Logger log = Logger.getLogger(Foo.class.getName()); + // It is very rare to see two loggers on a class, normally + // log information is multiplexed by levels + Logger log2= Logger.getLogger(Foo.class.getName()); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## LoggerIsNotStaticFinal +**Since:** 2.0 + +**Priority:** Medium High (2) + +In most cases, the Logger reference can be declared as static and final. + +**Example(s):** +``` +public class Foo{ + Logger log = Logger.getLogger(Foo.class.getName()); // not recommended + + static final Logger log = Logger.getLogger(Foo.class.getName()); // preferred approach +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SystemPrintln +**Since:** 2.1 + +**Priority:** Medium High (2) + +References to System.(out|err).print are usually intended for debugging purposes and can remain in +the codebase even in production code. By using a logger one can enable/disable this behaviour at +will (and by priority) and avoid clogging the Standard out log. + +**Example(s):** +``` +class Foo{ + Logger log = Logger.getLogger(Foo.class.getName()); + public void testA () { + System.out.println("Entering test"); + // Better use this + log.fine("Entering test"); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidPrintStackTrace +**Since:** 3.2 + +**Priority:** Medium (3) + +Avoid printStackTrace(); use a logger call instead. + +**Example(s):** +``` +class Foo { + void bar() { + try { + // do something + } catch (Exception e) { + e.printStackTrace(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## GuardLogStatementJavaUtil +**Since:** 5.1.0 + +**Priority:** Medium High (2) + +Whenever using a log level, one should check if the loglevel is actually enabled, or +otherwise skip the associate String creation and manipulation. + +**Example(s):** +``` +// Add this for performance + if (log.isLoggable(Level.FINE)) { ... + log.fine("log something" + " and " + "concat strings"); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|guardsMethods|[]|method use to guard the log statement| +|logLevels|[]|LogLevels to guard| + +## InvalidSlf4jMessageFormat +**Since:** 5.5.0 + +**Priority:** Low (5) + +Check for messages in slf4j loggers with non matching number of arguments and placeholders. + +**Example(s):** +``` +LOGGER.error("forget the arg {}"); +LOGGER.error("too many args {}", "arg1", "arg2"); +LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct. +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md new file mode 100644 index 000000000..034988971 --- /dev/null +++ b/docs/pages/pmd/rules/java/migrating.md @@ -0,0 +1,391 @@ +--- +title: Migration +summary: Contains rules about migrating from one JDK version to another. Don't use these rules directly, rather, use a wrapper ruleset such as migrating_to_13.xml. +permalink: pmd_rules_java_migrating.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml +--- +## ReplaceVectorWithList +**Since:** 3.4 + +**Priority:** Medium (3) + +Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. + +**Example(s):** +``` +public class Foo { + void bar() { + Vector v = new Vector(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ReplaceHashtableWithMap +**Since:** 3.4 + +**Priority:** Medium (3) + +Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. + +**Example(s):** +``` +public class Foo { + void bar() { + Hashtable h = new Hashtable(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ReplaceEnumerationWithIterator +**Since:** 3.4 + +**Priority:** Medium (3) + +Consider replacing Enumeration usages with the newer java.util.Iterator + +**Example(s):** +``` +public class Foo implements Enumeration { + private int x = 42; + public boolean hasMoreElements() { + return true; + } + public Object nextElement() { + return String.valueOf(i++); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidEnumAsIdentifier +**Since:** 3.4 + +**Priority:** Medium High (2) + +Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. + +**Example(s):** +``` +public class A { + public class foo { + String enum = "foo"; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidAssertAsIdentifier +**Since:** 3.4 + +**Priority:** Medium High (2) + +Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. + +**Example(s):** +``` +public class A { + public class foo { + String assert = "foo"; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## IntegerInstantiation +**Since:** 3.5 + +**Priority:** Medium High (2) + +Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Integer i = new Integer(0); // change to Integer i = Integer.valueOf(0); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ByteInstantiation +**Since:** 4.0 + +**Priority:** Medium High (2) + +Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Byte i = new Byte(0); // change to Byte i = Byte.valueOf(0); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## ShortInstantiation +**Since:** 4.0 + +**Priority:** Medium High (2) + +Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Short i = new Short(0); // change to Short i = Short.valueOf(0); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## LongInstantiation +**Since:** 4.0 + +**Priority:** Medium High (2) + +Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Long i = new Long(0); // change to Long i = Long.valueOf(0); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnit4TestShouldUseBeforeAnnotation +**Since:** 4.0 + +**Priority:** Medium (3) + +In JUnit 3, the setUp method was used to set up all data entities required in running tests. +JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests + +**Example(s):** +``` +public class MyTest { + public void setUp() { + bad(); + } +} +public class MyTest2 { + @Before public void setUp() { + good(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnit4TestShouldUseAfterAnnotation +**Since:** 4.0 + +**Priority:** Medium (3) + +In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. +JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test + +**Example(s):** +``` +public class MyTest { + public void tearDown() { + bad(); + } +} +public class MyTest2 { + @After public void tearDown() { + good(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnit4TestShouldUseTestAnnotation +**Since:** 4.0 + +**Priority:** Medium (3) + +In JUnit 3, the framework executed all methods which started with the word test as a unit test. +In JUnit 4, only methods annotated with the @Test annotation are executed. + +**Example(s):** +``` +public class MyTest { + public void testBad() { + doSomething(); + } + + @Test + public void testGood() { + doSomething(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnit4SuitesShouldUseSuiteAnnotation +**Since:** 4.0 + +**Priority:** Medium (3) + +In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated +through the @RunWith(Suite.class) annotation. + +**Example(s):** +``` +public class BadExample extends TestCase{ + + public static Test suite(){ + return new Suite(); + } +} + +@RunWith(Suite.class) +@SuiteClasses( { TestOne.class, TestTwo.class }) +public class GoodTest { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## JUnitUseExpected +**Since:** 4.0 + +**Priority:** Medium (3) + +In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. + +**Example(s):** +``` +public class MyTest { + @Test + public void testBad() { + try { + doSomething(); + fail("should have thrown an exception"); + } catch (Exception e) { + } + } + + @Test(expected=Exception.class) + public void testGood() { + doSomething(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/naming.md b/docs/pages/pmd/rules/java/naming.md new file mode 100644 index 000000000..c3d171472 --- /dev/null +++ b/docs/pages/pmd/rules/java/naming.md @@ -0,0 +1,530 @@ +--- +title: Naming +summary: The Naming Ruleset contains rules regarding preferred usage of names and identifiers. +permalink: pmd_rules_java_naming.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/naming.xml +--- +## ShortVariable +**Since:** 0.3 + +**Priority:** Medium (3) + +Fields, local variables, or parameter names that are very short are not helpful to the reader. + +**Example(s):** +``` +public class Something { + private int q = 15; // field - too short + public static void main( String as[] ) { // formal arg - too short + int r = 20 + q; // local var - too short + for (int i = 0; i < 10; i++) { // not a violation (inside 'for' loop) + r += q; + } + for (Integer i : numbers) { // not a violation (inside 'for-each' loop) + r += q; + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|minimum|3|Number of characters that are required as a minimum for a variable name.| + +## LongVariable +**Since:** 0.3 + +**Priority:** Medium (3) + +Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. + +**Example(s):** +``` +public class Something { + int reallyLongIntName = -3; // VIOLATION - Field + public static void main( String argumentsList[] ) { // VIOLATION - Formal + int otherReallyLongName = -5; // VIOLATION - Local + for (int interestingIntIndex = 0; // VIOLATION - For + interestingIntIndex < 10; + interestingIntIndex ++ ) { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|minimum|17|The variable length reporting threshold| + +## ShortMethodName +**Since:** 0.3 + +**Priority:** Medium (3) + +Method names that are very short are not helpful to the reader. + +**Example(s):** +``` +public class ShortMethod { + public void a( int i ) { // Violation + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|minimum|3|Number of characters that are required as a minimum for a method name.| + +## VariableNamingConventions +**Since:** 1.2 + +**Priority:** High (1) + +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores. + +**Example(s):** +``` +public class Foo { + public static final int MY_NUM = 0; + public String myTest = ""; + DataModule dmTest = new DataModule(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|parameterSuffix|[]|Method parameter variable suffixes| +|parameterPrefix|[]|Method parameter variable prefixes| +|localSuffix|[]|Local variable suffixes| +|localPrefix|[]|Local variable prefixes| +|memberSuffix|[]|Member variable suffixes| +|memberPrefix|[]|Member variable prefixes| +|staticSuffix|[]|Static variable suffixes| +|checkParameters|true|Check constructor and method parameter variables| +|checkNativeMethodParameters|true|Check method parameter of native methods| +|staticPrefix|[]|Static variable prefixes| +|checkLocals|true|Check local variables| +|checkMembers|true|Check member variables| + +## MethodNamingConventions +**Since:** 1.2 + +**Priority:** High (1) + +Method names should always begin with a lower case character, and should not contain underscores. + +**Example(s):** +``` +public class Foo { + public void fooStuff() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkNativeMethods|true|Check native methods| + +## ClassNamingConventions +**Since:** 1.2 + +**Priority:** High (1) + +Class names should always begin with an upper case character. + +**Example(s):** +``` +public class Foo {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AbstractNaming +**Since:** 1.4 + +**Priority:** Medium (3) + +Abstract classes should be named 'AbstractXXX'. + +**Example(s):** +``` +public abstract class Foo { // should be AbstractFoo +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|strict|true|Also flag classes, that are named Abstract, but are not abstract.| + +## AvoidDollarSigns +**Since:** 1.5 + +**Priority:** Medium (3) + +Avoid using dollar signs in variable/method/class/interface names. + +**Example(s):** +``` +public class Fo$o { // not a recommended name +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## MethodWithSameNameAsEnclosingClass +**Since:** 1.5 + +**Priority:** Medium (3) + +Non-constructor methods should not have the same name as the enclosing class. + +**Example(s):** +``` +public class MyClass { + + public MyClass() {} // this is OK because it is a constructor + + public void MyClass() {} // this is bad because it is a method +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SuspiciousHashcodeMethodName +**Since:** 1.5 + +**Priority:** Medium (3) + +The method name and return type are suspiciously close to hashCode(), which may denote an intention +to override the hashCode() method. + +**Example(s):** +``` +public class Foo { + public int hashcode() { // oops, this probably was supposed to be 'hashCode' + + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SuspiciousConstantFieldName +**Since:** 2.0 + +**Priority:** Medium (3) + +Field names using all uppercase characters - Sun's Java naming conventions indicating constants - should +be declared as final. + +**Example(s):** +``` +public class Foo { + // this is bad, since someone could accidentally + // do PI = 2.71828; which is actually e + // final double PI = 3.16; is ok + double PI = 3.16; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SuspiciousEqualsMethodName +**Since:** 2.0 + +**Priority:** Medium High (2) + +The method name and parameter number are suspiciously close to equals(Object), which can denote an +intention to override the equals(Object) method. + +**Example(s):** +``` +public class Foo { + public int equals(Object o) { + // oops, this probably was supposed to be boolean equals + } + public boolean equals(String s) { + // oops, this probably was supposed to be equals(Object) + } + public boolean equals(Object o1, Object o2) { + // oops, this probably was supposed to be equals(Object) + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidFieldNameMatchingTypeName +**Since:** 3.0 + +**Priority:** Medium (3) + +It is somewhat confusing to have a field name matching the declaring class name. +This probably means that type and/or field names should be chosen more carefully. + +**Example(s):** +``` +public class Foo extends Bar { + int foo; // There is probably a better name that can be used +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidFieldNameMatchingMethodName +**Since:** 3.0 + +**Priority:** Medium (3) + +It can be confusing to have a field name with the same name as a method. While this is permitted, +having information (field) and actions (method) is not clear naming. Developers versed in +Smalltalk often prefer this approach as the methods denote accessor methods. + +**Example(s):** +``` +public class Foo { + Object bar; + // bar is data or an action or both? + void bar() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## NoPackage +**Since:** 3.3 + +**Priority:** Medium (3) + +Detects when a class or interface does not have a package definition. + +**Example(s):** +``` +// no package declaration +public class ClassInDefaultPackage { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## PackageCase +**Since:** 3.3 + +**Priority:** Medium (3) + +Detects when a package definition contains uppercase characters. + +**Example(s):** +``` +package com.MyCompany; // should be lowercase name + +public class SomeClass { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## MisleadingVariableName +**Since:** 3.4 + +**Priority:** Medium (3) + +Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing. + +**Example(s):** +``` +public class Foo { + private int m_foo; // OK + public void bar(String m_baz) { // Bad + int m_boz = 42; // Bad + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## BooleanGetMethodName +**Since:** 4.0 + +**Priority:** Medium Low (4) + +Methods that return boolean results should be named as predicate statements to denote this. +I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get' +prefix for these methods. + +**Example(s):** +``` +public boolean getFoo(); // bad +public boolean isFoo(); // ok +public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|checkParameterizedMethods|false|Check parameterized methods| + +## ShortClassName +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Short Classnames with fewer than e.g. five characters are not recommended. + +**Example(s):** +``` +public class Foo { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|minimum|5|Number of characters that are required as a minimum for a class name.| + +## GenericsNaming +**Since:** 4.2.6 + +**Priority:** Medium Low (4) + +Names for references to generic values should be limited to a single uppercase letter. + +**Example(s):** +``` +public interface GenericDao extends BaseDao { + // This is ok... +} + +public interface GenericDao { + // Also this +} + +public interface GenericDao { + // 'e' should be an 'E' +} + +public interface GenericDao { + // 'EF' is not ok. +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/optimizations.md b/docs/pages/pmd/rules/java/optimizations.md new file mode 100644 index 000000000..9d3a8bf34 --- /dev/null +++ b/docs/pages/pmd/rules/java/optimizations.md @@ -0,0 +1,363 @@ +--- +title: Optimization +summary: These rules deal with different optimizations that generally apply to best practices. +permalink: pmd_rules_java_optimizations.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/optimizations.xml +--- +## LocalVariableCouldBeFinal +**Since:** 2.2 + +**Priority:** Medium (3) + +A local variable assigned only once can be declared final. + +**Example(s):** +``` +public class Bar { + public void foo () { + String txtA = "a"; // if txtA will not be assigned again it is better to do this: + final String txtB = "b"; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## MethodArgumentCouldBeFinal +**Since:** 2.2 + +**Priority:** Medium (3) + +A method argument that is never re-assigned within the method can be declared final. + +**Example(s):** +``` +public void foo1 (String param) { // do stuff with param never assigning it + +} + +public void foo2 (final String param) { // better, do stuff with param never assigning it + +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidInstantiatingObjectsInLoops +**Since:** 2.2 + +**Priority:** Medium (3) + +New objects created within loops should be checked to see if they can created outside them and reused. + +**Example(s):** +``` +public class Something { + public static void main( String as[] ) { + for (int i = 0; i < 10; i++) { + Foo f = new Foo(); // Avoid this whenever you can it's really expensive + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UseArrayListInsteadOfVector +**Since:** 3.0 + +**Priority:** Medium (3) + +ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. + +**Example(s):** +``` +public class SimpleTest extends TestCase { + public void testX() { + Collection c1 = new Vector(); + Collection c2 = new ArrayList(); // achieves the same with much better performance + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## SimplifyStartsWith +**Since:** 3.1 + +**Priority:** Medium (3) + +Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0) +at the expense of some readability. + +**Example(s):** +``` +public class Foo { + + boolean checkIt(String x) { + return x.startsWith("a"); // suboptimal + } + + boolean fasterCheckIt(String x) { + return x.charAt(0) == 'a'; // faster approach + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseStringBufferForStringAppends +**Since:** 3.1 + +**Priority:** Medium (3) + +The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer. +If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or +threadsafe StringBuffer is recommended to avoid this. + +**Example(s):** +``` +public class Foo { + void bar() { + String a; + a = "foo"; + a += " bar"; + // better would be: + // StringBuilder a = new StringBuilder("foo"); + // a.append(" bar); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UseArraysAsList +**Since:** 3.5 + +**Priority:** Medium (3) + +The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from +an array of objects. It is faster than executing a loop to copy all the elements of the array one by one. + +**Example(s):** +``` +public class Test { + public void foo(Integer[] ints) { + // could just use Arrays.asList(ints) + List l= new ArrayList(10); + for (int i=0; i< 100; i++) { + l.add(ints[i]); + } + for (int i=0; i< 100; i++) { + l.add(a[i].toString()); // won't trigger the rule + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidArrayLoops +**Since:** 3.5 + +**Priority:** Medium (3) + +Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead. + +**Example(s):** +``` +public class Test { + public void bar() { + int[] a = new int[10]; + int[] b = new int[10]; + for (int i=0;i<10;i++) { + b[i]=a[i]; + } + } +} + // this will trigger the rule + for (int i=0;i<10;i++) { + b[i]=a[c[i]]; + } + + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnnecessaryWrapperObjectCreation +**Since:** 3.8 + +**Priority:** Medium (3) + +Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects +just to create the primitive forms. Using these avoids the cost of creating objects that also need to be +garbage-collected later. + +**Example(s):** +``` +public int convert(String s) { + int i, i2; + + i = Integer.valueOf(s).intValue(); // this wastes an object + i = Integer.parseInt(s); // this is better + + i2 = Integer.valueOf(i).intValue(); // this wastes an object + i2 = i; // this is better + + String s3 = Integer.valueOf(i2).toString(); // this wastes an object + s3 = Integer.toString(i2); // this is better + + return i2; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AddEmptyString +**Since:** 4.0 + +**Priority:** Medium (3) + +The conversion of literals to strings by concatenating them with empty strings is inefficient. +It is much better to use one of the type-specific toString() methods instead. + +**Example(s):** +``` +String s = "" + 123; // inefficient +String t = Integer.toString(456); // preferred approach +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## RedundantFieldInitializer +**Since:** 5.0 + +**Priority:** Medium (3) + +Java will initialize fields with known default values so any explicit initialization of those same defaults +is redundant and results in a larger class file (approximately three additional bytecode instructions per field). + +**Example(s):** +``` +public class C { + boolean b = false; // examples of redundant initializers + byte by = 0; + short s = 0; + char c = 0; + int i = 0; + long l = 0; + + float f = .0f; // all possible float literals + doable d = 0d; // all possible double literals + Object o = null; + + MyClass mca[] = null; + int i1 = 0, ia1[] = null; + + class Nested { + boolean b = false; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## PrematureDeclaration +**Since:** 5.0 + +**Priority:** Medium (3) + +Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception. + +**Example(s):** +``` +public int getLength(String[] strings) { + + int length = 0; // declared prematurely + + if (strings == null || strings.length == 0) return 0; + + for (String str : strings) { + length += str.length(); + } + + return length; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/strictexception.md b/docs/pages/pmd/rules/java/strictexception.md new file mode 100644 index 000000000..967fab482 --- /dev/null +++ b/docs/pages/pmd/rules/java/strictexception.md @@ -0,0 +1,342 @@ +--- +title: Strict Exceptions +summary: These rules provide some strict guidelines about throwing and catching exceptions. +permalink: pmd_rules_java_strictexception.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/strictexception.xml +--- +## AvoidCatchingThrowable +**Since:** 1.2 + +**Priority:** Medium (3) + +Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as +OutOfMemoryError that should be exposed and managed separately. + +**Example(s):** +``` +public void bar() { + try { + // do something + } catch (Throwable th) { // should not catch Throwable + th.printStackTrace(); + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## SignatureDeclareThrowsException +**Since:** 1.2 + +**Priority:** Medium (3) + +Methods that declare the generic Exception as a possible throwable are not very helpful since their +failure modes are unclear. Use a class derived from RuntimeException or a more specific checked exception. + +**Example(s):** +``` +public void foo() throws Exception { +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ExceptionAsFlowControl +**Since:** 1.8 + +**Priority:** Medium (3) + +Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging. +Either add the necessary validation or use an alternate control structure. + +**Example(s):** +``` +public void bar() { + try { + try { + } catch (Exception e) { + throw new WrapperException(e); + // this is essentially a GOTO to the WrapperException catch block + } + } catch (WrapperException e) { + // do some more stuff + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AvoidCatchingNPE +**Since:** 1.8 + +**Priority:** Medium (3) + +Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the +original error, causing other, more subtle problems later on. + +**Example(s):** +``` +public class Foo { + void bar() { + try { + // do something + } catch (NullPointerException npe) { + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidThrowingRawExceptionTypes +**Since:** 1.8 + +**Priority:** High (1) + +Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, +Exception, or Error, use a subclassed exception or error instead. + +**Example(s):** +``` +public class Foo { + public void bar() throws Exception { + throw new Exception(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidThrowingNullPointerException +**Since:** 1.8 + +**Priority:** High (1) + +Avoid throwing NullPointerExceptions. These are confusing because most people will assume that the +virtual machine threw it. Consider using an IllegalArgumentException instead; this will be +clearly seen as a programmer-initiated exception. + +**Example(s):** +``` +public class Foo { + void bar() { + throw new NullPointerException(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidRethrowingException +**Since:** 3.8 + +**Priority:** Medium (3) + +Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. + +**Example(s):** +``` +public void bar() { + try { + // do something + } catch (SomeException se) { + throw se; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotExtendJavaLangError +**Since:** 4.0 + +**Priority:** Medium (3) + +Errors are system exceptions. Do not extend them. + +**Example(s):** +``` +public class Foo extends Error { } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DoNotThrowExceptionInFinally +**Since:** 4.2 + +**Priority:** Medium Low (4) + +Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions +or code defects. +Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block" + +**Example(s):** +``` +public class Foo { + public void bar() { + try { + // Here do some stuff + } catch( Exception e) { + // Handling the issue + } finally { + // is this really a good idea ? + throw new Exception(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidThrowingNewInstanceOfSameException +**Since:** 4.2.5 + +**Priority:** Medium (3) + +Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to +code size and runtime complexity. + +**Example(s):** +``` +public void bar() { + try { + // do something + } catch (SomeException se) { + // harmless comment + throw new SomeException(se); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidCatchingGenericException +**Since:** 4.2.6 + +**Priority:** Medium (3) + +Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block + +**Example(s):** +``` +package com.igate.primitive; + +public class PrimitiveType { + + public void downCastPrimitiveType() { + try { + System.out.println(" i [" + i + "]"); + } catch(Exception e) { + e.printStackTrace(); + } catch(RuntimeException e) { + e.printStackTrace(); + } catch(NullPointerException e) { + e.printStackTrace(); + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidLosingExceptionInformation +**Since:** 4.2.6 + +**Priority:** Medium High (2) + +Statements in a catch block that invoke accessors on the exception without using the information +only add to code size. Either remove the invocation, or use the return result. + +**Example(s):** +``` +public void bar() { + try { + // do something + } catch (SomeException se) { + se.getMessage(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/strings.md b/docs/pages/pmd/rules/java/strings.md new file mode 100644 index 000000000..d2a7e2a65 --- /dev/null +++ b/docs/pages/pmd/rules/java/strings.md @@ -0,0 +1,415 @@ +--- +title: String and StringBuffer +summary: These rules deal with different issues that can arise with manipulation of the String, StringBuffer, or StringBuilder instances. +permalink: pmd_rules_java_strings.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/strings.xml +--- +## AvoidDuplicateLiterals +**Since:** 1.0 + +**Priority:** Medium (3) + +Code containing duplicate String literals can usually be improved by declaring the String as a constant field. + +**Example(s):** +``` +private void bar() { + buz("Howdy"); + buz("Howdy"); + buz("Howdy"); + buz("Howdy"); + } + private void buz(String x) {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|exceptionfile||File containing strings to skip (one string per line), only used if ignore list is not set| +|separator|,|Ignore list separator| +|exceptionList||Strings to ignore| +|maxDuplicateLiterals|4|Max duplicate literals| +|minimumLength|3|Minimum string length to check| +|skipAnnotations|false|Skip literals within annotations| + +## StringInstantiation +**Since:** 1.0 + +**Priority:** Medium High (2) + +Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared. + +**Example(s):** +``` +private String bar = new String("bar"); // just do a String bar = "bar"; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## StringToString +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid calling toString() on objects already known to be string instances; this is unnecessary. + +**Example(s):** +``` +private String baz() { + String bar = "howdy"; + return bar.toString(); +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## InefficientStringBuffering +**Since:** 3.4 + +**Priority:** Medium (3) + +Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will +need to be be created and destroyed by the JVM. + +**Example(s):** +``` +// Avoid this, two buffers are actually being created here +StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir")); + + // do this instead +StringBuffer sb = new StringBuffer("tmp = "); +sb.append(System.getProperty("java.io.tmpdir")); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnnecessaryCaseChange +**Since:** 3.3 + +**Priority:** Medium (3) + +Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() + +**Example(s):** +``` +boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz") + +boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase() +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UseStringBufferLength +**Since:** 3.4 + +**Priority:** Medium (3) + +Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") +or StringBuffer.toString().length() == ... + +**Example(s):** +``` +StringBuffer sb = new StringBuffer(); + +if (sb.toString().equals("")) {} // inefficient + +if (sb.length() == 0) {} // preferred +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## AppendCharacterWithChar +**Since:** 3.5 + +**Priority:** Medium (3) + +Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. + +**Example(s):** +``` +StringBuffer sb = new StringBuffer(); +sb.append("a"); // avoid this + +StringBuffer sb = new StringBuffer(); +sb.append('a'); // use this instead +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ConsecutiveAppendsShouldReuse +**Since:** 5.1 + +**Priority:** Medium (3) + +Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performance +by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found [here](https://github.com/pmd/pmd/issues/202#issuecomment-274349067) + +**Example(s):** +``` +String foo = " "; + +StringBuffer buf = new StringBuffer(); +buf.append("Hello"); // poor +buf.append(foo); +buf.append("World"); + +StringBuffer buf = new StringBuffer(); +buf.append("Hello").append(foo).append("World"); // good +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ConsecutiveLiteralAppends +**Since:** 3.5 + +**Priority:** Medium (3) + +Consecutively calling StringBuffer/StringBuilder.append with String literals + +**Example(s):** +``` +StringBuffer buf = new StringBuffer(); +buf.append("Hello").append(" ").append("World"); // poor +buf.append("Hello World"); // good +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|threshold|1|Max consecutive appends| + +## UseIndexOfChar +**Since:** 3.5 + +**Priority:** Medium (3) + +Use String.indexOf(char) when checking for the index of a single character; it executes faster. + +**Example(s):** +``` +String s = "hello world"; + // avoid this +if (s.indexOf("d") {} + // instead do this +if (s.indexOf('d') {} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## InefficientEmptyStringCheck +**Since:** 3.6 + +**Priority:** Medium (3) + +String.trim().length() is an inefficient way to check if a String is really empty, as it +creates a new String object just to check its size. Consider creating a static function that +loops through a string, checking Character.isWhitespace() on each character and returning +false if a non-whitespace character is found. You can refer to Apache's StringUtils#isBlank (in commons-lang) +or Spring's StringUtils#hasText (in the Springs framework) for existing implementations. + +**Example(s):** +``` +public void bar(String string) { + if (string != null && string.trim().size() > 0) { + doSomething(); + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## InsufficientStringBufferDeclaration +**Since:** 3.6 + +**Priority:** Medium (3) + +Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times +during runtime. This rule attempts to determine the total number the characters that are actually +passed into StringBuffer.append(), but represents a best guess "worst case" scenario. An empty +StringBuffer/StringBuilder constructor initializes the object to 16 characters. This default +is assumed if the length of the constructor can not be determined. + +**Example(s):** +``` +StringBuffer bad = new StringBuffer(); +bad.append("This is a long string that will exceed the default 16 characters"); + +StringBuffer good = new StringBuffer(41); +good.append("This is a long string, which is pre-sized"); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UselessStringValueOf +**Since:** 3.8 + +**Priority:** Medium (3) + +No need to call String.valueOf to append to a string; just use the valueOf() argument directly. + +**Example(s):** +``` +public String convert(int i) { + String s; + s = "a" + String.valueOf(i); // not required + s = "a" + i; // preferred approach + return s; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## StringBufferInstantiationWithChar +**Since:** 3.9 + +**Priority:** Medium Low (4) + +Individual character values provided as initialization arguments will be converted into integers. +This can lead to internal buffer sizes that are larger than expected. Some examples: + +new StringBuffer() // 16 +new StringBuffer(6) // 6 +new StringBuffer("hello world") // 11 + 16 = 27 +new StringBuffer('A') // chr(A) = 65 +new StringBuffer("A") // 1 + 16 = 17 + +new StringBuilder() // 16 +new StringBuilder(6) // 6 +new StringBuilder("hello world") // 11 + 16 = 27 +new StringBuilder('C') // chr(C) = 67 +new StringBuilder("A") // 1 + 16 = 17 + +**Example(s):** +``` +// misleading instantiation, these buffers + // are actually sized to 99 characters long +StringBuffer sb1 = new StringBuffer('c'); +StringBuilder sb2 = new StringBuilder('c'); + +// in these forms, just single characters are allocated +StringBuffer sb3 = new StringBuffer("c"); +StringBuilder sb4 = new StringBuilder("c"); +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UseEqualsToCompareStrings +**Since:** 4.1 + +**Priority:** Medium (3) + +Using '==' or '!=' to compare strings only works if intern version is used on both sides. +Use the equals() method instead. + +**Example(s):** +``` +public boolean test(String s) { + if (s == "one") return true; // unreliable + if ("two".equals(s)) return true; // better + return false; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidStringBufferField +**Since:** 4.2 + +**Priority:** Medium (3) + +StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks +if held within objects with long lifetimes. + +**Example(s):** +``` +public class Foo { + private StringBuffer buffer; // potential memory leak as an instance variable; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/java/sunsecure.md b/docs/pages/pmd/rules/java/sunsecure.md new file mode 100644 index 000000000..cee12eeed --- /dev/null +++ b/docs/pages/pmd/rules/java/sunsecure.md @@ -0,0 +1,60 @@ +--- +title: Security Code Guidelines +summary: These rules check the security guidelines from Sun, published at http://java.sun.com/security/seccodeguide.html#gcg +permalink: pmd_rules_java_sunsecure.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/sunsecure.xml +--- +## MethodReturnsInternalArray +**Since:** 2.2 + +**Priority:** Medium (3) + +Exposing internal arrays to the caller violates object encapsulation since elements can be +removed or replaced outside of the object that owns it. It is safer to return a copy of the array. + +**Example(s):** +``` +public class SecureSystem { + UserData [] ud; + public UserData [] getUserData() { + // Don't return directly the internal array, return a copy + return ud; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ArrayIsStoredDirectly +**Since:** 2.2 + +**Priority:** Medium (3) + +Constructors and methods receiving arrays should clone objects and store the copy. +This prevents future changes from the user from affecting the original array. + +**Example(s):** +``` +public class Foo { + private String [] x; + public void foo (String [] param) { + // Don't do this, make a copy of the array at least + this.x=param; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/unnecessary.md b/docs/pages/pmd/rules/java/unnecessary.md new file mode 100644 index 000000000..47d325c5b --- /dev/null +++ b/docs/pages/pmd/rules/java/unnecessary.md @@ -0,0 +1,316 @@ +--- +title: Unnecessary +summary: The Unnecessary Ruleset contains a collection of rules for unnecessary code. +permalink: pmd_rules_java_unnecessary.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/unnecessary.xml +--- +## UnnecessaryConversionTemporary +**Since:** 0.1 + +**Priority:** Medium (3) + +Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods +on the wrapper classes instead. + +**Example(s):** +``` +public String convert(int x) { + String foo = new Integer(x).toString(); // this wastes an object + + return Integer.toString(x); // preferred approach +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnnecessaryReturn +**Since:** 1.3 + +**Priority:** Medium (3) + +Avoid the use of unnecessary return statements. + +**Example(s):** +``` +public class Foo { + public void bar() { + int x = 42; + return; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnnecessaryFinalModifier +**Since:** 3.0 + +**Priority:** Medium (3) + +When a class has the final modifier, all the methods are automatically final and do not need to be +tagged as such. Similarly, methods that can't be overridden (private methods, methods of anonymous classes, +methods of enum instance) do not need to be tagged either. + +**Example(s):** +``` +public final class Foo { + // This final modifier is not necessary, since the class is final + // and thus, all methods are final + private final void foo() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UselessOverridingMethod +**Since:** 3.3 + +**Priority:** Medium (3) + +The overriding method merely calls the same method defined in a superclass. + +**Example(s):** +``` +public void foo(String bar) { + super.foo(bar); // why bother overriding? +} + +public String foo() { + return super.foo(); // why bother overriding? +} + +@Id +public Long getId() { + return super.getId(); // OK if 'ignoreAnnotations' is false, which is the default behavior +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|ignoreAnnotations|false|Ignore annotations| + +## UselessOperationOnImmutable +**Since:** 3.5 + +**Priority:** Medium (3) + +An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself +since the result of the operation is a new object. Therefore, ignoring the operation result is an error. + +**Example(s):** +``` +import java.math.*; + +class Test { + void method1() { + BigDecimal bd=new BigDecimal(10); + bd.add(new BigDecimal(5)); // this will trigger the rule + } + void method2() { + BigDecimal bd=new BigDecimal(10); + bd = bd.add(new BigDecimal(5)); // this won't trigger the rule + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedNullCheckInEquals +**Since:** 3.5 + +**Priority:** Medium (3) + +After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object's equals() method. + +**Example(s):** +``` +public class Test { + + public String method1() { return "ok";} + public String method2() { return null;} + + public void method(String a) { + String b; + // I don't know it method1() can be "null" + // but I know "a" is not null.. + // I'd better write a.equals(method1()) + + if (a!=null && method1().equals(a)) { // will trigger the rule + //whatever + } + + if (method1().equals(a) && a != null) { // won't trigger the rule + //whatever + } + + if (a!=null && method1().equals(b)) { // won't trigger the rule + //whatever + } + + if (a!=null && "LITERAL".equals(a)) { // won't trigger the rule + //whatever + } + + if (a!=null && !a.equals("go")) { // won't trigger the rule + a=method2(); + if (method1().equals(a)) { + //whatever + } + } +} +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UselessParentheses +**Since:** 5.0 + +**Priority:** Medium Low (4) + +Useless parentheses should be removed. + +**Example(s):** +``` +public class Foo { + + private int _bar1; + private Integer _bar2; + + public void setBar(int n) { + _bar1 = Integer.valueOf((n)); // here + _bar2 = (n); // and here + } + +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UselessQualifiedThis +**Since:** 5.4.0 + +**Priority:** Medium (3) + +Look for qualified this usages in the same class. + +**Example(s):** +``` +public class Foo { + final Foo otherFoo = Foo.this; // use "this" directly + + public void doSomething() { + final Foo anotherFoo = Foo.this; // use "this" directly + } + + private ActionListener returnListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + doSomethingWithQualifiedThis(Foo.this); // This is fine + } + }; + } + + private class Foo3 { + final Foo myFoo = Foo.this; // This is fine + } + + private class Foo2 { + final Foo2 myFoo2 = Foo2.this; // Use "this" direclty + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## UnnecessaryModifier +**Since:** 1.02 + +**Priority:** Medium (3) + +Fields in interfaces and annotations are automatically `public static final`, and methods are `public abstract`. +Classes, interfaces or annotations nested in an interface or annotation are automatically `public static` +(all nested interfaces and annotations are automatically static). +Nested enums are automatically `static`. +For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous. + +**Example(s):** +``` +public @interface Annotation { + public abstract void bar(); // both abstract and public are ignored by the compiler + public static final int X = 0; // public, static, and final all ignored + public static class Bar {} // public, static ignored + public static interface Baz {} // ditto +} +public interface Foo { + public abstract void bar(); // both abstract and public are ignored by the compiler + public static final int X = 0; // public, static, and final all ignored + public static class Bar {} // public, static ignored + public static interface Baz {} // ditto +} +public class Bar { + public static interface Baz {} // static ignored + public static enum FoorBar { // static ignored + FOO; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/java/unusedcode.md b/docs/pages/pmd/rules/java/unusedcode.md new file mode 100644 index 000000000..9944476ce --- /dev/null +++ b/docs/pages/pmd/rules/java/unusedcode.md @@ -0,0 +1,102 @@ +--- +title: Unused Code +summary: The Unused Code ruleset contains rules that find unused or ineffective code. +permalink: pmd_rules_java_unusedcode.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../pmd-java/src/main/resources/rulesets/java/unusedcode.xml +--- +## UnusedPrivateField +**Since:** 0.1 + +**Priority:** Medium (3) + +Detects when a private field is declared and/or assigned a value, but not used. + +**Example(s):** +``` +public class Something { + private static int FOO = 2; // Unused + private int i = 5; // Unused + private int j = 6; + public int addOne() { + return j++; + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedLocalVariable +**Since:** 0.1 + +**Priority:** Medium (3) + +Detects when a local variable is declared and/or assigned, but not used. + +**Example(s):** +``` +public class Foo { + public void doSomething() { + int i = 5; // Unused + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedPrivateMethod +**Since:** 0.7 + +**Priority:** Medium (3) + +Unused Private Method detects when a private method is declared but is unused. + +**Example(s):** +``` +public class Something { + private void foo() {} // unused +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedFormalParameter +**Since:** 0.8 + +**Priority:** Medium (3) + +Avoid passing parameters to methods or constructors without actually referencing them in the method body. + +**Example(s):** +``` +public class Foo { + private void bar(String howdy) { + // howdy is not used + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkAll|false|Check all methods, including non-private ones| + diff --git a/docs/pages/pmd/rules/javascript.md b/docs/pages/pmd/rules/javascript.md deleted file mode 100644 index 27ec21b57..000000000 --- a/docs/pages/pmd/rules/javascript.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: JavaScript Rules -sidebar: pmd_sidebar -permalink: pmd_rules_javascript.html -folder: pmd/rules ---- diff --git a/docs/pages/pmd/rules/jsp.md b/docs/pages/pmd/rules/jsp.md index a95ff37fa..cd46ce419 100644 --- a/docs/pages/pmd/rules/jsp.md +++ b/docs/pages/pmd/rules/jsp.md @@ -1,6 +1,26 @@ --- -title: JSP Rules -sidebar: pmd_sidebar +title: Java Server Pages Rules permalink: pmd_rules_jsp.html folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [Basic JSF](pmd_rules_jsp_basic-jsf.html): Rules concerning basic JSF guidelines. +* [Basic JSP](pmd_rules_jsp_basic.html): Rules concerning basic JSP guidelines. + +## Basic JSF +* [DontNestJsfInJstlIteration](pmd_rules_jsp_basic-jsf.html#dontnestjsfinjstliteration): Do not nest JSF component custom actions inside a custom action that iterates over its body. + +## Basic JSP +* [NoLongScripts](pmd_rules_jsp_basic.html#nolongscripts): Scripts should be part of Tag Libraries, rather than part of JSP pages. +* [NoScriptlets](pmd_rules_jsp_basic.html#noscriptlets): Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of J... +* [NoInlineStyleInformation](pmd_rules_jsp_basic.html#noinlinestyleinformation): Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FON... +* [NoClassAttribute](pmd_rules_jsp_basic.html#noclassattribute): Do not use an attribute called 'class'. Use "styleclass" for CSS styles. +* [NoJspForward](pmd_rules_jsp_basic.html#nojspforward): Do not do a forward from within a JSP file. +* [IframeMissingSrcAttribute](pmd_rules_jsp_basic.html#iframemissingsrcattribute): IFrames which are missing a src element can cause security information popups in IE if you are ac... +* [NoHtmlComments](pmd_rules_jsp_basic.html#nohtmlcomments): In a production system, HTML comments increase the payload between the application server to th... +* [DuplicateJspImports](pmd_rules_jsp_basic.html#duplicatejspimports): Avoid duplicate import statements inside JSP's. +* [JspEncoding](pmd_rules_jsp_basic.html#jspencoding): A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. +* [NoInlineScript](pmd_rules_jsp_basic.html#noinlinescript): Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attri... +* [NoUnsanitizedJSPExpression](pmd_rules_jsp_basic.html#nounsanitizedjspexpression): Avoid using expressions without escaping / sanitizing. This could lead to cross site scripting - ... + diff --git a/docs/pages/pmd/rules/jsp/basic-jsf.md b/docs/pages/pmd/rules/jsp/basic-jsf.md new file mode 100644 index 000000000..ddf417e7f --- /dev/null +++ b/docs/pages/pmd/rules/jsp/basic-jsf.md @@ -0,0 +1,33 @@ +--- +title: Basic JSF +summary: Rules concerning basic JSF guidelines. +permalink: pmd_rules_jsp_basic-jsf.html +folder: pmd/rules/jsp +sidebaractiveurl: /pmd_rules_jsp.html +editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic-jsf.xml +--- +## DontNestJsfInJstlIteration +**Since:** 3.6 + +**Priority:** Medium (3) + +Do not nest JSF component custom actions inside a custom action that iterates over its body. + +**Example(s):** +``` +
      + +
    • +
      +
    +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/jsp/basic.md b/docs/pages/pmd/rules/jsp/basic.md new file mode 100644 index 000000000..f5e1a205c --- /dev/null +++ b/docs/pages/pmd/rules/jsp/basic.md @@ -0,0 +1,293 @@ +--- +title: Basic JSP +summary: Rules concerning basic JSP guidelines. +permalink: pmd_rules_jsp_basic.html +folder: pmd/rules/jsp +sidebaractiveurl: /pmd_rules_jsp.html +editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic.xml +--- +## NoLongScripts +**Since:** 3.6 + +**Priority:** Medium High (2) + +Scripts should be part of Tag Libraries, rather than part of JSP pages. + +**Example(s):** +``` + + + + + + +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoScriptlets +**Since:** 3.6 + +**Priority:** Medium (3) + +Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. + +**Example(s):** +``` + + +<% +response.setHeader("Pragma", "No-cache"); +%> + + + String title = "Hello world!"; + + +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoInlineStyleInformation +**Since:** 3.6 + +**Priority:** Medium (3) + +Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FONT> tags, or attributes like "align='center'". + +**Example(s):** +``` +

    text

    +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## NoClassAttribute +**Since:** 3.6 + +**Priority:** Medium High (2) + +Do not use an attribute called 'class'. Use "styleclass" for CSS styles. + +**Example(s):** +``` + +

    Some text

    + +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoJspForward +**Since:** 3.6 + +**Priority:** Medium (3) + +Do not do a forward from within a JSP file. + +**Example(s):** +``` + +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## IframeMissingSrcAttribute +**Since:** 3.6 + +**Priority:** Medium High (2) + +IFrames which are missing a src element can cause security information popups in IE if you are accessing the page +through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 + +**Example(s):** +``` +bad example><BODY> +<iframe></iframe> +</BODY> </HTML> + +<HTML><title>good example><BODY> +<iframe src="foo"></iframe> +</BODY> </HTML> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoHtmlComments +**Since:** 3.6 + +**Priority:** Medium High (2) + +In a production system, HTML comments increase the payload + between the application server to the client, and serve + little other purpose. Consider switching to JSP comments. + +**Example(s):** +``` +<HTML><title>bad example><BODY> +<!-- HTML comment --> +</BODY> </HTML> + +<HTML><title>good example><BODY> +<%-- JSP comment --%> +</BODY> </HTML> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## DuplicateJspImports +**Since:** 3.7 + +**Priority:** Medium (3) + +Avoid duplicate import statements inside JSP's. + +**Example(s):** +``` +<%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%><html><body><b><img src=\"<%=Some.get()%>/foo\">xx</img>text</b></body></html> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## JspEncoding +**Since:** 4.0 + +**Priority:** Medium (3) + +A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. + +**Example(s):** +``` +Most browsers should be able to interpret the following headers: + + <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + + <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoInlineScript +**Since:** 4.0 + +**Priority:** Medium (3) + +Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the "script" element. +Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth. + +**Example(s):** +``` +Most browsers should be able to interpret the following headers: + + <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + + <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## NoUnsanitizedJSPExpression +**Since:** 5.1.4 + +**Priority:** Medium (3) + +Avoid using expressions without escaping / sanitizing. This could lead to cross site scripting - as the expression +would be interpreted by the browser directly (e.g. "<script>alert('hello');</script>"). + +**Example(s):** +``` +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +${expression} <!-- don't use this --> +${fn:escapeXml(expression)} <!-- instead, escape it --> +<c:out value="${expression}" /> <!-- or use c:out --> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/plsql.md b/docs/pages/pmd/rules/plsql.md index c80914808..a4091e0d6 100644 --- a/docs/pages/pmd/rules/plsql.md +++ b/docs/pages/pmd/rules/plsql.md @@ -1,6 +1,37 @@ --- title: PLSQL Rules -sidebar: pmd_sidebar permalink: pmd_rules_plsql.html folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [Code Size](pmd_rules_plsql_codesize.html): The Code Size ruleset contains rules that find problems related to code size or complexity. +* [PLSQL DATETIME](pmd_rules_plsql_dates.html): The Dates ruleset deals with PLSQL DATETIME usages. +* [Strict Syntax](pmd_rules_plsql_strictsyntax.html): The Strict Syntax ruleset contains rules that highlight invalid plsql syntax, which works, but should be avoided. +* [Tom Kyte's Despair](pmd_rules_plsql_TomKytesDespair.html): Rules based on Thomas Kyte's recommendations on http://asktom.oracle.com/ and http://tkyte.blogspot.com/. + +## Code Size +* [NPathComplexity](pmd_rules_plsql_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [ExcessiveMethodLength](pmd_rules_plsql_codesize.html#excessivemethodlength): When methods are excessively long this usually indicates that the method is doing more than itsna... +* [ExcessiveParameterList](pmd_rules_plsql_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... +* [ExcessiveObjectLength](pmd_rules_plsql_codesize.html#excessiveobjectlength): Excessive object line lengths are usually indications that the object may be burdened with excess... +* [ExcessiveTypeLength](pmd_rules_plsql_codesize.html#excessivetypelength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [ExcessivePackageBodyLength](pmd_rules_plsql_codesize.html#excessivepackagebodylength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [ExcessivePackageSpecificationLength](pmd_rules_plsql_codesize.html#excessivepackagespecificationlength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [CyclomaticComplexity](pmd_rules_plsql_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [TooManyFields](pmd_rules_plsql_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... +* [NcssMethodCount](pmd_rules_plsql_codesize.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NcssObjectCount](pmd_rules_plsql_codesize.html#ncssobjectcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [TooManyMethods](pmd_rules_plsql_codesize.html#toomanymethods): A package or type with too many methods is probably a good suspect for refactoring, in order to r... + +## PLSQL DATETIME +* [TO_DATEWithoutDateFormat](pmd_rules_plsql_dates.html#to_datewithoutdateformat): TO_DATE without date format- use TO_DATE(expression, date-format) +* [TO_DATE_TO_CHAR](pmd_rules_plsql_dates.html#to_date_to_char): TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) +* [TO_TIMESTAMPWithoutDateFormat](pmd_rules_plsql_dates.html#to_timestampwithoutdateformat): TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) + +## Strict Syntax +* [MisplacedPragma](pmd_rules_plsql_strictsyntax.html#misplacedpragma): Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block,but the cod... + +## Tom Kyte's Despair +* [TomKytesDespair](pmd_rules_plsql_TomKytesDespair.html#tomkytesdespair): "WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR + diff --git a/docs/pages/pmd/rules/plsql/TomKytesDespair.md b/docs/pages/pmd/rules/plsql/TomKytesDespair.md new file mode 100644 index 000000000..6f9784c8b --- /dev/null +++ b/docs/pages/pmd/rules/plsql/TomKytesDespair.md @@ -0,0 +1,68 @@ +--- +title: Tom Kyte's Despair +summary: Rules based on Thomas Kyte's recommendations on http://asktom.oracle.com/ and http://tkyte.blogspot.com/. +permalink: pmd_rules_plsql_TomKytesDespair.html +folder: pmd/rules/plsql +sidebaractiveurl: /pmd_rules_plsql.html +editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/TomKytesDespair.xml +--- +## TomKytesDespair +**Since:** 5.1 + +**Priority:** Medium (3) + +"WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE BODY update_planned_hrs +IS + +PROCEDURE set_new_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER, p_hours IN NUMBER) +IS +BEGIN + UPDATE employee_on_activity ea + SET ea.ea_planned_hours = p_hours + WHERE + ea.ea_emp_id = p_emp_id + AND ea.ea_proj_id = p_project_id; + +EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE_APPLICATION_ERROR (-20100, 'No such employee or project'); + +END set_new_planned; + +FUNCTION existing_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER) RETURN NUMBER + +IS + +existing_hours NUMBER(4); + +BEGIN + SELECT ea.ea_planned_hours INTO existing_hours + FROM employee_on_activity ea + WHERE + ea.ea_emp_id = p_emp_id + AND ea.ea_proj_id = p_project_id; + + RETURN (existing_hours); + + EXCEPTION + WHEN OTHERS THEN NULL; + + END existing_planned; + +END update_planned_hrs; +/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/plsql/codesize.md b/docs/pages/pmd/rules/plsql/codesize.md new file mode 100644 index 000000000..405da0ba8 --- /dev/null +++ b/docs/pages/pmd/rules/plsql/codesize.md @@ -0,0 +1,524 @@ +--- +title: Code Size +summary: The Code Size ruleset contains rules that find problems related to code size or complexity. +permalink: pmd_rules_plsql_codesize.html +folder: pmd/rules/plsql +sidebaractiveurl: /pmd_rules_plsql.html +editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/codesize.xml +--- +## NPathComplexity +**Since:** 5.1 + +**Priority:** Medium (3) + +The NPath complexity of a method is the number of acyclic execution paths through that method. +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability. + +**Example(s):** +``` +CREATE OR REPLACE +PROCEDURE bar AS BEGIN -- this is something more complex than it needs to be, + if (y) THEN -- it should be broken down into smaller methods or functions + for j IN 0 .. j-1 LOOP + if (j > r) THEN + doSomething; + while (f < 5 ) LOOP + anotherThing; + f := f - 27; + END LOOP; + else + tryThis(); + END IF; + END LOOP; + END IF; + if ( r - n > 45) THEN + while (doMagic) LOOP + findRabbits; + END LOOP; + END IF; + BEGIN + doSomethingDangerous(); + EXCEPTION WHEN FooException THEN + makeAmends; + BEGIN + dontDoItAgain; + EXCEPTION + WHEN OTHERS THEN + log_problem; + END; + END; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveMethodLength +**Since:** 5.1 + +**Priority:** Medium (3) + +When methods are excessively long this usually indicates that the method is doing more than its +name/signature might suggest. They also become challenging for others to digest since excessive +scrolling causes readers to lose focus. +Try to reduce the method length by creating helper methods and removing any copy/pasted code. + +**Example(s):** +``` +CREATE OR REPLACE +PROCEDURE doSomething BEGIN + DBMS_OUTPUT.PUT_LINE("Hello world!"); + DBMS_OUTPUT.PUT_LINE("Hello world!"); + -- 98 copies omitted for brevity. +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveParameterList +**Since:** 5.1 + +**Priority:** Medium (3) + +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. + +**Example(s):** +``` +CREATE OR REPLACE +PROCEDURE addPerson( -- too many arguments liable to be mixed up + birthYear pls_integer, birthMonth pls_integer, birthDate pls_integer, height pls_integer, weight pls_integer, ssn pls_integer) { + + . . . . +END ADDPERSON; + +CREATE OR REPLACE +PROCEDURE addPerson( -- preferred approach + birthdate DATE, measurements BodyMeasurements , ssn INTEGER) BEGIN + + . . . . +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveObjectLength +**Since:** 5.1 + +**Priority:** Medium (3) + +Excessive object line lengths are usually indications that the object may be burdened with excessive +responsibilities that could be provided by other objects. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +CREATE OR REPLACE +PACKAGE BODY Foo AS + PROCEDURE bar1 IS BEGIN + -- 1000 lines of code + END bar1; + PROCEDURE bar2 IS BEGIN + -- 1000 lines of code + END bar2; + PROCEDURE bar3 IS BEGIN + -- 1000 lines of code + END bar3; + + + PROCEDURE barN IS BEGIN + -- 1000 lines of code + END barn; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessiveTypeLength +**Since:** 5.1 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +CREATE OR REPLACE +TYPE BODY Foo AS + MEMBER PROCEDURE bar1 IS BEGIN + -- 1000 lines of code + END bar1; + MEMBER PROCEDURE bar2 IS BEGIN + -- 1000 lines of code + END bar2; + MEMBER PROCEDURE bar3 IS BEGIN + -- 1000 lines of code + END bar3; + + + MEMBER PROCEDURE barN IS BEGIN + -- 1000 lines of code + END barn; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessivePackageBodyLength +**Since:** 5.1 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +CREATE OR REPLACE +PACKAGE BODY Foo AS + PROCEDURE bar1 IS BEGIN + -- 1000 lines of code + END bar1; + PROCEDURE bar2 IS BEGIN + -- 1000 lines of code + END bar2; + PROCEDURE bar3 IS BEGIN + -- 1000 lines of code + END bar3; + + + PROCEDURE barN IS BEGIN + -- 1000 lines of code + END barn; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## ExcessivePackageSpecificationLength +**Since:** 5.1 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +CREATE OR REPLACE +PACKAGE Foo AS + PROCEDURE bar1 ; + PROCEDURE bar2 ; + PROCEDURE bar3 ; + + .. + + PROCEDURE barN ; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## CyclomaticComplexity +**Since:** 5.1 + +**Priority:** Medium (3) + +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. + +**Example(s):** +``` +-- Cyclomatic Complexity of 25 +CREATE OR REPLACE PACKAGE BODY pkg_pmd_working_sequence AS +1 PROCEDURE ty_logger IS BEGIN +2 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +3 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +4 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +5 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +6 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +7 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +8 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +9 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +10 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + END IF; +11 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +12 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +13 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +14 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +15 ELSIF false + THEN +16 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +17 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +18 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +19 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +20 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +21 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +22 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +23 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +24 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +25 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + END IF; + END IF; +END; + +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## TooManyFields +**Since:** 5.1 + +**Priority:** Medium (3) + +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field. + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE pkg_too_many_fields AS + C_CHAR_A CONSTANT CHAR(1 CHAR) := 'A'; + C_CHAR_B CONSTANT CHAR(1 CHAR) := 'B'; + ... + C_CHAR_Z CONSTANT CHAR(1 CHAR) := 'Z'; +END pkg_too_many_fields; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|maxfields|15|Max allowable fields| + +## NcssMethodCount +**Since:** 5.1 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE BODY AS + FUNCTION methd RETURN INTEGER IS + BEGIN + RETURN 1;; + END; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## NcssObjectCount +**Since:** 5.1 + +**Priority:** Medium (3) + +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given Oracle object. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE pkg_ + PROCEDURE Foo IS + BEGIN + --this class only has 6 NCSS lines + super(); + super(); + END; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## TooManyMethods +**Since:** 5.1 + +**Priority:** Medium (3) + +A package or type with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to +have more fine grained objects. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|maxmethods|1|The method count reporting threshold| + diff --git a/docs/pages/pmd/rules/plsql/dates.md b/docs/pages/pmd/rules/plsql/dates.md new file mode 100644 index 000000000..756465f62 --- /dev/null +++ b/docs/pages/pmd/rules/plsql/dates.md @@ -0,0 +1,133 @@ +--- +title: PLSQL DATETIME +summary: The Dates ruleset deals with PLSQL DATETIME usages. +permalink: pmd_rules_plsql_dates.html +folder: pmd/rules/plsql +sidebaractiveurl: /pmd_rules_plsql.html +editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/dates.xml +--- +## TO_DATEWithoutDateFormat +**Since:** 5.1 + +**Priority:** Medium (3) + +TO_DATE without date format- use TO_DATE(expression, date-format) + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE BODY date_utilities +IS + +-- Take single parameter, relyimg on current default NLS date format +FUNCTION to_date_single_parameter (p_date_string IN VARCHAR2) RETURN DATE +IS +BEGIN + RETURN TO_DATE(p_date_string); +END to_date_single_parameter ; + +-- Take 2 parameters, using an explicit date format string +FUNCTION to_date_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE +IS +BEGIN + TO_DATE(p_date_string, p_date_format); +END to_date_two_parameters ; + +-- Take 3 parameters, using an explicit date format string and an explicit language +FUNCTION to_date_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE +IS +BEGIN + TO_DATE(p_date_string, p_format_mask, p_nls_language); +END to_date_three_parameters ; + +END date_utilities ; +/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## TO_DATE_TO_CHAR +**Since:** 5.1 + +**Priority:** Medium (3) + +TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE BODY date_utilities +IS + +-- Take single parameter, relyimg on current default NLS date format +FUNCTION strip_time (p_date IN DATE) RETURN DATE +IS +BEGIN + RETURN TO_DATE(TO_CHAR(p_date)); +END strip_time ; + + +END date_utilities ; +/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## TO_TIMESTAMPWithoutDateFormat +**Since:** 5.1 + +**Priority:** Medium (3) + +TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE BODY date_utilities +IS + +-- Take single parameter, relyimg on current default NLS date format +FUNCTION to_timestamp_single_parameter (p_date_string IN VARCHAR2) RETURN DATE +IS +BEGIN + RETURN TO_TIMESTAMP(p_date_string); +END to_timestamp_single_parameter ; + +-- Take 2 parameters, using an explicit date format string +FUNCTION to_timestamp_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE +IS +BEGIN + TO_TIMESTAMP(p_date_string, p_date_format); +END to_timestamp_two_parameters ; + +-- Take 3 parameters, using an explicit date format string and an explicit language +FUNCTION to_timestamp_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE +IS +BEGIN + TO_TIMESTAMP(p_date_string, p_format_mask, p_nls_language); +END to_timestamp_three_parameters ; + +END date_utilities ; +/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/plsql/strictsyntax.md b/docs/pages/pmd/rules/plsql/strictsyntax.md new file mode 100644 index 000000000..dc408f128 --- /dev/null +++ b/docs/pages/pmd/rules/plsql/strictsyntax.md @@ -0,0 +1,46 @@ +--- +title: Strict Syntax +summary: The Strict Syntax ruleset contains rules that highlight invalid plsql syntax, which works, but should be avoided. +permalink: pmd_rules_plsql_strictsyntax.html +folder: pmd/rules/plsql +sidebaractiveurl: /pmd_rules_plsql.html +editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/strictsyntax.xml +--- +## MisplacedPragma +**Since:** 5.5.2 + +**Priority:** Medium (3) + +Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block, +but the code does not complain, when being compiled on the 11g DB. +https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#BABIIHBJ + +**Example(s):** +``` +create or replace package inline_pragma_error is + +end; +/ + +create or replace package body inline_pragma_error is + procedure do_transaction(p_input_token in varchar(200)) is + PRAGMA AUTONOMOUS_TRANSACTION; /* this is correct place for PRAGMA */ + begin + PRAGMA AUTONOMOUS_TRANSACTION; /* this is the wrong place for PRAGMA -> violation */ + /* do something */ + COMMIT; + end do_transaction; + +end inline_pragma_error; +/ +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/vf.md b/docs/pages/pmd/rules/vf.md new file mode 100644 index 000000000..e0ef040ab --- /dev/null +++ b/docs/pages/pmd/rules/vf.md @@ -0,0 +1,13 @@ +--- +title: Salesforce VisualForce Rules +permalink: pmd_rules_vf.html +folder: pmd/rules +--- +List of rulesets and rules contained in each ruleset. + +* [Basic VF](pmd_rules_vf_security.html): Rules concerning basic VF guidelines. + +## Basic VF +* [VfUnescapeEl](pmd_rules_vf_security.html#vfunescapeel): Avoid unescaped user controlled content in EL as it results in XSS. +* [VfCsrf](pmd_rules_vf_security.html#vfcsrf): Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. + diff --git a/docs/pages/pmd/rules/vf/security.md b/docs/pages/pmd/rules/vf/security.md new file mode 100644 index 000000000..fe133ea91 --- /dev/null +++ b/docs/pages/pmd/rules/vf/security.md @@ -0,0 +1,46 @@ +--- +title: Basic VF +summary: Rules concerning basic VF guidelines. +permalink: pmd_rules_vf_security.html +folder: pmd/rules/vf +sidebaractiveurl: /pmd_rules_vf.html +editmepath: ../pmd-visualforce/src/main/resources/rulesets/vf/security.xml +--- +## VfUnescapeEl +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid unescaped user controlled content in EL as it results in XSS. + +**Example(s):** +``` +<apex:outputText value="Potential XSS is {! here }" escape="false" /> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## VfCsrf +**Since:** 5.6.0 + +**Priority:** Medium (3) + +Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. + +**Example(s):** +``` +<apex:page controller="AcRestActionsController" action="{!csrfInitMethod}" > +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + diff --git a/docs/pages/pmd/rules/vm.md b/docs/pages/pmd/rules/vm.md index 0cc4f3a95..e74f8c20c 100644 --- a/docs/pages/pmd/rules/vm.md +++ b/docs/pages/pmd/rules/vm.md @@ -1,6 +1,20 @@ --- -title: Apache Velocity Rules -sidebar: pmd_sidebar +title: VM Rules permalink: pmd_rules_vm.html folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [Basic Velocity](pmd_rules_vm_basic.html): The Basic Velocity ruleset contains basic rules for Apache Velocity pages. + +## Basic Velocity +* [AvoidDeeplyNestedIfStmts](pmd_rules_vm_basic.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... +* [CollapsibleIfStatements](pmd_rules_vm_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... +* [ExcessiveTemplateLength](pmd_rules_vm_basic.html#excessivetemplatelength): The template is too long. It should be broken up into smaller pieces. +* [AvoidReassigningParameters](pmd_rules_vm_basic.html#avoidreassigningparameters): Reassigning values to incoming parameters is not recommended. Use temporary local variables inst... +* [EmptyIfStmt](pmd_rules_vm_basic.html#emptyifstmt): Empty if statements should be deleted. +* [EmptyForeachStmt](pmd_rules_vm_basic.html#emptyforeachstmt): Empty foreach statements should be deleted. +* [UnusedMacroParameter](pmd_rules_vm_basic.html#unusedmacroparameter): Avoid unused macro parameters. They should be deleted. +* [NoInlineJavaScript](pmd_rules_vm_basic.html#noinlinejavascript): Avoid inline JavaScript. Import .js files instead. +* [NoInlineStyles](pmd_rules_vm_basic.html#noinlinestyles): Avoid inline styles. Use css classes instead. + diff --git a/docs/pages/pmd/rules/vm/basic.md b/docs/pages/pmd/rules/vm/basic.md new file mode 100644 index 000000000..7b32df8eb --- /dev/null +++ b/docs/pages/pmd/rules/vm/basic.md @@ -0,0 +1,140 @@ +--- +title: Basic Velocity +summary: The Basic Velocity ruleset contains basic rules for Apache Velocity pages. +permalink: pmd_rules_vm_basic.html +folder: pmd/rules/vm +sidebaractiveurl: /pmd_rules_vm.html +editmepath: ../pmd-vm/src/main/resources/rulesets/vm/basic.xml +--- +## AvoidDeeplyNestedIfStmts +**Since:** 5.1 + +**Priority:** Medium (3) + +Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|problemDepth|3|The if statement depth reporting threshold| + +## CollapsibleIfStatements +**Since:** 5.1 + +**Priority:** Medium (3) + +Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## ExcessiveTemplateLength +**Since:** 5.1 + +**Priority:** Medium (3) + +The template is too long. It should be broken up into smaller pieces. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## AvoidReassigningParameters +**Since:** 5.1 + +**Priority:** Medium High (2) + +Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## EmptyIfStmt +**Since:** 5.1 + +**Priority:** Medium High (2) + +Empty if statements should be deleted. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## EmptyForeachStmt +**Since:** 5.1 + +**Priority:** Medium High (2) + +Empty foreach statements should be deleted. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## UnusedMacroParameter +**Since:** 5.1 + +**Priority:** Medium High (2) + +Avoid unused macro parameters. They should be deleted. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## NoInlineJavaScript +**Since:** 5.1 + +**Priority:** Medium High (2) + +Avoid inline JavaScript. Import .js files instead. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + +## NoInlineStyles +**Since:** 5.1 + +**Priority:** Medium High (2) + +Avoid inline styles. Use css classes instead. + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/xml.md b/docs/pages/pmd/rules/xml.md index 91968c2bb..9d58e4b61 100644 --- a/docs/pages/pmd/rules/xml.md +++ b/docs/pages/pmd/rules/xml.md @@ -1,6 +1,17 @@ --- -title: XML and XSL Rules -sidebar: pmd_sidebar +title: XML Rules permalink: pmd_rules_xml.html folder: pmd/rules --- +List of rulesets and rules contained in each ruleset. + +* [Basic POM](pmd_rules_xml_basic.html): The Basic POM Ruleset contains a collection of good practices regarding Maven's POM files. +* [Basic XML](pmd_rules_xml_basic.html): The Basic XML Ruleset contains a collection of good practices which everyone should follow. + +## Basic POM +* [ProjectVersionAsDependencyVersion](pmd_rules_xml_basic.html#projectversionasdependencyversion): Using that expression in dependency declarations seems like a shortcut, but it can go wrong. By f... +* [InvalidDependencyTypes](pmd_rules_xml_basic.html#invaliddependencytypes): While Maven will not failed if you use an invalid type for a dependency in the dependency managem... + +## Basic XML +* [MistypedCDATASection](pmd_rules_xml_basic.html#mistypedcdatasection): An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and ends with a ]]> mar... + diff --git a/docs/pages/pmd/rules/xml/basic.md b/docs/pages/pmd/rules/xml/basic.md new file mode 100644 index 000000000..88bb206a5 --- /dev/null +++ b/docs/pages/pmd/rules/xml/basic.md @@ -0,0 +1,29 @@ +--- +title: Basic XML +summary: The Basic XML Ruleset contains a collection of good practices which everyone should follow. +permalink: pmd_rules_xml_basic.html +folder: pmd/rules/xml +sidebaractiveurl: /pmd_rules_xml.html +editmepath: ../pmd-xml/src/main/resources/rulesets/xml/basic.xml +--- +## MistypedCDATASection +**Since:** 5.0 + +**Priority:** Medium (3) + +An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and ends with a ]]> marker, which has only two ]. + +**Example(s):** +``` +An extra [ looks like <!CDATA[[]]>, and an extra ] looks like <!CDATA[]]]>. +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + diff --git a/docs/pages/pmd/rules/xsl.md b/docs/pages/pmd/rules/xsl.md new file mode 100644 index 000000000..55a023262 --- /dev/null +++ b/docs/pages/pmd/rules/xsl.md @@ -0,0 +1,13 @@ +--- +title: XSL Rules +permalink: pmd_rules_xsl.html +folder: pmd/rules +--- +List of rulesets and rules contained in each ruleset. + +* [XPath in XSL](pmd_rules_xsl_xpath.html): This ruleset regroups a collection of good practices regarding XPath querying and functions inside an XSL. + +## XPath in XSL +* [UseConcatOnce](pmd_rules_xsl_xpath.html#useconcatonce): The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b'... +* [AvoidAxisNavigation](pmd_rules_xsl_xpath.html#avoidaxisnavigation): Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100%... + diff --git a/docs/pages/pmd/rules/xsl/xpath.md b/docs/pages/pmd/rules/xsl/xpath.md new file mode 100644 index 000000000..0cf411365 --- /dev/null +++ b/docs/pages/pmd/rules/xsl/xpath.md @@ -0,0 +1,52 @@ +--- +title: XPath in XSL +summary: This ruleset regroups a collection of good practices regarding XPath querying and functions inside an XSL. +permalink: pmd_rules_xsl_xpath.html +folder: pmd/rules/xsl +sidebaractiveurl: /pmd_rules_xsl.html +editmepath: ../pmd-xml/src/main/resources/rulesets/xsl/xpath.xml +--- +## UseConcatOnce +**Since:** 5.0 + +**Priority:** Medium (3) + +The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)". + +**Example(s):** +``` +<xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/> + <xsl:variable name="var" select="concat("Welcome","to you ",$name))"> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| + +## AvoidAxisNavigation +**Since:** 5.0 + +**Priority:** Medium (3) + +Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document. + +**Example(s):** +``` +<xsl:variable name="var" select="//item/descendant::child"/> +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|violationSuppressRegex||Suppress violations with messages matching a regular expression| +|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|version|1.0|XPath specification version| +|xpath||XPath expression| +|checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.| + From 4c3e65c8f9dfedb094d0b644d8bfbf52cd3d538f Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 28 Jul 2017 12:23:17 +0200 Subject: [PATCH 05/24] Fix checkstyle --- .../java/net/sourceforge/pmd/docs/RuleDocGenerator.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index df752152e..36dd1444d 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -244,9 +244,9 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add("|----|-------------|-----------|"); for (PropertyDescriptor<?> propertyDescriptor : rule.getPropertyDescriptors()) { lines.add("|" + propertyDescriptor.name() - + "|" + (propertyDescriptor.defaultValue() != null ? String.valueOf(propertyDescriptor.defaultValue()) : "") - + "|" + propertyDescriptor.description() - + "|"); + + "|" + (propertyDescriptor.defaultValue() != null ? String.valueOf(propertyDescriptor.defaultValue()) : "") + + "|" + propertyDescriptor.description() + + "|"); } lines.add(""); } @@ -269,7 +269,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws */ private static String getRuleSetSourceFilepath(RuleSet ruleset) throws IOException { Path root = FileSystems.getDefault().getPath("..").toAbsolutePath().normalize(); - final String rulesetFilename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName())); + final String rulesetFilename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName())); final List<Path> foundPathResult = new LinkedList<>(); Files.walkFileTree(root, new SimpleFileVisitor<Path>() { From 3e39828dd9f8a098add38379ad178341f08faab6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Mon, 31 Jul 2017 21:10:55 +0200 Subject: [PATCH 06/24] [doc] Fixes for #526 --- .../pmd/docs/RuleDocGenerator.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 36dd1444d..5749cc54b 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -33,6 +33,7 @@ import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.rule.XPathRule; public class RuleDocGenerator { private static final String LANGUAGE_INDEX_FILENAME_PATTERN = "docs/pages/pmd/rules/${language.tersename}.md"; @@ -216,8 +217,16 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add("sidebaractiveurl: /" + LANGUAGE_INDEX_PERMALINK_PATTERN.replace("${language.tersename}", languageTersename)); lines.add("editmepath: ../" + getRuleSetSourceFilepath(ruleset)); lines.add("---"); - - for (Rule rule : ruleset.getRules()) { + + List<Rule> sortedRules = new ArrayList<>(ruleset.getRules()); + Collections.sort(sortedRules, new Comparator<Rule>() { + @Override + public int compare(Rule o1, Rule o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }); + + for (Rule rule : sortedRules) { lines.add("## " + rule.getName()); if (rule.getSince() != null) { lines.add("**Since:** " + rule.getSince()); @@ -237,12 +246,20 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add(""); } } - if (!rule.getPropertyDescriptors().isEmpty()) { + + List<PropertyDescriptor<?>> properties = new ArrayList<>(rule.getPropertyDescriptors()); + // filter out standard properties + properties.remove(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR); + properties.remove(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR); + properties.remove(XPathRule.XPATH_DESCRIPTOR); + properties.remove(XPathRule.VERSION_DESCRIPTOR); + + if (!properties.isEmpty()) { lines.add("**This rule has the following properties:**"); lines.add(""); lines.add("|Name|Default Value|Description|"); lines.add("|----|-------------|-----------|"); - for (PropertyDescriptor<?> propertyDescriptor : rule.getPropertyDescriptors()) { + for (PropertyDescriptor<?> propertyDescriptor : properties) { lines.add("|" + propertyDescriptor.name() + "|" + (propertyDescriptor.defaultValue() != null ? String.valueOf(propertyDescriptor.defaultValue()) : "") + "|" + propertyDescriptor.description() From 1d706726af59067d289cede4fdf4f2531e9ee400 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Mon, 31 Jul 2017 21:11:21 +0200 Subject: [PATCH 07/24] [doc] Update generated rule doc --- docs/pages/pmd/rules/apex/apexunit.md | 4 - docs/pages/pmd/rules/apex/braces.md | 88 +- docs/pages/pmd/rules/apex/complexity.md | 156 +- docs/pages/pmd/rules/apex/performance.md | 28 +- docs/pages/pmd/rules/apex/security.md | 212 +- docs/pages/pmd/rules/apex/style.md | 128 +- docs/pages/pmd/rules/ecmascript/basic.md | 224 +-- docs/pages/pmd/rules/ecmascript/braces.md | 68 +- .../pages/pmd/rules/ecmascript/unnecessary.md | 79 +- docs/pages/pmd/rules/java/android.md | 27 - docs/pages/pmd/rules/java/basic.md | 765 +++---- docs/pages/pmd/rules/java/braces.md | 102 +- docs/pages/pmd/rules/java/clone.md | 123 +- docs/pages/pmd/rules/java/codesize.md | 476 +++-- docs/pages/pmd/rules/java/comments.md | 126 +- docs/pages/pmd/rules/java/controversial.md | 652 +++--- docs/pages/pmd/rules/java/coupling.md | 94 +- docs/pages/pmd/rules/java/design.md | 1788 +++++++---------- docs/pages/pmd/rules/java/empty.md | 254 +-- docs/pages/pmd/rules/java/finalizers.md | 110 +- docs/pages/pmd/rules/java/imports.md | 73 +- docs/pages/pmd/rules/java/j2ee.md | 169 +- docs/pages/pmd/rules/java/javabeans.md | 11 - docs/pages/pmd/rules/java/junit.md | 251 +-- .../pmd/rules/java/logging-jakarta-commons.md | 111 +- docs/pages/pmd/rules/java/logging-java.md | 147 +- docs/pages/pmd/rules/java/migrating.md | 348 ++-- docs/pages/pmd/rules/java/naming.md | 480 ++--- docs/pages/pmd/rules/java/optimizations.md | 338 ++-- docs/pages/pmd/rules/java/strictexception.md | 302 +-- docs/pages/pmd/rules/java/strings.md | 336 ++-- docs/pages/pmd/rules/java/sunsecure.md | 48 +- docs/pages/pmd/rules/java/unnecessary.md | 220 +- docs/pages/pmd/rules/java/unusedcode.md | 67 +- docs/pages/pmd/rules/jsp/basic-jsf.md | 9 - docs/pages/pmd/rules/jsp/basic.md | 273 +-- docs/pages/pmd/rules/plsql/TomKytesDespair.md | 9 - docs/pages/pmd/rules/plsql/codesize.md | 508 +++-- docs/pages/pmd/rules/plsql/dates.md | 73 +- docs/pages/pmd/rules/plsql/strictsyntax.md | 9 - docs/pages/pmd/rules/vf/security.md | 26 +- docs/pages/pmd/rules/vm/basic.md | 91 +- docs/pages/pmd/rules/xml/basic.md | 9 - docs/pages/pmd/rules/xsl/xpath.md | 29 +- 44 files changed, 3483 insertions(+), 5958 deletions(-) diff --git a/docs/pages/pmd/rules/apex/apexunit.md b/docs/pages/pmd/rules/apex/apexunit.md index ced790393..7ce403575 100644 --- a/docs/pages/pmd/rules/apex/apexunit.md +++ b/docs/pages/pmd/rules/apex/apexunit.md @@ -31,8 +31,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| @@ -61,8 +59,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| diff --git a/docs/pages/pmd/rules/apex/braces.md b/docs/pages/pmd/rules/apex/braces.md index fd560383e..1473297b8 100644 --- a/docs/pages/pmd/rules/apex/braces.md +++ b/docs/pages/pmd/rules/apex/braces.md @@ -6,22 +6,22 @@ folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/braces.xml --- -## IfStmtsMustUseBraces +## ForLoopsMustUseBraces **Since:** 5.6.0 **Priority:** Medium (3) -Avoid using if statements without using braces to surround the code block. If the code -formatting or indentation is lost then it becomes difficult to separate the code being -controlled from the rest. +Avoid using 'for' statements without using surrounding braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest. **Example(s):** ``` -if (foo) // not recommended - x++; +for (int i = 0; i < 42; i++) // not recommended + foo(); -if (foo) { // preferred approach - x++; +for (int i = 0; i < 42; i++) { // preferred approach + foo(); } ``` @@ -29,94 +29,82 @@ if (foo) { // preferred approach |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## WhileLoopsMustUseBraces +## IfElseStmtsMustUseBraces **Since:** 5.6.0 **Priority:** Medium (3) -Avoid using 'while' statements without using braces to surround the code block. If the code -formatting or indentation is lost then it becomes difficult to separate the code being -controlled from the rest. +Avoid using if..else statements without using surrounding braces. If the code formatting +or indentation is lost then it becomes difficult to separate the code being controlled +from the rest. **Example(s):** ``` -while (true) // not recommended - x++; +// this is OK +if (foo) x++; -while (true) { // preferred approach - x++; -} + // but this is not +if (foo) + x = x+1; + else + x = x-1; ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## IfElseStmtsMustUseBraces +## IfStmtsMustUseBraces **Since:** 5.6.0 **Priority:** Medium (3) -Avoid using if..else statements without using surrounding braces. If the code formatting -or indentation is lost then it becomes difficult to separate the code being controlled -from the rest. +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. **Example(s):** ``` -// this is OK -if (foo) x++; +if (foo) // not recommended + x++; - // but this is not -if (foo) - x = x+1; - else - x = x-1; +if (foo) { // preferred approach + x++; +} ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ForLoopsMustUseBraces +## WhileLoopsMustUseBraces **Since:** 5.6.0 **Priority:** Medium (3) -Avoid using 'for' statements without using surrounding braces. If the code formatting or -indentation is lost then it becomes difficult to separate the code being controlled -from the rest. +Avoid using 'while' statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. **Example(s):** ``` -for (int i = 0; i < 42; i++) // not recommended - foo(); +while (true) // not recommended + x++; -for (int i = 0; i < 42; i++) { // preferred approach - foo(); +while (true) { // preferred approach + x++; } ``` @@ -124,10 +112,6 @@ for (int i = 0; i < 42; i++) { // preferred approach |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| diff --git a/docs/pages/pmd/rules/apex/complexity.md b/docs/pages/pmd/rules/apex/complexity.md index fd8dca388..8bf1d704e 100644 --- a/docs/pages/pmd/rules/apex/complexity.md +++ b/docs/pages/pmd/rules/apex/complexity.md @@ -32,13 +32,49 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| |problemDepth|3|The if statement depth reporting threshold| +## ExcessiveClassLength +**Since:** 5.5.0 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +public class Foo { + public void bar1() { + // 1000 lines of code + } + public void bar2() { + // 1000 lines of code + } + public void bar3() { + // 1000 lines of code + } + public void barN() { + // 1000 lines of code + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|cc_categories|[Style]|Code Climate Categories| +|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| +|cc_block_highlighting|false|Code Climate Block Highlighting| +|sigma||Sigma value| + ## ExcessiveParameterList **Since:** 5.5.0 @@ -63,8 +99,6 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |cc_categories|[Style]|Code Climate Categories| @@ -72,30 +106,28 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| -## ExcessiveClassLength +## ExcessivePublicCount **Since:** 5.5.0 **Priority:** Medium (3) -Excessive class file lengths are usually indications that the class may be burdened with excessive -responsibilities that could be provided by external classes or functions. In breaking these methods -apart the code becomes more managable and ripe for reuse. +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily. **Example(s):** ``` public class Foo { - public void bar1() { - // 1000 lines of code - } - public void bar2() { - // 1000 lines of code - } - public void bar3() { - // 1000 lines of code - } - public void barN() { - // 1000 lines of code - } + public String value; + public Bar something; + public Variable var; + // [... more more public attributes ...] + + public void doWork() {} + public void doMoreWork() {} + public void doWorkAgain() {} + // [... more more public methods ...] } ``` @@ -103,8 +135,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |cc_categories|[Style]|Code Climate Categories| @@ -112,25 +142,26 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| -## NcssMethodCount +## NcssConstructorCount **Since:** 5.5.0 **Priority:** Medium (3) This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. **Example(s):** ``` public class Foo extends Bar { - //this method only has 1 NCSS lines - public Integer methd() { - super.methd(); + //this constructor only has 1 NCSS lines + public Foo() { + super(); - return 1; + + super.foo(); } } ``` @@ -139,8 +170,6 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |cc_categories|[Style]|Code Climate Categories| @@ -148,27 +177,25 @@ public class Foo extends Bar { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| -## NcssTypeCount +## NcssMethodCount **Since:** 5.5.0 **Priority:** Medium (3) This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, +of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. **Example(s):** ``` -//this class only has 6 NCSS lines public class Foo extends Bar { - public Foo() { - super(); - - + //this method only has 1 NCSS lines + public Integer methd() { + super.methd(); - super.foo(); + return 1; } } ``` @@ -177,8 +204,6 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |cc_categories|[Style]|Code Climate Categories| @@ -186,25 +211,26 @@ public class Foo extends Bar { |cc_block_highlighting|false|Code Climate Block Highlighting| |sigma||Sigma value| -## NcssConstructorCount +## NcssTypeCount **Since:** 5.5.0 **Priority:** Medium (3) This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. **Example(s):** ``` +//this class only has 6 NCSS lines public class Foo extends Bar { - //this constructor only has 1 NCSS lines public Foo() { super(); + super.foo(); } } @@ -214,8 +240,6 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |cc_categories|[Style]|Code Climate Categories| @@ -278,8 +302,6 @@ high complexity, and 11+ is very high complexity. |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |showMethodsComplexity|true|Add method average violations to the report| |showClassesComplexity|true|Add class average violations to the report| |cc_categories|[Style]|Code Climate Categories| @@ -318,48 +340,8 @@ public class Person { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| |maxfields|15|Max allowable fields| -## ExcessivePublicCount -**Since:** 5.5.0 - -**Priority:** Medium (3) - -Classes with large numbers of public methods and attributes require disproportionate testing efforts -since combinational side effects grow rapidly and increase risk. Refactoring these classes into -smaller ones not only increases testability and reliability but also allows new variations to be -developed easily. - -**Example(s):** -``` -public class Foo { - public String value; - public Bar something; - public Variable var; - // [... more more public attributes ...] - - public void doWork() {} - public void doMoreWork() {} - public void doWorkAgain() {} - // [... more more public methods ...] -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|cc_categories|[Style]|Code Climate Categories| -|cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| -|cc_block_highlighting|false|Code Climate Block Highlighting| -|sigma||Sigma value| - diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md index d58eaf941..f24acd4b2 100644 --- a/docs/pages/pmd/rules/apex/performance.md +++ b/docs/pages/pmd/rules/apex/performance.md @@ -6,19 +6,21 @@ folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/performance.xml --- -## AvoidSoqlInLoops +## AvoidDmlStatementsInLoops **Since:** 5.5.0 **Priority:** Medium (3) -New objects created within loops should be checked to see if they can created outside them and reused. +Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. **Example(s):** ``` public class Something { - public static void main( String as[] ) { - for (Integer i = 0; i < 10; i++) { - List<Account> accounts = [SELECT Id FROM Account]; + public void foo() { + for (Integer i = 0; i < 151; i++) { + Account account; + ... + insert account; } } } @@ -28,27 +30,23 @@ public class Something { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## AvoidDmlStatementsInLoops +## AvoidSoqlInLoops **Since:** 5.5.0 **Priority:** Medium (3) -Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. +New objects created within loops should be checked to see if they can created outside them and reused. **Example(s):** ``` public class Something { - public void foo() { - for (Integer i = 0; i < 151; i++) { - Account account; - ... - insert account; + public static void main( String as[] ) { + for (Integer i = 0; i < 10; i++) { + List<Account> accounts = [SELECT Id FROM Account]; } } } @@ -58,8 +56,6 @@ public class Something { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md index f7928661c..39cf3f158 100644 --- a/docs/pages/pmd/rules/apex/security.md +++ b/docs/pages/pmd/rules/apex/security.md @@ -6,18 +6,21 @@ folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/security.xml --- -## ApexSharingViolations +## ApexBadCrypto **Since:** 5.5.3 **Priority:** Medium (3) -Detect classes declared without explicit sharing mode if DML methods are used. This -forces the developer to take access restrictions into account before modifying objects. +The rule makes sure you are using randomly generated IVs and keys for `Crypto` calls. +Hard-wiring these values greatly compromises the security of encrypted data. **Example(s):** ``` public without sharing class Foo { -// DML operation here + Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123'); + Blob hardCodedKey = Blob.valueOf('0000000000000000'); + Blob data = Blob.valueOf('Data to be encrypted'); + Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data); } ``` @@ -25,26 +28,33 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexOpenRedirect +## ApexCRUDViolation **Since:** 5.5.3 **Priority:** Medium (3) -Checks against redirects to user-controlled locations. This prevents attackers from -redirecting users to phishing sites. +The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. +Since Apex runs in system mode not having proper permissions checks results in escalation of +privilege and may produce runtime errors. This check forces you to handle such scenarios. **Example(s):** ``` -public without sharing class Foo { - String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param'); - PageReference page() { - return new PageReference(unsafeLocation); +public class Foo { + public Contact foo(String status, String ID) { + Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID]; + + // Make sure we can update the database before even trying + if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) { + return null; + } + + c.Status__c = status; + update c; + return c; } } ``` @@ -53,26 +63,27 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexInsecureEndpoint +## ApexCSRF **Since:** 5.5.3 **Priority:** Medium (3) -Checks against accessing endpoints under plain **http**. You should always use -**https** for security. +Check to avoid making DML operations in Apex class constructor/init method. This prevents +modification of the database just by accessing a page. **Example(s):** ``` -public without sharing class Foo { - void foo() { - HttpRequest req = new HttpRequest(); - req.setEndpoint('http://localhost:com'); +public class Foo { + public init() { + insert data; + } + + public Foo() { + insert data; } } ``` @@ -81,25 +92,30 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexXSSFromURLParam +## ApexDangerousMethods **Since:** 5.5.3 **Priority:** Medium (3) -Makes sure that all values obtained from URL parameters are properly escaped / sanitized -to avoid XSS attacks. +Checks against calling dangerous methods. + +For the time being, it reports: + +* Against `FinancialForce`'s `Configuration.disableTriggerCRUDSecurity()`. Disabling CRUD security +opens the door to several attacks and requires manual validation, which is unreliable. +* Calling `System.debug` passing sensitive data as parameter, which could lead to exposure +of private data. **Example(s):** ``` -public without sharing class Foo { - String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param'); - String usedLater = unescapedstring; +public class Foo { + public Foo() { + Configuration.disableTriggerCRUDSecurity(); + } } ``` @@ -107,25 +123,25 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexXSSFromEscapeFalse +## ApexInsecureEndpoint **Since:** 5.5.3 **Priority:** Medium (3) -Reports on calls to `addError` with disabled escaping. The message passed to `addError` -will be displayed directly to the user in the UI, making it prime ground for XSS -attacks if unescaped. +Checks against accessing endpoints under plain **http**. You should always use +**https** for security. **Example(s):** ``` public without sharing class Foo { - Trigger.new[0].addError(vulnerableHTMLGoesHere, false); + void foo() { + HttpRequest req = new HttpRequest(); + req.setEndpoint('http://localhost:com'); + } } ``` @@ -133,27 +149,25 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexBadCrypto +## ApexOpenRedirect **Since:** 5.5.3 **Priority:** Medium (3) -The rule makes sure you are using randomly generated IVs and keys for `Crypto` calls. -Hard-wiring these values greatly compromises the security of encrypted data. +Checks against redirects to user-controlled locations. This prevents attackers from +redirecting users to phishing sites. **Example(s):** ``` public without sharing class Foo { - Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123'); - Blob hardCodedKey = Blob.valueOf('0000000000000000'); - Blob data = Blob.valueOf('Data to be encrypted'); - Blob encrypted = Crypto.encrypt('AES128', hardCodedKey, hardCodedIV, data); + String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param'); + PageReference page() { + return new PageReference(unsafeLocation); + } } ``` @@ -161,30 +175,22 @@ public without sharing class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexCSRF +## ApexSharingViolations **Since:** 5.5.3 **Priority:** Medium (3) -Check to avoid making DML operations in Apex class constructor/init method. This prevents -modification of the database just by accessing a page. +Detect classes declared without explicit sharing mode if DML methods are used. This +forces the developer to take access restrictions into account before modifying objects. **Example(s):** ``` -public class Foo { - public init() { - insert data; - } - - public Foo() { - insert data; - } +public without sharing class Foo { +// DML operation here } ``` @@ -192,8 +198,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| @@ -218,35 +222,36 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexCRUDViolation +## ApexSuggestUsingNamedCred **Since:** 5.5.3 **Priority:** Medium (3) -The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. -Since Apex runs in system mode not having proper permissions checks results in escalation of -privilege and may produce runtime errors. This check forces you to handle such scenarios. +Detects hardcoded credentials used in requests to an endpoint. + +You should refrain from hardcoding credentials: + * They are hard to mantain by being mixed in application code + * Particularly hard to update them when used from different classes + * Granting a developer access to the codebase means granting knowledge + of credentials, keeping a two-level access is not possible. + * Using different credentials for different environments is troublesome + and error-prone. + +Instead, you should use *Named Credentials* and a callout endpoint. + +For more information, you can check [this](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials.htm) **Example(s):** ``` public class Foo { - public Contact foo(String status, String ID) { - Contact c = [SELECT Status__c FROM Contact WHERE Id=:ID]; - - // Make sure we can update the database before even trying - if (!Schema.sObjectType.Contact.fields.Name.isUpdateable()) { - return null; - } - - c.Status__c = status; - update c; - return c; + public void foo(String username, String password) { + Blob headerValue = Blob.valueOf(username + ':' + password); + String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); + req.setHeader('Authorization', authorizationHeader); } } ``` @@ -255,32 +260,23 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexDangerousMethods +## ApexXSSFromEscapeFalse **Since:** 5.5.3 **Priority:** Medium (3) -Checks against calling dangerous methods. - -For the time being, it reports: - -* Against `FinancialForce`'s `Configuration.disableTriggerCRUDSecurity()`. Disabling CRUD security -opens the door to several attacks and requires manual validation, which is unreliable. -* Calling `System.debug` passing sensitive data as parameter, which could lead to exposure -of private data. +Reports on calls to `addError` with disabled escaping. The message passed to `addError` +will be displayed directly to the user in the UI, making it prime ground for XSS +attacks if unescaped. **Example(s):** ``` -public class Foo { - public Foo() { - Configuration.disableTriggerCRUDSecurity(); - } +public without sharing class Foo { + Trigger.new[0].addError(vulnerableHTMLGoesHere, false); } ``` @@ -288,39 +284,23 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## ApexSuggestUsingNamedCred +## ApexXSSFromURLParam **Since:** 5.5.3 **Priority:** Medium (3) -Detects hardcoded credentials used in requests to an endpoint. - -You should refrain from hardcoding credentials: - * They are hard to mantain by being mixed in application code - * Particularly hard to update them when used from different classes - * Granting a developer access to the codebase means granting knowledge - of credentials, keeping a two-level access is not possible. - * Using different credentials for different environments is troublesome - and error-prone. - -Instead, you should use *Named Credentials* and a callout endpoint. - -For more information, you can check [this](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials.htm) +Makes sure that all values obtained from URL parameters are properly escaped / sanitized +to avoid XSS attacks. **Example(s):** ``` -public class Foo { - public void foo(String username, String password) { - Blob headerValue = Blob.valueOf(username + ':' + password); - String authorizationHeader = 'BASIC ' + EncodingUtil.base64Encode(headerValue); - req.setHeader('Authorization', authorizationHeader); - } +public without sharing class Foo { + String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param'); + String usedLater = unescapedstring; } ``` @@ -328,8 +308,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| diff --git a/docs/pages/pmd/rules/apex/style.md b/docs/pages/pmd/rules/apex/style.md index 409f3284e..465f5756c 100644 --- a/docs/pages/pmd/rules/apex/style.md +++ b/docs/pages/pmd/rules/apex/style.md @@ -6,21 +6,20 @@ folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/style.xml --- -## VariableNamingConventions +## AvoidGlobalModifier **Since:** 5.5.0 -**Priority:** High (1) +**Priority:** Medium (3) -A variable naming conventions rule - customize this to your liking. Currently, it -checks for final variables that should be fully capitalized and non-final variables -that should not include underscores. +Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. +Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in. **Example(s):** ``` -public class Foo { - public static final Integer MY_NUM = 0; - public String myTest = ''; - DataModule dmTest = new DataModule(); +global class Unchangeable { + global UndeletableType unchangable(UndeletableType param) { + // ... + } } ``` @@ -28,34 +27,33 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|parameterSuffix|[]|Method parameter variable suffixes| -|parameterPrefix|[]|Method parameter variable prefixes| -|localSuffix|[]|Local variable suffixes| -|localPrefix|[]|Local variable prefixes| -|memberSuffix|[]|Member variable suffixes| -|memberPrefix|[]|Member variable prefixes| -|staticSuffix|[]|Static variable suffixes| -|staticPrefix|[]|Static variable prefixes| -|checkParameters|true|Check constructor and method parameter variables| -|checkLocals|true|Check local variables| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -|checkMembers|true|Check member variables| -## MethodNamingConventions +## AvoidLogicInTrigger **Since:** 5.5.0 -**Priority:** High (1) +**Priority:** Medium (3) -Method names should always begin with a lower case character, and should not contain underscores. +As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style. +Therefore delegate the triggers work to a regular class (often called Trigger handler class). + +See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices **Example(s):** ``` -public class Foo { - public void fooStuff() { +trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { + for(Account acc : Trigger.new) { + if(Trigger.isInsert) { + ... + } + + ... + + if(Trigger.isDelete) { + ... + } } } ``` @@ -64,8 +62,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| @@ -86,26 +82,22 @@ public class Foo {} |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## MethodWithSameNameAsEnclosingClass +## MethodNamingConventions **Since:** 5.5.0 -**Priority:** Medium (3) +**Priority:** High (1) -Non-constructor methods should not have the same name as the enclosing class. +Method names should always begin with a lower case character, and should not contain underscores. **Example(s):** ``` -public class MyClass { - // this is OK because it is a constructor - public MyClass() {} - // this is bad because it is a method - public void MyClass() {} +public class Foo { + public void fooStuff() { + } } ``` @@ -113,36 +105,24 @@ public class MyClass { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## AvoidLogicInTrigger +## MethodWithSameNameAsEnclosingClass **Since:** 5.5.0 **Priority:** Medium (3) -As triggers do not allow methods like regular classes they are less flexible and suited to apply good encapsulation style. -Therefore delegate the triggers work to a regular class (often called Trigger handler class). - -See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices +Non-constructor methods should not have the same name as the enclosing class. **Example(s):** ``` -trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { - for(Account acc : Trigger.new) { - if(Trigger.isInsert) { - ... - } - - ... - - if(Trigger.isDelete) { - ... - } - } +public class MyClass { + // this is OK because it is a constructor + public MyClass() {} + // this is bad because it is a method + public void MyClass() {} } ``` @@ -150,26 +130,25 @@ trigger Accounts on Account (before insert, before update, before delete, after |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| -## AvoidGlobalModifier +## VariableNamingConventions **Since:** 5.5.0 -**Priority:** Medium (3) +**Priority:** High (1) -Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. -Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in. +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores. **Example(s):** ``` -global class Unchangeable { - global UndeletableType unchangable(UndeletableType param) { - // ... - } +public class Foo { + public static final Integer MY_NUM = 0; + public String myTest = ''; + DataModule dmTest = new DataModule(); } ``` @@ -177,9 +156,18 @@ global class Unchangeable { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|parameterSuffix|[]|Method parameter variable suffixes| +|parameterPrefix|[]|Method parameter variable prefixes| +|localSuffix|[]|Local variable suffixes| +|localPrefix|[]|Local variable prefixes| +|memberSuffix|[]|Member variable suffixes| +|memberPrefix|[]|Member variable prefixes| +|staticSuffix|[]|Static variable suffixes| +|staticPrefix|[]|Static variable prefixes| +|checkParameters|true|Check constructor and method parameter variables| +|checkLocals|true|Check local variables| |cc_categories|[Style]|Code Climate Categories| |cc_remediation_points_multiplier|1|Code Climate Remediation Points multiplier| |cc_block_highlighting|false|Code Climate Block Highlighting| +|checkMembers|true|Check member variables| diff --git a/docs/pages/pmd/rules/ecmascript/basic.md b/docs/pages/pmd/rules/ecmascript/basic.md index b62e0e0c1..e9a192bb8 100644 --- a/docs/pages/pmd/rules/ecmascript/basic.md +++ b/docs/pages/pmd/rules/ecmascript/basic.md @@ -31,10 +31,6 @@ function getX() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |allowIf|false|Allow assignment within the conditional expression of an if statement| |allowFor|false|Allow assignment within the conditional expression of a for statement| |allowWhile|false|Allow assignment within the conditional expression of a while statement| @@ -42,64 +38,30 @@ function getX() { |allowTernaryResults|false|Allow assignment within the result expressions of a ternary operator| |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| -## UnreachableCode -**Since:** 5.0 +## AvoidTrailingComma +**Since:** 5.1 **Priority:** High (1) -A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these -will never execute. This is a bug, or extremely poor style. +This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. **Example(s):** ``` -// Ok -function foo() { - return 1; -} -// Bad -function bar() { - var x = 1; - return x; - x = 2; -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## InnaccurateNumericLiteral -**Since:** 5.0 - -**Priority:** Medium High (2) - -The numeric literal will have at different value at runtime, which can happen if you provide too much -precision in a floating point number. This may result in numeric calculations being in error. +function(arg) { + var obj1 = { a : 1 }; // Ok + var arr1 = [ 1, 2 ]; // Ok -**Example(s):** -``` -var a = 9; // Ok -var b = 999999999999999; // Ok -var c = 999999999999999999999; // Not good -var w = 1.12e-4; // Ok -var x = 1.12; // Ok -var y = 1.1234567890123; // Ok -var z = 1.12345678901234567; // Not good + var obj2 = { a : 1, }; // Syntax error in some browsers! + var arr2 = [ 1, 2, ]; // Length 2 or 3 depending on the browser! +} ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|allowObjectLiteral|false|Allow a trailing comma within an object literal| +|allowArrayLiteral|false|Allow a trailing comma within an array literal| ## ConsistentReturn **Since:** 5.0 @@ -133,63 +95,10 @@ function bar() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |rhinoLanguageVersion|VERSION_DEFAULT|Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.| |recordingLocalJsDocComments|true|Specifies that JsDoc comments are produced in the AST.| |recordingComments|true|Specifies that comments are produced in the AST.| -## ScopeForInVariable -**Since:** 5.0 - -**Priority:** High (1) - -A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the 'var' keyword can -refer to a variable in an enclosing scope outside the nearest enclosing scope. This will overwrite the -existing value of the variable in the outer scope when the body of the for-in is evaluated. When the for-in loop -has finished, the variable will contain the last value used in the for-in, and the original value from before -the for-in loop will be gone. Since the for-in variable name is most likely intended to be a temporary name, it -is better to explicitly scope the variable name to the nearest enclosing scope with 'var'. - -**Example(s):** -``` -// Ok -function foo() { - var p = 'clean'; - function() { - var obj = { dirty: 'dirty' }; - for (var p in obj) { // Use 'var' here. - obj[p] = obj[p]; - } - return x; - }(); - - // 'p' still has value of 'clean'. -} -// Bad -function bar() { - var p = 'clean'; - function() { - var obj = { dirty: 'dirty' }; - for (p in obj) { // Oh no, missing 'var' here! - obj[p] = obj[p]; - } - return x; - }(); - - // 'p' is trashed and has value of 'dirty'! -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## EqualComparison **Since:** 5.0 @@ -218,15 +127,6 @@ if (someVar != 3) { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## GlobalVariable **Since:** 5.0 @@ -246,43 +146,88 @@ function(arg) { } ``` -**This rule has the following properties:** +## InnaccurateNumericLiteral +**Since:** 5.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) -## AvoidTrailingComma -**Since:** 5.1 +The numeric literal will have at different value at runtime, which can happen if you provide too much +precision in a floating point number. This may result in numeric calculations being in error. + +**Example(s):** +``` +var a = 9; // Ok +var b = 999999999999999; // Ok +var c = 999999999999999999999; // Not good +var w = 1.12e-4; // Ok +var x = 1.12; // Ok +var y = 1.1234567890123; // Ok +var z = 1.12345678901234567; // Not good +``` + +## ScopeForInVariable +**Since:** 5.0 **Priority:** High (1) -This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. +A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the 'var' keyword can +refer to a variable in an enclosing scope outside the nearest enclosing scope. This will overwrite the +existing value of the variable in the outer scope when the body of the for-in is evaluated. When the for-in loop +has finished, the variable will contain the last value used in the for-in, and the original value from before +the for-in loop will be gone. Since the for-in variable name is most likely intended to be a temporary name, it +is better to explicitly scope the variable name to the nearest enclosing scope with 'var'. **Example(s):** ``` -function(arg) { - var obj1 = { a : 1 }; // Ok - var arr1 = [ 1, 2 ]; // Ok +// Ok +function foo() { + var p = 'clean'; + function() { + var obj = { dirty: 'dirty' }; + for (var p in obj) { // Use 'var' here. + obj[p] = obj[p]; + } + return x; + }(); - var obj2 = { a : 1, }; // Syntax error in some browsers! - var arr2 = [ 1, 2, ]; // Length 2 or 3 depending on the browser! + // 'p' still has value of 'clean'. +} +// Bad +function bar() { + var p = 'clean'; + function() { + var obj = { dirty: 'dirty' }; + for (p in obj) { // Oh no, missing 'var' here! + obj[p] = obj[p]; + } + return x; + }(); + + // 'p' is trashed and has value of 'dirty'! } ``` -**This rule has the following properties:** +## UnreachableCode +**Since:** 5.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|allowObjectLiteral|false|Allow a trailing comma within an object literal| -|allowArrayLiteral|false|Allow a trailing comma within an array literal| +**Priority:** High (1) + +A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these +will never execute. This is a bug, or extremely poor style. + +**Example(s):** +``` +// Ok +function foo() { + return 1; +} +// Bad +function bar() { + var x = 1; + return x; + x = 2; +} +``` ## UseBaseWithParseInt **Since:** 5.0.1 @@ -296,12 +241,3 @@ TODO parseInt("10",base); ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/ecmascript/braces.md b/docs/pages/pmd/rules/ecmascript/braces.md index 37246da17..6574ed850 100644 --- a/docs/pages/pmd/rules/ecmascript/braces.md +++ b/docs/pages/pmd/rules/ecmascript/braces.md @@ -6,34 +6,25 @@ folder: pmd/rules/ecmascript sidebaractiveurl: /pmd_rules_ecmascript.html editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/braces.xml --- -## IfStmtsMustUseBraces +## ForLoopsMustUseBraces **Since:** 5.0 **Priority:** Medium (3) -Avoid using if statements without using curly braces. +Avoid using 'for' statements without using curly braces. **Example(s):** ``` // Ok -if (foo) { - x++; +for (var i = 0; i < 42; i++) { + foo(); } // Bad -if (foo) - x++; +for (var i = 0; i < 42; i++) + foo(); ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## IfElseStmtsMustUseBraces **Since:** 5.0 @@ -57,68 +48,41 @@ else y++; ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## WhileLoopsMustUseBraces +## IfStmtsMustUseBraces **Since:** 5.0 **Priority:** Medium (3) -Avoid using 'while' statements without using curly braces. +Avoid using if statements without using curly braces. **Example(s):** ``` // Ok -while (true) { +if (foo) { x++; } // Bad -while (true) +if (foo) x++; ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ForLoopsMustUseBraces +## WhileLoopsMustUseBraces **Since:** 5.0 **Priority:** Medium (3) -Avoid using 'for' statements without using curly braces. +Avoid using 'while' statements without using curly braces. **Example(s):** ``` // Ok -for (var i = 0; i < 42; i++) { - foo(); +while (true) { + x++; } // Bad -for (var i = 0; i < 42; i++) - foo(); +while (true) + x++; ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/ecmascript/unnecessary.md b/docs/pages/pmd/rules/ecmascript/unnecessary.md index 84bfdd4be..02e1211c7 100644 --- a/docs/pages/pmd/rules/ecmascript/unnecessary.md +++ b/docs/pages/pmd/rules/ecmascript/unnecessary.md @@ -6,28 +6,31 @@ folder: pmd/rules/ecmascript sidebaractiveurl: /pmd_rules_ecmascript.html editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/unnecessary.xml --- -## UnnecessaryParentheses -**Since:** 5.0 +## NoElseReturn +**Since:** 5.5.0 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -Unnecessary parentheses should be removed. +The else block in a if-else-construct is unnecessary if the `if` block contains a return. + Then the content of the else block can be put outside. + + See also: http://eslint.org/docs/rules/no-else-return **Example(s):** ``` -var x = 1; // Ok -var y = (1 + 1); // Ok -var z = ((1 + 1)); // Bad -``` - -**This rule has the following properties:** +// Bad: +if (x) { + return y; +} else { + return z; +} -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +// Good: +if (x) { + return y; +} +return z; +``` ## UnnecessaryBlock **Since:** 5.0 @@ -50,47 +53,17 @@ if (bar) { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## NoElseReturn -**Since:** 5.5.0 +## UnnecessaryParentheses +**Since:** 5.0 -**Priority:** Medium (3) +**Priority:** Medium Low (4) -The else block in a if-else-construct is unnecessary if the `if` block contains a return. - Then the content of the else block can be put outside. - - See also: http://eslint.org/docs/rules/no-else-return +Unnecessary parentheses should be removed. **Example(s):** ``` -// Bad: -if (x) { - return y; -} else { - return z; -} - -// Good: -if (x) { - return y; -} -return z; +var x = 1; // Ok +var y = (1 + 1); // Ok +var z = ((1 + 1)); // Bad ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/android.md b/docs/pages/pmd/rules/java/android.md index b627bc026..c9ff23e6a 100644 --- a/docs/pages/pmd/rules/java/android.md +++ b/docs/pages/pmd/rules/java/android.md @@ -23,15 +23,6 @@ public class DummyActivity extends Activity { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## CallSuperLast **Since:** 4.2.5 @@ -49,15 +40,6 @@ public class DummyActivity extends Activity { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## DoNotHardCodeSDCard **Since:** 4.2.6 @@ -76,12 +58,3 @@ public class MyActivity extends Activity { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md index a60e7139f..78eb82222 100644 --- a/docs/pages/pmd/rules/java/basic.md +++ b/docs/pages/pmd/rules/java/basic.md @@ -6,234 +6,28 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/basic.xml --- -## JumbledIncrementer -**Since:** 1.0 - -**Priority:** Medium (3) - -Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. - -**Example(s):** -``` -public class JumbledIncrementerRule1 { - public void foo() { - for (int i = 0; i < 10; i++) { // only references 'i' - for (int k = 0; k < 20; i++) { // references both 'i' and 'k' - System.out.println("Hello"); - } - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ForLoopShouldBeWhileLoop -**Since:** 1.02 - -**Priority:** Medium (3) - -Some for loops can be simplified to while loops, this makes them more concise. - -**Example(s):** -``` -public class Foo { - void bar() { - for (;true;) true; // No Init or Update part, may as well be: while (true) - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## OverrideBothEqualsAndHashcode -**Since:** 0.4 - -**Priority:** Medium (3) - -Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. - -**Example(s):** -``` -public class Bar { // poor, missing a hashcode() method - public boolean equals(Object o) { - // do some comparison - } -} - -public class Baz { // poor, missing an equals() method - public int hashCode() { - // return some hash value - } -} - -public class Foo { // perfect, both methods provided - public boolean equals(Object other) { - // do some comparison - } - public int hashCode() { - // return some hash value - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## DoubleCheckedLocking -**Since:** 1.04 - -**Priority:** High (1) - -Partially created objects can be returned by the Double Checked Locking pattern when used in Java. -An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the -reference points to. - -Note: With Java 5, you can make Double checked locking work, if you declare the variable to be `volatile`. - -For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html -or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html - -**Example(s):** -``` -public class Foo { - /*volatile */ Object baz = null; // fix for Java5 and later: volatile - Object bar() { - if (baz == null) { // baz may be non-null yet not fully created - synchronized(this) { - if (baz == null) { - baz = new Object(); - } - } - } - return baz; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## ReturnFromFinallyBlock -**Since:** 1.05 - -**Priority:** Medium (3) - -Avoid returning from a finally block, this can discard exceptions. - -**Example(s):** -``` -public class Bar { - public String foo() { - try { - throw new Exception( "My Exception" ); - } catch (Exception e) { - throw e; - } finally { - return "A. O. K."; // return not recommended here - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UnconditionalIfStatement -**Since:** 1.5 - -**Priority:** Medium (3) - -Do not use "if" statements whose conditionals are always true or always false. - -**Example(s):** -``` -public class Foo { - public void close() { - if (true) { // fixed conditional, not recommended - // ... - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## BooleanInstantiation -**Since:** 1.2 +## AvoidBranchingStatementAsLastInLoop +**Since:** 5.0 **Priority:** Medium High (2) -Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. - -**Example(s):** -``` -Boolean bar = new Boolean("true"); // unnecessary creation, just reference Boolean.TRUE; -Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## CollapsibleIfStatements -**Since:** 3.1 - -**Priority:** Medium (3) - -Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. +Using a branching statement as the last part of a loop may be a bug, and/or is confusing. +Ensure that the usage is not a bug, or consider using another approach. **Example(s):** ``` -void bar() { - if (x) { // original implementation - if (y) { - // do stuff - } +// unusual use of branching statement in a loop +for (int i = 0; i < 10; i++) { + if (i*i <= 25) { + continue; } + break; } -void bar() { - if (x && y) { // optimized implementation - // do stuff + // this makes more sense... +for (int i = 0; i < 10; i++) { + if (i*i > 25) { + break; } } ``` @@ -242,41 +36,9 @@ void bar() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ClassCastExceptionWithToArray -**Since:** 3.4 - -**Priority:** Medium (3) - -When deriving an array of a specific class from your Collection, one should provide an array of -the same class as the parameter of the toArray() method. Doing otherwise you will will result -in a ClassCastException. - -**Example(s):** -``` -Collection c = new ArrayList(); -Integer obj = new Integer(1); -c.add(obj); - - // this would trigger the rule (and throw a ClassCastException if executed) -Integer[] a = (Integer [])c.toArray(); - - // this is fine and will not trigger the rule -Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|checkReturnLoopTypes|[for, do, while]|Check for return statements in loop types| +|checkContinueLoopTypes|[for, do, while]|Check for continue statements in loop types| +|checkBreakLoopTypes|[for, do, while]|Check for break statements in loop types| ## AvoidDecimalLiteralsInBigDecimalConstructor **Since:** 3.4 @@ -302,48 +64,34 @@ BigDecimal bd = new BigDecimal("1.123"); // preferred approach BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer values ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## MisplacedNullCheck -**Since:** 3.5 +## AvoidMultipleUnaryOperators +**Since:** 4.2 -**Priority:** Medium (3) +**Priority:** Medium High (2) -The null check here is misplaced. If the variable is null a NullPointerException will be thrown. -Either the check is useless (the variable will never be "null") or it is incorrect. +The use of multiple unary operators may be problematic, and/or confusing. +Ensure that the intended usage is not a bug, or consider simplifying the expression. **Example(s):** ``` -public class Foo { - void bar() { - if (a.equals(baz) && a != null) {} - } -} -``` - -``` -public class Foo { - void bar() { - if (a.equals(baz) || a == null) {} - } -} -``` +// These are typo bugs, or at best needlessly complex and confusing: +int i = - -1; +int j = + - +1; +int z = ~~2; +boolean b = !!true; +boolean c = !!!true; -**This rule has the following properties:** +// These are better: +int i = 1; +int j = -1; +int z = 2; +boolean b = true; +boolean c = false; -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +// And these just make your brain hurt: +int i = ~-2; +int j = -~7; +``` ## AvoidThreadGroup **Since:** 3.6 @@ -365,41 +113,48 @@ public class Bar { } ``` +## AvoidUsingHardCodedIP +**Since:** 4.1 + +**Priority:** Medium (3) + +Application with hard-coded IP addresses can become impossible to deploy in some cases. +Externalizing IP adresses is preferable. + +**Example(s):** +``` +public class Foo { + private String ip = "127.0.0.1"; // not recommended +} +``` + **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|checkAddressTypes|[IPv4, IPv6, IPv4 mapped IPv6]|Check for IP address types.| +|pattern|^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$|Regular Expression| -## BrokenNullCheck -**Since:** 3.8 +## AvoidUsingOctalValues +**Since:** 3.9 -**Priority:** Medium High (2) +**Priority:** Medium (3) -The null check is broken since it will throw a NullPointerException itself. -It is likely that you used || instead of && or vice versa. +Integer literals should not start with zero since this denotes that the rest of literal will be +interpreted as an octal value. **Example(s):** ``` -public String bar(String string) { - // should be && - if (string!=null || !string.equals("")) - return string; - // should be || - if (string==null && string.equals("")) - return string; -} +int i = 012; // set i with 10 not 12 +int j = 010; // set j with 8 not 10 +k = i * j; // set k with 80 not 120 ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|strict|false|Detect violations between 00 and 07| ## BigIntegerInstantiation **Since:** 3.9 @@ -418,60 +173,39 @@ BigInteger bi4; bi4 = new BigInteger(0); // reference BigInteger.ZERO instead ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AvoidUsingOctalValues -**Since:** 3.9 +## BooleanInstantiation +**Since:** 1.2 -**Priority:** Medium (3) +**Priority:** Medium High (2) -Integer literals should not start with zero since this denotes that the rest of literal will be -interpreted as an octal value. +Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. **Example(s):** ``` -int i = 012; // set i with 10 not 12 -int j = 010; // set j with 8 not 10 -k = i * j; // set k with 80 not 120 +Boolean bar = new Boolean("true"); // unnecessary creation, just reference Boolean.TRUE; +Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|strict|false|Detect violations between 00 and 07| - -## AvoidUsingHardCodedIP -**Since:** 4.1 +## BrokenNullCheck +**Since:** 3.8 -**Priority:** Medium (3) +**Priority:** Medium High (2) -Application with hard-coded IP addresses can become impossible to deploy in some cases. -Externalizing IP adresses is preferable. +The null check is broken since it will throw a NullPointerException itself. +It is likely that you used || instead of && or vice versa. **Example(s):** ``` -public class Foo { - private String ip = "127.0.0.1"; // not recommended +public String bar(String string) { + // should be && + if (string!=null || !string.equals("")) + return string; + // should be || + if (string==null && string.equals("")) + return string; } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|checkAddressTypes|[IPv4, IPv6, IPv4 mapped IPv6]|Check for IP address types.| -|pattern|^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$|Regular Expression| - ## CheckResultSet **Since:** 4.1 @@ -484,83 +218,18 @@ If the value return is 'false', it should be handled properly. ``` Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); -rst.next(); // what if it returns false? bad form -String firstName = rst.getString(1); - -Statement stat = conn.createStatement(); -ResultSet rst = stat.executeQuery("SELECT name FROM person"); -if (rst.next()) { // result is properly examined and used - String firstName = rst.getString(1); - } else { - // handle missing data -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AvoidMultipleUnaryOperators -**Since:** 4.2 - -**Priority:** Medium High (2) - -The use of multiple unary operators may be problematic, and/or confusing. -Ensure that the intended usage is not a bug, or consider simplifying the expression. - -**Example(s):** -``` -// These are typo bugs, or at best needlessly complex and confusing: -int i = - -1; -int j = + - +1; -int z = ~~2; -boolean b = !!true; -boolean c = !!!true; - -// These are better: -int i = 1; -int j = -1; -int z = 2; -boolean b = true; -boolean c = false; - -// And these just make your brain hurt: -int i = ~-2; -int j = -~7; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## ExtendsObject -**Since:** 5.0 - -**Priority:** Medium Low (4) - -No need to explicitly extend Object. +rst.next(); // what if it returns false? bad form +String firstName = rst.getString(1); -**Example(s):** -``` -public class Foo extends Object { // not required +Statement stat = conn.createStatement(); +ResultSet rst = stat.executeQuery("SELECT name FROM person"); +if (rst.next()) { // result is properly examined and used + String firstName = rst.getString(1); + } else { + // handle missing data } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## CheckSkipResult **Since:** 5.0 @@ -588,49 +257,52 @@ public class Foo { } ``` -**This rule has the following properties:** +## ClassCastExceptionWithToArray +**Since:** 3.4 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium (3) -## AvoidBranchingStatementAsLastInLoop -**Since:** 5.0 +When deriving an array of a specific class from your Collection, one should provide an array of +the same class as the parameter of the toArray() method. Doing otherwise you will will result +in a ClassCastException. -**Priority:** Medium High (2) +**Example(s):** +``` +Collection c = new ArrayList(); +Integer obj = new Integer(1); +c.add(obj); -Using a branching statement as the last part of a loop may be a bug, and/or is confusing. -Ensure that the usage is not a bug, or consider using another approach. + // this would trigger the rule (and throw a ClassCastException if executed) +Integer[] a = (Integer [])c.toArray(); + + // this is fine and will not trigger the rule +Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); +``` + +## CollapsibleIfStatements +**Since:** 3.1 + +**Priority:** Medium (3) + +Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. **Example(s):** ``` -// unusual use of branching statement in a loop -for (int i = 0; i < 10; i++) { - if (i*i <= 25) { - continue; +void bar() { + if (x) { // original implementation + if (y) { + // do stuff + } } - break; } - // this makes more sense... -for (int i = 0; i < 10; i++) { - if (i*i > 25) { - break; +void bar() { + if (x && y) { // optimized implementation + // do stuff } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|checkReturnLoopTypes|[for, do, while]|Check for return statements in loop types| -|checkContinueLoopTypes|[for, do, while]|Check for continue statements in loop types| -|checkBreakLoopTypes|[for, do, while]|Check for break statements in loop types| - ## DontCallThreadRun **Since:** 4.3 @@ -645,15 +317,6 @@ t.run(); // use t.start() instead new Thread().run(); // same violation ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## DontUseFloatTypeForLoopIndices **Since:** 4.3 @@ -678,14 +341,163 @@ public class Count { } ``` -**This rule has the following properties:** +## DoubleCheckedLocking +**Since:** 1.04 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** High (1) + +Partially created objects can be returned by the Double Checked Locking pattern when used in Java. +An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the +reference points to. + +Note: With Java 5, you can make Double checked locking work, if you declare the variable to be `volatile`. + +For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html +or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html + +**Example(s):** +``` +public class Foo { + /*volatile */ Object baz = null; // fix for Java5 and later: volatile + Object bar() { + if (baz == null) { // baz may be non-null yet not fully created + synchronized(this) { + if (baz == null) { + baz = new Object(); + } + } + } + return baz; + } +} +``` + +## ExtendsObject +**Since:** 5.0 + +**Priority:** Medium Low (4) + +No need to explicitly extend Object. + +**Example(s):** +``` +public class Foo extends Object { // not required +} +``` + +## ForLoopShouldBeWhileLoop +**Since:** 1.02 + +**Priority:** Medium (3) + +Some for loops can be simplified to while loops, this makes them more concise. + +**Example(s):** +``` +public class Foo { + void bar() { + for (;true;) true; // No Init or Update part, may as well be: while (true) + } +} +``` + +## JumbledIncrementer +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**Example(s):** +``` +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} +``` + +## MisplacedNullCheck +**Since:** 3.5 + +**Priority:** Medium (3) + +The null check here is misplaced. If the variable is null a NullPointerException will be thrown. +Either the check is useless (the variable will never be "null") or it is incorrect. + +**Example(s):** +``` +public class Foo { + void bar() { + if (a.equals(baz) && a != null) {} + } +} +``` + +``` +public class Foo { + void bar() { + if (a.equals(baz) || a == null) {} + } +} +``` + +## OverrideBothEqualsAndHashcode +**Since:** 0.4 + +**Priority:** Medium (3) + +Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. + +**Example(s):** +``` +public class Bar { // poor, missing a hashcode() method + public boolean equals(Object o) { + // do some comparison + } +} + +public class Baz { // poor, missing an equals() method + public int hashCode() { + // return some hash value + } +} + +public class Foo { // perfect, both methods provided + public boolean equals(Object other) { + // do some comparison + } + public int hashCode() { + // return some hash value + } +} +``` + +## ReturnFromFinallyBlock +**Since:** 1.05 + +**Priority:** Medium (3) + +Avoid returning from a finally block, this can discard exceptions. + +**Example(s):** +``` +public class Bar { + public String foo() { + try { + throw new Exception( "My Exception" ); + } catch (Exception e) { + throw e; + } finally { + return "A. O. K."; // return not recommended here + } + } +} +``` ## SimplifiedTernary **Since:** 5.4.0 @@ -723,12 +535,21 @@ public class Foo { } ``` -**This rule has the following properties:** +## UnconditionalIfStatement +**Since:** 1.5 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) + +Do not use "if" statements whose conditionals are always true or always false. + +**Example(s):** +``` +public class Foo { + public void close() { + if (true) { // fixed conditional, not recommended + // ... + } + } +} +``` diff --git a/docs/pages/pmd/rules/java/braces.md b/docs/pages/pmd/rules/java/braces.md index e4e7b8656..3b520a068 100644 --- a/docs/pages/pmd/rules/java/braces.md +++ b/docs/pages/pmd/rules/java/braces.md @@ -6,62 +6,21 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/braces.xml --- -## IfStmtsMustUseBraces -**Since:** 1.0 - -**Priority:** Medium (3) - -Avoid using if statements without using braces to surround the code block. If the code -formatting or indentation is lost then it becomes difficult to separate the code being -controlled from the rest. - -**Example(s):** -``` -if (foo) // not recommended - x++; - -if (foo) { // preferred approach - x++; -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## WhileLoopsMustUseBraces +## ForLoopsMustUseBraces **Since:** 0.7 **Priority:** Medium (3) -Avoid using 'while' statements without using braces to surround the code block. If the code -formatting or indentation is lost then it becomes difficult to separate the code being -controlled from the rest. +Avoid using 'for' statements without using curly braces. If the code formatting or +indentation is lost then it becomes difficult to separate the code being controlled +from the rest. **Example(s):** ``` -while (true) // not recommended - x++; - -while (true) { // preferred approach - x++; -} +for (int i = 0; i < 42; i++) + foo(); ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## IfElseStmtsMustUseBraces **Since:** 0.2 @@ -83,36 +42,41 @@ if (foo) x = x-1; ``` -**This rule has the following properties:** +## IfStmtsMustUseBraces +**Since:** 1.0 + +**Priority:** Medium (3) -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +Avoid using if statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. -## ForLoopsMustUseBraces +**Example(s):** +``` +if (foo) // not recommended + x++; + +if (foo) { // preferred approach + x++; +} +``` + +## WhileLoopsMustUseBraces **Since:** 0.7 **Priority:** Medium (3) -Avoid using 'for' statements without using curly braces. If the code formatting or -indentation is lost then it becomes difficult to separate the code being controlled -from the rest. +Avoid using 'while' statements without using braces to surround the code block. If the code +formatting or indentation is lost then it becomes difficult to separate the code being +controlled from the rest. **Example(s):** ``` -for (int i = 0; i < 42; i++) - foo(); +while (true) // not recommended + x++; + +while (true) { // preferred approach + x++; +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md index afb2348ed..62a91a3ab 100644 --- a/docs/pages/pmd/rules/java/clone.md +++ b/docs/pages/pmd/rules/java/clone.md @@ -6,57 +6,34 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/clone.xml --- -## ProperCloneImplementation -**Since:** 1.4 +## CloneMethodMustBePublic +**Since:** 5.4.0 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Object clone() should be implemented with super.clone(). +The java Manual says "By convention, classes that implement this interface should override +Object.clone (which is protected) with a public method." **Example(s):** ``` -class Foo{ - public Object clone(){ - return new Foo(); // This is bad +public class Foo implements Cloneable { + @Override + protected Object clone() throws CloneNotSupportedException { // Violation, must be public } } -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## CloneThrowsCloneNotSupportedException -**Since:** 1.9 - -**Priority:** Medium (3) -The method clone() should throw a CloneNotSupportedException. +public class Foo implements Cloneable { + @Override + protected Foo clone() { // Violation, must be public + } +} -**Example(s):** -``` -public class MyClass implements Cloneable{ - public Object clone() { // will cause an error - MyClass clone = (MyClass)super.clone(); - return clone; - } - } +public class Foo implements Cloneable { + @Override + public Object clone() // Ok +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## CloneMethodMustImplementCloneable **Since:** 1.9 @@ -73,15 +50,6 @@ public class MyClass { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## CloneMethodReturnTypeMustMatchClassName **Since:** 5.4.0 @@ -107,49 +75,36 @@ public class Foo implements Cloneable { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## CloneMethodMustBePublic -**Since:** 5.4.0 +## CloneThrowsCloneNotSupportedException +**Since:** 1.9 **Priority:** Medium (3) -The java Manual says "By convention, classes that implement this interface should override -Object.clone (which is protected) with a public method." +The method clone() should throw a CloneNotSupportedException. **Example(s):** ``` -public class Foo implements Cloneable { - @Override - protected Object clone() throws CloneNotSupportedException { // Violation, must be public - } -} +public class MyClass implements Cloneable{ + public Object clone() { // will cause an error + MyClass clone = (MyClass)super.clone(); + return clone; + } + } +``` -public class Foo implements Cloneable { - @Override - protected Foo clone() { // Violation, must be public - } -} +## ProperCloneImplementation +**Since:** 1.4 -public class Foo implements Cloneable { - @Override - public Object clone() // Ok -} -``` +**Priority:** Medium High (2) -**This rule has the following properties:** +Object clone() should be implemented with super.clone(). -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Example(s):** +``` +class Foo{ + public Object clone(){ + return new Foo(); // This is bad + } +} +``` diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md index 169b2115a..17cc32541 100644 --- a/docs/pages/pmd/rules/java/codesize.md +++ b/docs/pages/pmd/rules/java/codesize.md @@ -6,43 +6,89 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/codesize.xml --- -## NPathComplexity -**Since:** 3.9 +## CyclomaticComplexity +**Since:** 1.03 **Priority:** Medium (3) -The NPath complexity of a method is the number of acyclic execution paths through that method. -A threshold of 200 is generally considered the point where measures should be taken to reduce -complexity and increase readability. +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. **Example(s):** ``` -void bar() { // this is something more complex than it needs to be, - if (y) { // it should be broken down into smaller methods or functions - for (j = 0; j < m; j++) { - if (j > r) { - doSomething(); - while (f < 5 ) { - anotherThing(); - f -= 27; - } - } else { - tryThis(); - } - } - } - if ( r - n > 45) { - while (doMagic()) { - findRabbits(); - } - } - try { - doSomethingDangerous(); - } catch (Exception ex) { - makeAmends(); - } finally { - dontDoItAgain(); - } +public class Foo { // This has a Cyclomatic Complexity = 12 +1 public void example() { +2 if (a == b) { +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else{ + switch (z) { +9 case 1: + fiddle(); + break; +10 case 2: + fiddle(); + break; +11 case 3: + fiddle(); + break; +12 default: + fiddle(); + break; + } + } + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## ExcessiveClassLength +**Since:** 0.6 + +**Priority:** Medium (3) + +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. + +**Example(s):** +``` +public class Foo { + public void bar1() { + // 1000 lines of code + } + public void bar2() { + // 1000 lines of code + } + public void bar3() { + // 1000 lines of code + } + + + public void barN() { + // 1000 lines of code } } ``` @@ -51,8 +97,6 @@ void bar() { // this is something more complex than it needs to be, |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -80,8 +124,6 @@ public void doSomething() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -113,38 +155,32 @@ public void addPerson( // preferred approach |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| -## ExcessiveClassLength -**Since:** 0.6 +## ExcessivePublicCount +**Since:** 1.04 **Priority:** Medium (3) -Excessive class file lengths are usually indications that the class may be burdened with excessive -responsibilities that could be provided by external classes or functions. In breaking these methods -apart the code becomes more managable and ripe for reuse. +Classes with large numbers of public methods and attributes require disproportionate testing efforts +since combinational side effects grow rapidly and increase risk. Refactoring these classes into +smaller ones not only increases testability and reliability but also allows new variations to be +developed easily. **Example(s):** ``` public class Foo { - public void bar1() { - // 1000 lines of code - } - public void bar2() { - // 1000 lines of code - } - public void bar3() { - // 1000 lines of code - } - - - public void barN() { - // 1000 lines of code - } + public String value; + public Bar something; + public Variable var; + // [... more more public attributes ...] + + public void doWork() {} + public void doMoreWork() {} + public void doWorkAgain() {} + // [... more more public methods ...] } ``` @@ -152,132 +188,10 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| -## CyclomaticComplexity -**Since:** 1.03 - -**Priority:** Medium (3) - -Complexity directly affects maintenance costs is determined by the number of decision points in a method -plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. -Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote -high complexity, and 11+ is very high complexity. - -**Example(s):** -``` -public class Foo { // This has a Cyclomatic Complexity = 12 -1 public void example() { -2 if (a == b) { -3 if (a1 == b1) { - fiddle(); -4 } else if a2 == b2) { - fiddle(); - } else { - fiddle(); - } -5 } else if (c == d) { -6 while (c == d) { - fiddle(); - } -7 } else if (e == f) { -8 for (int n = 0; n < h; n++) { - fiddle(); - } - } else{ - switch (z) { -9 case 1: - fiddle(); - break; -10 case 2: - fiddle(); - break; -11 case 3: - fiddle(); - break; -12 default: - fiddle(); - break; - } - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|showMethodsComplexity|true|Add method average violations to the report| -|showClassesComplexity|true|Add class average violations to the report| -|reportLevel|10|Cyclomatic Complexity reporting threshold| - -## StdCyclomaticComplexity -**Since:** 5.1.2 - -**Priority:** Medium (3) - -Complexity directly affects maintenance costs is determined by the number of decision points in a method -plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. -Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote -high complexity, and 11+ is very high complexity. - -**Example(s):** -``` -public class Foo { // This has a Cyclomatic Complexity = 12 -1 public void example() { -2 if (a == b || (c == d && e == f)) { // Only one -3 if (a1 == b1) { - fiddle(); -4 } else if a2 == b2) { - fiddle(); - } else { - fiddle(); - } -5 } else if (c == d) { -6 while (c == d) { - fiddle(); - } -7 } else if (e == f) { -8 for (int n = 0; n < h; n++) { - fiddle(); - } - } else{ - switch (z) { -9 case 1: - fiddle(); - break; -10 case 2: - fiddle(); - break; -11 case 3: - fiddle(); - break; -12 default: - fiddle(); - break; - } - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|showMethodsComplexity|true|Add method average violations to the report| -|showClassesComplexity|true|Add class average violations to the report| -|reportLevel|10|Cyclomatic Complexity reporting threshold| - ## ModifiedCyclomaticComplexity **Since:** 5.1.2 @@ -333,69 +247,32 @@ public class Foo { // This has a Cyclomatic Complexity = 9 |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |showMethodsComplexity|true|Add method average violations to the report| |showClassesComplexity|true|Add class average violations to the report| |reportLevel|10|Cyclomatic Complexity reporting threshold| -## ExcessivePublicCount -**Since:** 1.04 +## NcssConstructorCount +**Since:** 3.9 **Priority:** Medium (3) -Classes with large numbers of public methods and attributes require disproportionate testing efforts -since combinational side effects grow rapidly and increase risk. Refactoring these classes into -smaller ones not only increases testability and reliability but also allows new variations to be -developed easily. +This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines +of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, +lines of code that are split are counted as one. **Example(s):** ``` -public class Foo { - public String value; - public Bar something; - public Variable var; - // [... more more public attributes ...] - - public void doWork() {} - public void doMoreWork() {} - public void doWorkAgain() {} - // [... more more public methods ...] -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| +public class Foo extends Bar { + public Foo() { + super(); -## TooManyFields -**Since:** 3.0 -**Priority:** Medium (3) -Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, -possibly through grouping related fields in new objects. For example, a class with individual -city/state/zip fields could park them within a single Address field. -**Example(s):** -``` -public class Person { // too many separate fields - int birthYear; - int birthMonth; - int birthDate; - float height; - float weight; -} -public class Person { // this is more manageable - Date birthDate; - BodyMeasurements measurements; + //this constructor only has 1 NCSS lines + super.foo(); + } } ``` @@ -403,9 +280,9 @@ public class Person { // this is more manageable |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|maxfields|15|Max allowable fields| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| ## NcssMethodCount **Since:** 3.9 @@ -436,8 +313,6 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -471,34 +346,106 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| -## NcssConstructorCount +## NPathComplexity **Since:** 3.9 **Priority:** Medium (3) -This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, -lines of code that are split are counted as one. +The NPath complexity of a method is the number of acyclic execution paths through that method. +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability. **Example(s):** ``` -public class Foo extends Bar { - public Foo() { - super(); +void bar() { // this is something more complex than it needs to be, + if (y) { // it should be broken down into smaller methods or functions + for (j = 0; j < m; j++) { + if (j > r) { + doSomething(); + while (f < 5 ) { + anotherThing(); + f -= 27; + } + } else { + tryThis(); + } + } + } + if ( r - n > 45) { + while (doMagic()) { + findRabbits(); + } + } + try { + doSomethingDangerous(); + } catch (Exception ex) { + makeAmends(); + } finally { + dontDoItAgain(); + } + } +} +``` +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| +## StdCyclomaticComplexity +**Since:** 5.1.2 +**Priority:** Medium (3) +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. - //this constructor only has 1 NCSS lines - super.foo(); - } +**Example(s):** +``` +public class Foo { // This has a Cyclomatic Complexity = 12 +1 public void example() { +2 if (a == b || (c == d && e == f)) { // Only one +3 if (a1 == b1) { + fiddle(); +4 } else if a2 == b2) { + fiddle(); + } else { + fiddle(); + } +5 } else if (c == d) { +6 while (c == d) { + fiddle(); + } +7 } else if (e == f) { +8 for (int n = 0; n < h; n++) { + fiddle(); + } + } else{ + switch (z) { +9 case 1: + fiddle(); + break; +10 case 2: + fiddle(); + break; +11 case 3: + fiddle(); + break; +12 default: + fiddle(); + break; + } + } + } } ``` @@ -506,11 +453,40 @@ public class Foo extends Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| + +## TooManyFields +**Since:** 3.0 + +**Priority:** Medium (3) + +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field. + +**Example(s):** +``` +public class Person { // too many separate fields + int birthYear; + int birthMonth; + int birthDate; + float height; + float weight; +} + +public class Person { // this is more manageable + Date birthDate; + BodyMeasurements measurements; +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|maxfields|15|Max allowable fields| ## TooManyMethods **Since:** 4.2 @@ -524,9 +500,5 @@ have more fine grained objects. |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |maxmethods|10|The method count reporting threshold| diff --git a/docs/pages/pmd/rules/java/comments.md b/docs/pages/pmd/rules/java/comments.md index e1b75f33d..4a98e3a09 100644 --- a/docs/pages/pmd/rules/java/comments.md +++ b/docs/pages/pmd/rules/java/comments.md @@ -6,6 +6,65 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/comments.xml --- +## CommentContent +**Since:** 5.0 + +**Priority:** Medium (3) + +A rule for the politically correct... we don't want to offend anyone. + +**Example(s):** +``` +// OMG, this is horrible, Bob is an idiot !!! +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|disallowedTerms|[idiot, jerk]|Illegal terms or phrases| +|caseSensitive|false|Case sensitive| +|wordsAreRegex|false|Use regular expressions| + +## CommentDefaultAccessModifier +**Since:** 5.4.0 + +**Priority:** Medium (3) + +To avoid mistakes if we want that a Method, Field or Nested class have a default access modifier + we must add a comment at the beginning of the Method, Field or Nested class. + By default the comment must be /* default */, if you want another, you have to provide a regex. + +**Example(s):** +``` +public class Foo { + final String stringValue = "some string"; + String getString() { + return stringValue; + } + + class NestedFoo { + } + } + + // should be + public class Foo { + /* default */ final String stringValue = "some string"; + /* default */ String getString() { + return stringValue; + } + + /* default */ class NestedFoo { + } + } +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|regex||Regular expression| + ## CommentRequired **Since:** 5.1 @@ -26,8 +85,6 @@ Denotes whether comments are required (or unwanted) for specific language elemen |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |serialVersionUIDCommentRequired|Ignored|serial version UID commts. Possible values: [Required, Ignored, Unwanted]| |enumCommentRequirement|Required|Enum comments. Possible values: [Required, Ignored, Unwanted]| |protectedMethodCommentRequirement|Required|Protected method constructor comments. Possible values: [Required, Ignored, Unwanted]| @@ -66,71 +123,6 @@ Determines whether the dimensions of non-header comments found are within the sp |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |maxLines|6|Maximum lines| |maxLineLength|80|Maximum line length| -## CommentContent -**Since:** 5.0 - -**Priority:** Medium (3) - -A rule for the politically correct... we don't want to offend anyone. - -**Example(s):** -``` -// OMG, this is horrible, Bob is an idiot !!! -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|disallowedTerms|[idiot, jerk]|Illegal terms or phrases| -|caseSensitive|false|Case sensitive| -|wordsAreRegex|false|Use regular expressions| - -## CommentDefaultAccessModifier -**Since:** 5.4.0 - -**Priority:** Medium (3) - -To avoid mistakes if we want that a Method, Field or Nested class have a default access modifier - we must add a comment at the beginning of the Method, Field or Nested class. - By default the comment must be /* default */, if you want another, you have to provide a regex. - -**Example(s):** -``` -public class Foo { - final String stringValue = "some string"; - String getString() { - return stringValue; - } - - class NestedFoo { - } - } - - // should be - public class Foo { - /* default */ final String stringValue = "some string"; - /* default */ String getString() { - return stringValue; - } - - /* default */ class NestedFoo { - } - } -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|regex||Regular expression| - diff --git a/docs/pages/pmd/rules/java/controversial.md b/docs/pages/pmd/rules/java/controversial.md index f661a0da6..32d90d960 100644 --- a/docs/pages/pmd/rules/java/controversial.md +++ b/docs/pages/pmd/rules/java/controversial.md @@ -6,84 +6,6 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/controversial.xml --- -## UnnecessaryConstructor -**Since:** 1.0 - -**Priority:** Medium (3) - -This rule detects when a constructor is not necessary; i.e., when there is only one constructor, -its public, has an empty body, and takes no arguments. - -**Example(s):** -``` -public class Foo { - public Foo() {} -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## NullAssignment -**Since:** 1.02 - -**Priority:** Medium (3) - -Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type -of assignment is an indication that the programmer doesn't completely understand what is going on in the code. - -NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. - -**Example(s):** -``` -public void bar() { - Object x = null; // this is OK - x = new Object(); - // big, complex piece of code here - x = null; // this is not required - // big, complex piece of code here -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## OnlyOneReturn -**Since:** 1.0 - -**Priority:** Medium (3) - -A method should have only one exit point, and that should be the last statement in the method. - -**Example(s):** -``` -public class OneReturnOnly1 { - public void foo(int x) { - if (x > 0) { - return "hey"; // first exit - } - return "hi"; // second exit - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## AssignmentInOperand **Since:** 1.03 @@ -105,8 +27,6 @@ public void bar() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| |allowWhile|false|Allow assignment within the conditional expression of a while statement| |allowFor|false|Allow assignment within the conditional expression of a for statement| @@ -128,195 +48,161 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## DontImportSun -**Since:** 1.5 +## AvoidAccessibilityAlteration +**Since:** 4.1 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. +Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(), +as the interface PrivilegedAction, allows for the runtime alteration of variable, class, or +method visibility, even if they are private. This violates the principle of encapsulation. **Example(s):** ``` -import sun.misc.foo; -public class Foo {} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SuspiciousOctalEscape -**Since:** 1.5 - -**Priority:** Medium (3) - -A suspicious octal escape sequence was found inside a String literal. -The Java language specification (section 3.10.6) says an octal -escape sequence inside a literal String shall consist of a backslash -followed by: - - OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Method; +import java.security.PrivilegedAction; -Any octal escape sequence followed by non-octal digits can be confusing, -e.g. "\038" is interpreted as the octal escape sequence "\03" followed by -the literal character "8". +public class Violation { + public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { + // Possible call to forbidden getDeclaredConstructors + Class[] arrayOfClass = new Class[1]; + this.getClass().getDeclaredConstructors(); + this.getClass().getDeclaredConstructor(arrayOfClass); + Class clazz = this.getClass(); + clazz.getDeclaredConstructor(arrayOfClass); + clazz.getDeclaredConstructors(); + // Possible call to forbidden setAccessible + clazz.getMethod("", arrayOfClass).setAccessible(false); + AccessibleObject.setAccessible(null, false); + Method.setAccessible(null, false); + Method[] methodsArray = clazz.getMethods(); + int nbMethod; + for ( nbMethod = 0; nbMethod < methodsArray.length; nbMethod++ ) { + methodsArray[nbMethod].setAccessible(false); + } -**Example(s):** -``` -public void foo() { - // interpreted as octal 12, followed by character '8' - System.out.println("suspicious: \128"); + // Possible call to forbidden PrivilegedAction + PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run(); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## CallSuperInConstructor -**Since:** 3.0 +## AvoidFinalLocalVariable +**Since:** 4.1 **Priority:** Medium (3) -It is a good practice to call super() in a constructor. If super() is not called but -another constructor (such as an overloaded constructor) is called, this rule will not report it. +Avoid using final local variables, turn them into fields. **Example(s):** ``` -public class Foo extends Bar{ - public Foo() { - // call the constructor of Bar - super(); - } - public Foo(int code) { - // do something with code - this(); - // no problem with this - } +public class MyClass { + public void foo() { + final String finalLocalVariable; + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UnnecessaryParentheses -**Since:** 3.1 +## AvoidLiteralsInIfCondition +**Since:** 4.2.6 **Priority:** Medium (3) -Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. +Avoid using hard-coded literals in conditional statements. By declaring them as static variables +or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. +More exceptions can be defined with the property "ignoreMagicNumbers". **Example(s):** ``` -public class Foo { - boolean bar() { - return (true); - } -} -``` +private static final int MAX_NUMBER_OF_REQUESTS = 10; -**This rule has the following properties:** +public void checkRequests() { -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| + if (i == 10) { // magic number, buried in a method + doSomething(); + } -## DefaultPackage -**Since:** 3.4 + if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach + doSomething(); + } -**Priority:** Medium (3) + if (aString.indexOf('.') != -1) {} // magic number -1, by default ignored + if (aString.indexOf('.') >= 0) { } // alternative approach -Use explicit scoping instead of accidental usage of default package private level. -The rule allows methods and fields annotated with Guava's @VisibleForTesting. + if (aDouble > 0.0) {} // magic number 0.0 + if (aDouble >= Double.MIN_VALUE) {} // preferred approach +} +``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## DataflowAnomalyAnalysis -**Since:** 3.9 +|ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored| -**Priority:** Low (5) +## AvoidPrefixingMethodParameters +**Since:** 5.0 -The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow. -From those informations there can be found various problems. +**Priority:** Medium Low (4) -1. UR - Anomaly: There is a reference to a variable that was not defined before. This is a bug and leads to an error. -2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text. -3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug. +Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readability. +To indicate whether or not a parameter will be modify in a method, its better to document method +behavior with Javadoc. **Example(s):** ``` -public void foo() { - int buz = 5; - buz = 6; // redefinition of buz -> dd-anomaly - foo(buz); - buz = 2; -} // buz is undefined when leaving scope -> du-anomaly +// Not really clear +public class Foo { + public void bar( + int inLeftOperand, + Result outRightOperand) { + outRightOperand.setValue(inLeftOperand * outRightOperand.getValue()); + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|maxViolations|100|Maximum number of anomalies per class| -|maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.| +``` +// Far more useful +public class Foo { + /** + * + * @param leftOperand, (purpose), not modified by method. + * @param rightOperand (purpose), will be modified by the method: contains the result. + */ + public void bar( + int leftOperand, + Result rightOperand) { + rightOperand.setValue(leftOperand * rightOperand.getValue()); + } +} +``` -## AvoidFinalLocalVariable +## AvoidUsingNativeCode **Since:** 4.1 -**Priority:** Medium (3) +**Priority:** Medium High (2) -Avoid using final local variables, turn them into fields. +Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability +and increases the maintenance burden. **Example(s):** ``` -public class MyClass { - public void foo() { - final String finalLocalVariable; - } -} -``` +public class SomeJNIClass { -**This rule has the following properties:** + public SomeJNIClass() { + System.loadLibrary("nativelib"); + } -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| + static { + System.loadLibrary("nativelib"); + } + + public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { + System.loadLibrary("nativelib"); + } +} +``` ## AvoidUsingShortType **Since:** 4.1 @@ -340,15 +226,6 @@ public class UsingShort { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## AvoidUsingVolatile **Since:** 4.1 @@ -366,98 +243,65 @@ public class ThrDeux { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidUsingNativeCode -**Since:** 4.1 - -**Priority:** Medium High (2) - -Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability -and increases the maintenance burden. - -**Example(s):** -``` -public class SomeJNIClass { - - public SomeJNIClass() { - System.loadLibrary("nativelib"); - } +## CallSuperInConstructor +**Since:** 3.0 - static { - System.loadLibrary("nativelib"); - } +**Priority:** Medium (3) - public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { - System.loadLibrary("nativelib"); - } +It is a good practice to call super() in a constructor. If super() is not called but +another constructor (such as an overloaded constructor) is called, this rule will not report it. + +**Example(s):** +``` +public class Foo extends Bar{ + public Foo() { + // call the constructor of Bar + super(); + } + public Foo(int code) { + // do something with code + this(); + // no problem with this + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +## DataflowAnomalyAnalysis +**Since:** 3.9 -## AvoidAccessibilityAlteration -**Since:** 4.1 +**Priority:** Low (5) -**Priority:** Medium (3) +The dataflow analysis tracks local definitions, undefinitions and references to variables on different paths on the data flow. +From those informations there can be found various problems. -Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(), -as the interface PrivilegedAction, allows for the runtime alteration of variable, class, or -method visibility, even if they are private. This violates the principle of encapsulation. +1. UR - Anomaly: There is a reference to a variable that was not defined before. This is a bug and leads to an error. +2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text. +3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug. **Example(s):** ``` -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Method; -import java.security.PrivilegedAction; - -public class Violation { - public void invalidCallsInMethod() throws SecurityException, NoSuchMethodException { - // Possible call to forbidden getDeclaredConstructors - Class[] arrayOfClass = new Class[1]; - this.getClass().getDeclaredConstructors(); - this.getClass().getDeclaredConstructor(arrayOfClass); - Class clazz = this.getClass(); - clazz.getDeclaredConstructor(arrayOfClass); - clazz.getDeclaredConstructors(); - // Possible call to forbidden setAccessible - clazz.getMethod("", arrayOfClass).setAccessible(false); - AccessibleObject.setAccessible(null, false); - Method.setAccessible(null, false); - Method[] methodsArray = clazz.getMethods(); - int nbMethod; - for ( nbMethod = 0; nbMethod < methodsArray.length; nbMethod++ ) { - methodsArray[nbMethod].setAccessible(false); - } - - // Possible call to forbidden PrivilegedAction - PrivilegedAction priv = (PrivilegedAction) new Object(); priv.run(); - } -} +public void foo() { + int buz = 5; + buz = 6; // redefinition of buz -> dd-anomaly + foo(buz); + buz = 2; +} // buz is undefined when leaving scope -> du-anomaly ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|maxViolations|100|Maximum number of anomalies per class| +|maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.| + +## DefaultPackage +**Since:** 3.4 + +**Priority:** Medium (3) + +Use explicit scoping instead of accidental usage of default package private level. +The rule allows methods and fields annotated with Guava's @VisibleForTesting. ## DoNotCallGarbageCollectionExplicitly **Since:** 4.2 @@ -494,14 +338,39 @@ public class GCCall { } ``` -**This rule has the following properties:** +## DontImportSun +**Since:** 1.5 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium Low (4) + +Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. + +**Example(s):** +``` +import sun.misc.foo; +public class Foo {} +``` + +## NullAssignment +**Since:** 1.02 + +**Priority:** Medium (3) + +Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, this type +of assignment is an indication that the programmer doesn't completely understand what is going on in the code. + +NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. + +**Example(s):** +``` +public void bar() { + Object x = null; // this is OK + x = new Object(); + // big, complex piece of code here + x = null; // this is not required + // big, complex piece of code here +} +``` ## OneDeclarationPerLine **Since:** 5.0 @@ -527,99 +396,103 @@ String name, |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.| -## AvoidPrefixingMethodParameters -**Since:** 5.0 +## OnlyOneReturn +**Since:** 1.0 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readability. -To indicate whether or not a parameter will be modify in a method, its better to document method -behavior with Javadoc. +A method should have only one exit point, and that should be the last statement in the method. **Example(s):** ``` -// Not really clear -public class Foo { - public void bar( - int inLeftOperand, - Result outRightOperand) { - outRightOperand.setValue(inLeftOperand * outRightOperand.getValue()); +public class OneReturnOnly1 { + public void foo(int x) { + if (x > 0) { + return "hey"; // first exit + } + return "hi"; // second exit } } ``` +## SuspiciousOctalEscape +**Since:** 1.5 + +**Priority:** Medium (3) + +A suspicious octal escape sequence was found inside a String literal. +The Java language specification (section 3.10.6) says an octal +escape sequence inside a literal String shall consist of a backslash +followed by: + + OctalDigit | OctalDigit OctalDigit | ZeroToThree OctalDigit OctalDigit + +Any octal escape sequence followed by non-octal digits can be confusing, +e.g. "\038" is interpreted as the octal escape sequence "\03" followed by +the literal character "8". + +**Example(s):** ``` -// Far more useful -public class Foo { - /** - * - * @param leftOperand, (purpose), not modified by method. - * @param rightOperand (purpose), will be modified by the method: contains the result. - */ - public void bar( - int leftOperand, - Result rightOperand) { - rightOperand.setValue(leftOperand * rightOperand.getValue()); - } +public void foo() { + // interpreted as octal 12, followed by character '8' + System.out.println("suspicious: \128"); } ``` -**This rule has the following properties:** +## UnnecessaryConstructor +**Since:** 1.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## AvoidLiteralsInIfCondition -**Since:** 4.2.6 +This rule detects when a constructor is not necessary; i.e., when there is only one constructor, +its public, has an empty body, and takes no arguments. + +**Example(s):** +``` +public class Foo { + public Foo() {} +} +``` + +## UnnecessaryParentheses +**Since:** 3.1 **Priority:** Medium (3) -Avoid using hard-coded literals in conditional statements. By declaring them as static variables -or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. -More exceptions can be defined with the property "ignoreMagicNumbers". +Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. **Example(s):** ``` -private static final int MAX_NUMBER_OF_REQUESTS = 10; +public class Foo { + boolean bar() { + return (true); + } +} +``` -public void checkRequests() { +## UseConcurrentHashMap +**Since:** 4.2.6 - if (i == 10) { // magic number, buried in a method - doSomething(); - } +**Priority:** Medium (3) - if (i == MAX_NUMBER_OF_REQUESTS) { // preferred approach - doSomething(); - } +Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can +perform efficient map reads without blocking other threads. - if (aString.indexOf('.') != -1) {} // magic number -1, by default ignored - if (aString.indexOf('.') >= 0) { } // alternative approach +**Example(s):** +``` +public class ConcurrentApp { + public void getMyInstance() { + Map map1 = new HashMap(); // fine for single-threaded access + Map map2 = new ConcurrentHashMap(); // preferred for use with multiple threads - if (aDouble > 0.0) {} // magic number 0.0 - if (aDouble >= Double.MIN_VALUE) {} // preferred approach + // the following case will be ignored by this rule + Map map3 = someModule.methodThatReturnMap(); // might be OK, if the returned map is already thread-safe + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored| - ## UseObjectForClearerAPI **Since:** 4.2.6 @@ -649,42 +522,3 @@ public class MyClass { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UseConcurrentHashMap -**Since:** 4.2.6 - -**Priority:** Medium (3) - -Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can -perform efficient map reads without blocking other threads. - -**Example(s):** -``` -public class ConcurrentApp { - public void getMyInstance() { - Map map1 = new HashMap(); // fine for single-threaded access - Map map2 = new ConcurrentHashMap(); // preferred for use with multiple threads - - // the following case will be ignored by this rule - Map map3 = someModule.methodThatReturnMap(); // might be OK, if the returned map is already thread-safe - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/coupling.md b/docs/pages/pmd/rules/java/coupling.md index 4540940aa..ac7168297 100644 --- a/docs/pages/pmd/rules/java/coupling.md +++ b/docs/pages/pmd/rules/java/coupling.md @@ -38,8 +38,6 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |threshold|20|Unique type reporting threshold| ## ExcessiveImports @@ -65,12 +63,47 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| +## LawOfDemeter +**Since:** 5.0 + +**Priority:** Medium (3) + +The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes or objects. +See also the references: +Andrew Hunt, David Thomas, and Ward Cunningham. The Pragmatic Programmer. From Journeyman to Master. Addison-Wesley Longman, Amsterdam, October 1999.; +K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented programs. Software, IEEE, 6(5):38–48, 1989.; +http://www.ccs.neu.edu/home/lieber/LoD.html; +http://en.wikipedia.org/wiki/Law_of_Demeter + +**Example(s):** +``` +public class Foo { + /** + * This example will result in two violations. + */ + public void example(Bar b) { + // this method call is ok, as b is a parameter of "example" + C c = b.getC(); + + // this method call is a violation, as we are using c, which we got from B. + // We should ask b directly instead, e.g. "b.doItOnC();" + c.doIt(); + + // this is also a violation, just expressed differently as a method chain without temporary variables. + b.getC().doIt(); + + // a constructor call, not a method call. + D d = new D(); + // this method call is ok, because we have create the new instance of D locally. + d.doSomethingElse(); + } +} +``` + ## LooseCoupling **Since:** 0.7 @@ -97,13 +130,6 @@ public Set getFoo() { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## LoosePackageCoupling **Since:** 5.0 @@ -127,52 +153,6 @@ public class Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |classes|[]|Allowed classes| |packages|[]|Restricted packages| -## LawOfDemeter -**Since:** 5.0 - -**Priority:** Medium (3) - -The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce coupling between classes or objects. -See also the references: -Andrew Hunt, David Thomas, and Ward Cunningham. The Pragmatic Programmer. From Journeyman to Master. Addison-Wesley Longman, Amsterdam, October 1999.; -K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented programs. Software, IEEE, 6(5):38–48, 1989.; -http://www.ccs.neu.edu/home/lieber/LoD.html; -http://en.wikipedia.org/wiki/Law_of_Demeter - -**Example(s):** -``` -public class Foo { - /** - * This example will result in two violations. - */ - public void example(Bar b) { - // this method call is ok, as b is a parameter of "example" - C c = b.getC(); - - // this method call is a violation, as we are using c, which we got from B. - // We should ask b directly instead, e.g. "b.doItOnC();" - c.doIt(); - - // this is also a violation, just expressed differently as a method chain without temporary variables. - b.getC().doIt(); - - // a constructor call, not a method call. - D d = new D(); - // this method call is ok, because we have create the new instance of D locally. - d.doSomethingElse(); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index ef6050c9f..2a919a596 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -6,119 +6,110 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/design.xml --- -## UseUtilityClass -**Since:** 0.3 +## AbstractClassWithoutAbstractMethod +**Since:** 3.0 **Priority:** Medium (3) -For classes that only have static methods, consider making them utility classes. -Note that this doesn't apply to abstract classes, since their subclasses may -well include non-static methods. Also, if you want this class to be a utility class, -remember to add a private constructor to prevent instantiation. -(Note, that this use was known before PMD 5.1.0 as UseSingleton). +The abstract class does not contain any abstract methods. An abstract class suggests +an incomplete implementation, which is to be completed by subclasses implementing the +abstract methods. If the class is intended to be used as a base class only (not to be instantiated +directly) a protected constructor can be provided prevent direct instantiation. **Example(s):** ``` -public class MaybeAUtility { - public static void foo() {} - public static void bar() {} +public abstract class Foo { + void int method1() { ... } + void int method2() { ... } + // consider using abstract methods or removing + // the abstract modifier and adding protected constructors } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SimplifyBooleanReturns -**Since:** 0.9 +## AbstractClassWithoutAnyMethod +**Since:** 4.2 -**Priority:** Medium (3) +**Priority:** High (1) -Avoid unnecessary if-then-else statements when returning a boolean. The result of -the conditional test can be returned instead. +If an abstract class does not provides any methods, it may be acting as a simple data container +that is not meant to be instantiated. In this case, it is probably better to use a private or +protected constructor in order to prevent instantiation than make the class misleadingly abstract. **Example(s):** ``` -public boolean isBarEqualTo(int x) { - - if (bar == x) { // this bit of code... - return true; - } else { - return false; - } +public class abstract Example { + String field; + int otherField; } +``` -public boolean isBarEqualTo(int x) { +## AccessorClassGeneration +**Since:** 1.04 - return bar == x; // can be replaced with this -} -``` +**Priority:** Medium (3) -**This rule has the following properties:** +Instantiation by way of private constructors from outside of the constructor's class often causes the +generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this +situation. The generated class file is actually an interface. It gives the accessing class the ability +to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. +This turns a private constructor effectively into one with package scope, and is challenging to discern. -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Example(s):** +``` +public class Outer { + void method(){ + Inner ic = new Inner();//Causes generation of accessor class + } + public class Inner { + private Inner(){} + } +} +``` -## SimplifyBooleanExpressions -**Since:** 1.05 +## AccessorMethodGeneration +**Since:** 5.5.4 **Priority:** Medium (3) -Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. +When accessing a private field / method from another class, the Java compiler will generate a accessor methods +with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can +be avoided by changing the visibility of the field / method from private to package-private. **Example(s):** ``` -public class Bar { - // can be simplified to - // bar = isFoo(); - private boolean bar = (isFoo() == true); +public class OuterClass { + private int counter; + /* package */ int id; - public isFoo() { return false;} + public class InnerClass { + InnerClass() { + OuterClass.this.counter++; // wrong accessor method will be generated + } + + public int getOuterClassId() { + return OuterClass.this.id; // id is package-private, no accessor method needed + } + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## SwitchStmtsShouldHaveDefault -**Since:** 1.0 +## AssignmentToNonFinalStatic +**Since:** 2.2 **Priority:** Medium (3) -All switch statements should include a default option to catch any unspecified values. +Identifies a possible unsafe usage of a static field. **Example(s):** ``` -public void bar() { - int x = 2; - switch (x) { - case 1: int j = 6; - case 2: int j = 8; - // missing default: here - } +public class StaticField { + static int x; + public FinalFields(int y) { + x = y; // unsafe + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## AvoidDeeplyNestedIfStmts **Since:** 1.0 @@ -145,10 +136,65 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |problemDepth|3|The if statement depth reporting threshold| +## AvoidInstanceofChecksInCatchClause +**Since:** 3.0 + +**Priority:** Medium (3) + +Each caught exception type should be handled in its own catch clause. + +**Example(s):** +``` +try { // Avoid this + // do something +} catch (Exception ee) { + if (ee instanceof IOException) { + cleanup(); + } +} +try { // Prefer this: + // do something +} catch (IOException ee) { + cleanup(); +} +``` + +## AvoidProtectedFieldInFinalClass +**Since:** 2.1 + +**Priority:** Medium (3) + +Do not use protected fields in final classes since they cannot be subclassed. +Clarify your intent by using private or package access modifiers instead. + +**Example(s):** +``` +public final class Bar { + private int x; + protected int y; // bar cannot be subclassed, so is y really private or package visible? + Bar() {} +} +``` + +## AvoidProtectedMethodInFinalClassNotExtending +**Since:** 5.1 + +**Priority:** Medium (3) + +Do not use protected methods in most final classes since they cannot be subclassed. This should +only be allowed in final classes that extend other classes with protected methods (whose +visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead. + +**Example(s):** +``` +public final class Foo { + private int bar() {} + protected int baz() {} // Foo cannot be subclassed, and doesn't extend anything, so is baz() really private or package visible? +} +``` + ## AvoidReassigningParameters **Since:** 1.0 @@ -165,145 +211,67 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SwitchDensity -**Since:** 1.02 +## AvoidSynchronizedAtMethodLevel +**Since:** 3.0 **Priority:** Medium (3) -A high ratio of statements to labels in a switch statement implies that the switch statement -is overloaded. Consider moving the statements into new methods or creating subclasses based -on the switch variable. +Method-level synchronization can cause problems when new code is added to the method. +Block-level synchronization helps to ensure that only the code that needs synchronization +gets it. **Example(s):** ``` public class Foo { - public void bar(int x) { - switch (x) { - case 1: { - // lots of statements - break; - } case 2: { - // lots of statements - break; - } + // Try to avoid this: + synchronized void foo() { + } + // Prefer this: + void bar() { + synchronized(this) { + } + } + + // Try to avoid this for static methods: + static synchronized void fooStatic() { + } + + // Prefer this: + static void barStatic() { + synchronized(Foo.class) { } } } ``` -**This rule has the following properties:** +## BadComparison +**Since:** 1.8 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| +**Priority:** Medium (3) -## ConstructorCallsOverridableMethod -**Since:** 1.04 +Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation +precision when comparing floating point numbers these are likely to cause logic errors. + +**Example(s):** +``` +boolean x = (y == Double.NaN); +``` + +## ClassWithOnlyPrivateConstructorsShouldBeFinal +**Since:** 4.1 **Priority:** High (1) -Calling overridable methods during construction poses a risk of invoking methods on an incompletely -constructed object and can be difficult to debug. -It may leave the sub-class unable to construct its superclass or forced to replicate the construction -process completely within itself, losing the ability to call super(). If the default constructor -contains a call to an overridable method, the subclass may be completely uninstantiable. Note that -this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a -private method bar() that calls a public method buz(), this denotes a problem. +A class with only private constructors should be final, unless the private constructor +is invoked by a inner class. **Example(s):** ``` -public class SeniorClass { - public SeniorClass(){ - toString(); //may throw NullPointerException if overridden - } - public String toString(){ - return "IAmSeniorClass"; - } -} -public class JuniorClass extends SeniorClass { - private String name; - public JuniorClass(){ - super(); //Automatic call leads to NullPointerException - name = "JuniorClass"; - } - public String toString(){ - return name.toUpperCase(); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AccessorClassGeneration -**Since:** 1.04 - -**Priority:** Medium (3) - -Instantiation by way of private constructors from outside of the constructor's class often causes the -generation of an accessor. A factory method, or non-privatization of the constructor can eliminate this -situation. The generated class file is actually an interface. It gives the accessing class the ability -to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. -This turns a private constructor effectively into one with package scope, and is challenging to discern. - -**Example(s):** -``` -public class Outer { - void method(){ - Inner ic = new Inner();//Causes generation of accessor class - } - public class Inner { - private Inner(){} - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## FinalFieldCouldBeStatic -**Since:** 1.1 - -**Priority:** Medium (3) - -If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead -in each object at runtime. - -**Example(s):** -``` -public class Foo { - public final int BAR = 42; // this could be static and save some space +public class Foo { //Should be final + private Foo() { } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## CloseResource **Since:** 1.2.2 @@ -332,94 +300,83 @@ public class Bar { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |closeAsDefaultTarget|true|Consider 'close' as a target by default| |types|[java.sql.Connection, java.sql.Statement, java.sql.ResultSet]|Affected types| |closeTargets|[]|Methods which may close this resource| -## NonStaticInitializer -**Since:** 1.5 +## CompareObjectsWithEquals +**Since:** 3.2 **Priority:** Medium (3) -A non-static initializer block will be called any time a constructor is invoked (just prior to -invoking the constructor). While this is a valid language construct, it is rarely used and is -confusing. +Use equals() to compare object references; avoid comparing them with ==. **Example(s):** ``` -public class MyClass { - // this block gets run before any call to a constructor - { - System.out.println("I am about to construct myself"); +class Foo { + boolean bar(String a, String b) { + return a == b; } } ``` -**This rule has the following properties:** +## ConfusingTernary +**Since:** 1.9 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## DefaultLabelNotLastInSwitchStmt -**Since:** 1.5 +Avoid negation within an "if" expression with an "else" clause. For example, rephrase: -**Priority:** Medium (3) + if (x != y) diff(); else same(); +as: + if (x == y) same(); else diff(); -By convention, the default label should be the last label in a switch statement. +Most "if (x != y)" cases without an "else" are often return cases, so consistent use of this +rule makes the code easier to read. Also, this resolves trivial ordering problems, such +as "does the error case go first?" or "does the common case go first?". **Example(s):** ``` -public class Foo { - void bar(int a) { - switch (a) { - case 1: // do something - break; - default: // the default case should be last, by convention - break; - case 2: - break; - } - } -} +boolean bar(int x, int y) { + return (x != y) ? diff : same; + } ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|ignoreElseIf|false|Ignore conditions with an else-if case| -## NonCaseLabelInSwitchStatement -**Since:** 1.5 +## ConstantsInInterface +**Since:** 5.5 **Priority:** Medium (3) -A non-case label (e.g. a named break/continue label) was present in a switch statement. -This legal, but confusing. It is easy to mix up the case labels and the non-case labels. +Avoid constants in interfaces. Interfaces should define types, constants are implementation details +better placed in classes or enums. See Effective Java, item 19. **Example(s):** ``` -public class Foo { - void bar(int a) { - switch (a) { - case 1: - // do something - break; - mylabel: // this is legal, but confusing! - break; - default: - break; - } - } +public interface ConstantInterface { + public static final int CONST1 = 1; // violation, no fields allowed in interface! + static final int CONST2 = 1; // violation, no fields allowed in interface! + final int CONST3 = 1; // violation, no fields allowed in interface! + int CONST4 = 1; // violation, no fields allowed in interface! +} + +// with ignoreIfHasMethods = false +public interface AnotherConstantInterface { + public static final int CONST1 = 1; // violation, no fields allowed in interface! + + int anyMethod(); +} + +// with ignoreIfHasMethods = true +public interface YetAnotherConstantInterface { + public static final int CONST1 = 1; // no violation + + int anyMethod(); } ``` @@ -427,62 +384,86 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods| -## OptimizableToArrayCall -**Since:** 1.8 +## ConstructorCallsOverridableMethod +**Since:** 1.04 -**Priority:** Medium (3) +**Priority:** High (1) -Calls to a collection's toArray() method should specify target arrays sized to match the size of the -collection. Initial arrays that are too small are discarded in favour of new ones that have to be created -that are the proper size. +Calling overridable methods during construction poses a risk of invoking methods on an incompletely +constructed object and can be difficult to debug. +It may leave the sub-class unable to construct its superclass or forced to replicate the construction +process completely within itself, losing the ability to call super(). If the default constructor +contains a call to an overridable method, the subclass may be completely uninstantiable. Note that +this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a +private method bar() that calls a public method buz(), this denotes a problem. **Example(s):** ``` -List foos = getFoos(); - - // inefficient, the array will be discarded -Foo[] fooArray = foos.toArray(new Foo[0]); - - // much better; this one sizes the destination array, - // avoiding of a new one via reflection -Foo[] fooArray = foos.toArray(new Foo[foos.size()]); +public class SeniorClass { + public SeniorClass(){ + toString(); //may throw NullPointerException if overridden + } + public String toString(){ + return "IAmSeniorClass"; + } +} +public class JuniorClass extends SeniorClass { + private String name; + public JuniorClass(){ + super(); //Automatic call leads to NullPointerException + name = "JuniorClass"; + } + public String toString(){ + return name.toUpperCase(); + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## BadComparison -**Since:** 1.8 +## DefaultLabelNotLastInSwitchStmt +**Since:** 1.5 **Priority:** Medium (3) -Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation -precision when comparing floating point numbers these are likely to cause logic errors. +By convention, the default label should be the last label in a switch statement. **Example(s):** ``` -boolean x = (y == Double.NaN); +public class Foo { + void bar(int a) { + switch (a) { + case 1: // do something + break; + default: // the default case should be last, by convention + break; + case 2: + break; + } + } +} ``` -**This rule has the following properties:** +## EmptyMethodInAbstractClassShouldBeAbstract +**Since:** 4.1 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** High (1) + +Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate +usage by developers who should be implementing their own versions in the concrete subclasses. + +**Example(s):** +``` +public abstract class ShouldBeAbstract { + public Object couldBeAbstract() { + // Should be abstract method ? + return null; + } + + public void couldBeAbstract() { + } +} +``` ## EqualsNull **Since:** 1.9 @@ -504,84 +485,26 @@ if (x == null) { // preferred } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ConfusingTernary -**Since:** 1.9 +## FieldDeclarationsShouldBeAtStartOfClass +**Since:** 5.0 **Priority:** Medium (3) -Avoid negation within an "if" expression with an "else" clause. For example, rephrase: - - if (x != y) diff(); else same(); -as: - if (x == y) same(); else diff(); - -Most "if (x != y)" cases without an "else" are often return cases, so consistent use of this -rule makes the code easier to read. Also, this resolves trivial ordering problems, such -as "does the error case go first?" or "does the common case go first?". - -**Example(s):** -``` -boolean bar(int x, int y) { - return (x != y) ? diff : same; - } -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|ignoreElseIf|false|Ignore conditions with an else-if case| - -## InstantiationToGetClass -**Since:** 2.0 - -**Priority:** Medium Low (4) - -Avoid instantiating an object just to call getClass() on it; use the .class public member instead. +Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. **Example(s):** ``` -// replace this -Class c = new String().getClass(); - - // with this: -Class c = String.class; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## IdempotentOperations -**Since:** 2.0 +public class HelloWorldBean { -**Priority:** Medium (3) + // Field declared before methods / inner classes - OK + private String _thing; -Avoid idempotent operations - they have no effect. + public String getMessage() { + return "Hello World!"; + } -**Example(s):** -``` -public class Foo { - public void bar() { - int x = 2; - x = x; - } + // Field declared after methods / inner classes - avoid this + private String _fieldInWrongLocation; } ``` @@ -589,469 +512,207 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.| +|ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations| +|ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.| -## SimpleDateFormatNeedsLocale -**Since:** 2.0 +## FinalFieldCouldBeStatic +**Since:** 1.1 **Priority:** Medium (3) -Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate -formatting is used. +If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead +in each object at runtime. **Example(s):** ``` public class Foo { - // Should specify Locale.US (or whatever) - private SimpleDateFormat sdf = new SimpleDateFormat("pattern"); + public final int BAR = 42; // this could be static and save some space } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ImmutableField -**Since:** 2.0 +## GodClass +**Since:** 5.0 **Priority:** Medium (3) -Identifies private fields whose values never change once they are initialized either in the declaration -of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. - -**Example(s):** -``` -public class Foo { - private int x; // could be final - public Foo() { - x = 7; - } - public void foo() { - int a = x + 2; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +The God Class rule detects the God Class design flaw using metrics. God classes do too many things, +are very big and overly complex. They should be split apart to be more object-oriented. +The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". +The violations are reported against the entire class. See also the references: +Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: +Using Software Metrics to Characterize, Evaluate, and Improve the Design +of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. -## UseLocaleWithCaseConversions +## IdempotentOperations **Since:** 2.0 **Priority:** Medium (3) -When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that -have unusual conventions, i.e. Turkish. - -**Example(s):** -``` -class Foo { - // BAD - if (x.toLowerCase().equals("list")) { } - /* - This will not match "LIST" when in Turkish locale - The above could be - if (x.toLowerCase(Locale.US).equals("list")) { } - or simply - if (x.equalsIgnoreCase("list")) { } - */ - // GOOD - String z = a.toLowerCase(Locale.EN); -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidProtectedFieldInFinalClass -**Since:** 2.1 - -**Priority:** Medium (3) - -Do not use protected fields in final classes since they cannot be subclassed. -Clarify your intent by using private or package access modifiers instead. - -**Example(s):** -``` -public final class Bar { - private int x; - protected int y; // bar cannot be subclassed, so is y really private or package visible? - Bar() {} -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AssignmentToNonFinalStatic -**Since:** 2.2 - -**Priority:** Medium (3) - -Identifies a possible unsafe usage of a static field. - -**Example(s):** -``` -public class StaticField { - static int x; - public FinalFields(int y) { - x = y; // unsafe - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## MissingStaticMethodInNonInstantiatableClass -**Since:** 3.0 - -**Priority:** Medium (3) - -A class that has private constructors and does not have any static methods or fields cannot be used. - -**Example(s):** -``` -// This class is unusable, since it cannot be -// instantiated (private constructor), -// and no static method can be called. - -public class Foo { - private Foo() {} - void foo() {} -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidSynchronizedAtMethodLevel -**Since:** 3.0 - -**Priority:** Medium (3) - -Method-level synchronization can cause problems when new code is added to the method. -Block-level synchronization helps to ensure that only the code that needs synchronization -gets it. +Avoid idempotent operations - they have no effect. **Example(s):** ``` public class Foo { - // Try to avoid this: - synchronized void foo() { - } - // Prefer this: - void bar() { - synchronized(this) { - } - } - - // Try to avoid this for static methods: - static synchronized void fooStatic() { - } - - // Prefer this: - static void barStatic() { - synchronized(Foo.class) { - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## MissingBreakInSwitch -**Since:** 3.0 - -**Priority:** Medium (3) - -Switch statements without break or return statements for each case option -may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. - -**Example(s):** -``` -public void bar(int status) { - switch(status) { - case CANCELLED: - doCancelled(); - // break; hm, should this be commented out? - case NEW: - doNew(); - // is this really a fall-through? - case REMOVED: - doRemoved(); - // what happens if you add another case after this one? - case OTHER: // empty case - this is interpreted as an intentional fall-through - case ERROR: - doErrorHandling(); - break; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UseNotifyAllInsteadOfNotify -**Since:** 3.0 - -**Priority:** Medium (3) - -Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only -one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. - -**Example(s):** -``` -void bar() { - x.notify(); - // If many threads are monitoring x, only one (and you won't know which) will be notified. - // use instead: - x.notifyAll(); - } -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidInstanceofChecksInCatchClause -**Since:** 3.0 - -**Priority:** Medium (3) - -Each caught exception type should be handled in its own catch clause. - -**Example(s):** -``` -try { // Avoid this - // do something -} catch (Exception ee) { - if (ee instanceof IOException) { - cleanup(); + public void bar() { + int x = 2; + x = x; } } -try { // Prefer this: - // do something -} catch (IOException ee) { - cleanup(); -} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AbstractClassWithoutAbstractMethod -**Since:** 3.0 - +## ImmutableField +**Since:** 2.0 + **Priority:** Medium (3) -The abstract class does not contain any abstract methods. An abstract class suggests -an incomplete implementation, which is to be completed by subclasses implementing the -abstract methods. If the class is intended to be used as a base class only (not to be instantiated -directly) a protected constructor can be provided prevent direct instantiation. +Identifies private fields whose values never change once they are initialized either in the declaration +of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. **Example(s):** ``` -public abstract class Foo { - void int method1() { ... } - void int method2() { ... } - // consider using abstract methods or removing - // the abstract modifier and adding protected constructors +public class Foo { + private int x; // could be final + public Foo() { + x = 7; + } + public void foo() { + int a = x + 2; + } } ``` -**This rule has the following properties:** +## InstantiationToGetClass +**Since:** 2.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium Low (4) -## SimplifyConditional -**Since:** 3.1 +Avoid instantiating an object just to call getClass() on it; use the .class public member instead. + +**Example(s):** +``` +// replace this +Class c = new String().getClass(); + + // with this: +Class c = String.class; +``` + +## LogicInversion +**Since:** 5.0 **Priority:** Medium (3) -No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. +Use opposite operator instead of negating the whole expression with a logic complement operator. **Example(s):** ``` -class Foo { - void bar(Object x) { - if (x != null && x instanceof Bar) { - // just drop the "x != null" check +public boolean bar(int a, int b) { + + if (!(a == b)) { // use != + return false; + } + + if (!(a < b)) { // use >= + return false; } - } + + return true; } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## CompareObjectsWithEquals -**Since:** 3.2 +## MissingBreakInSwitch +**Since:** 3.0 **Priority:** Medium (3) -Use equals() to compare object references; avoid comparing them with ==. +Switch statements without break or return statements for each case option +may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. **Example(s):** ``` -class Foo { - boolean bar(String a, String b) { - return a == b; - } +public void bar(int status) { + switch(status) { + case CANCELLED: + doCancelled(); + // break; hm, should this be commented out? + case NEW: + doNew(); + // is this really a fall-through? + case REMOVED: + doRemoved(); + // what happens if you add another case after this one? + case OTHER: // empty case - this is interpreted as an intentional fall-through + case ERROR: + doErrorHandling(); + break; + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## PositionLiteralsFirstInComparisons -**Since:** 3.3 +## MissingStaticMethodInNonInstantiatableClass +**Since:** 3.0 **Priority:** Medium (3) -Position literals first in comparisons, if the second argument is null then NullPointerExceptions -can be avoided, they will just return false. +A class that has private constructors and does not have any static methods or fields cannot be used. **Example(s):** ``` -class Foo { - boolean bar(String x) { - return x.equals("2"); // should be "2".equals(x) - } +// This class is unusable, since it cannot be +// instantiated (private constructor), +// and no static method can be called. + +public class Foo { + private Foo() {} + void foo() {} } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## PositionLiteralsFirstInCaseInsensitiveComparisons -**Since:** 5.1 +## NonCaseLabelInSwitchStatement +**Since:** 1.5 **Priority:** Medium (3) -Position literals first in comparisons, if the second argument is null then NullPointerExceptions -can be avoided, they will just return false. +A non-case label (e.g. a named break/continue label) was present in a switch statement. +This legal, but confusing. It is easy to mix up the case labels and the non-case labels. **Example(s):** ``` -class Foo { - boolean bar(String x) { - return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x) +public class Foo { + void bar(int a) { + switch (a) { + case 1: + // do something + break; + mylabel: // this is legal, but confusing! + break; + default: + break; + } } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UnnecessaryLocalBeforeReturn -**Since:** 3.3 +## NonStaticInitializer +**Since:** 1.5 **Priority:** Medium (3) -Avoid the creation of unnecessary local variables +A non-static initializer block will be called any time a constructor is invoked (just prior to +invoking the constructor). While this is a valid language construct, it is rarely used and is +confusing. **Example(s):** ``` -public class Foo { - public int foo() { - int x = doSomething(); - return x; // instead, just 'return doSomething();' - } +public class MyClass { + // this block gets run before any call to a constructor + { + System.out.println("I am about to construct myself"); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|statementOrderMatters|true|If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.| - ## NonThreadSafeSingleton **Since:** 3.4 @@ -1086,154 +747,64 @@ public static Foo getFoo() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.| |checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.| -## SingleMethodSingleton -**Since:** 5.4 - -**Priority:** Medium High (2) - -Some classes contain overloaded getInstance. The problem with overloaded getInstance methods -is that the instance created using the overloaded method is not cached and so, - for each call and new objects will be created for every invocation. - -**Example(s):** -``` -public class Singleton { - - private static Singleton singleton = new Singleton( ); - - private Singleton(){ } - -public static Singleton getInstance( ) { - return singleton; -} -public static Singleton getInstance(Object obj){ - Singleton singleton = (Singleton) obj; - return singleton; //violation -} -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SingletonClassReturningNewInstance -**Since:** 5.4 - -**Priority:** Medium High (2) - -Some classes contain overloaded getInstance. The problem with overloaded getInstance methods -is that the instance created using the overloaded method is not cached and so, - for each call and new objects will be created for every invocation. - -**Example(s):** -``` -class Singleton { - private static Singleton instance = null; - public static Singleton getInstance() { - synchronized(Singleton.class){ - return new Singleton(); - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UncommentedEmptyMethodBody -**Since:** 3.4 +## OptimizableToArrayCall +**Since:** 1.8 **Priority:** Medium (3) -Uncommented Empty Method Body finds instances where a method body does not contain -statements, but there is no comment. By explicitly commenting empty method bodies -it is easier to distinguish between intentional (commented) and unintentional -empty methods. +Calls to a collection's toArray() method should specify target arrays sized to match the size of the +collection. Initial arrays that are too small are discarded in favour of new ones that have to be created +that are the proper size. **Example(s):** ``` -public void doSomething() { -} -``` +List foos = getFoos(); -**This rule has the following properties:** + // inefficient, the array will be discarded +Foo[] fooArray = foos.toArray(new Foo[0]); -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| + // much better; this one sizes the destination array, + // avoiding of a new one via reflection +Foo[] fooArray = foos.toArray(new Foo[foos.size()]); +``` -## UncommentedEmptyConstructor -**Since:** 3.4 +## PositionLiteralsFirstInCaseInsensitiveComparisons +**Since:** 5.1 **Priority:** Medium (3) -Uncommented Empty Constructor finds instances where a constructor does not -contain statements, but there is no comment. By explicitly commenting empty -constructors it is easier to distinguish between intentional (commented) -and unintentional empty constructors. +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false. **Example(s):** ``` -public Foo() { - // This constructor is intentionally empty. Nothing special is needed here. +class Foo { + boolean bar(String x) { + return x.equalsIgnoreCase("2"); // should be "2".equalsIgnoreCase(x) + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not| - -## UnsynchronizedStaticDateFormatter -**Since:** 3.6 +## PositionLiteralsFirstInComparisons +**Since:** 3.3 **Priority:** Medium (3) -SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances -for each thread. If multiple threads must access a static formatter, the formatter must be -synchronized either on method or block level. +Position literals first in comparisons, if the second argument is null then NullPointerExceptions +can be avoided, they will just return false. **Example(s):** ``` -public class Foo { - private static final SimpleDateFormat sdf = new SimpleDateFormat(); - void bar() { - sdf.format(); // poor, no thread-safety - } - synchronized void foo() { - sdf.format(); // preferred - } +class Foo { + boolean bar(String x) { + return x.equals("2"); // should be "2".equals(x) + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## PreserveStackTrace **Since:** 3.7 @@ -1268,100 +839,156 @@ public class Foo { } ``` -**This rule has the following properties:** +## ReturnEmptyArrayRatherThanNull +**Since:** 4.2 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** High (1) -## UseCollectionIsEmpty -**Since:** 3.9 +For any method that returns an array, it is a better to return an empty array rather than a +null reference. This removes the need for null checking all results and avoids inadvertent +NullPointerExceptions. + +**Example(s):** +``` +public class Example { + // Not a good idea... + public int[] badBehavior() { + // ... + return null; + } + + // Good behavior + public String[] bonnePratique() { + //... + return new String[0]; + } +} +``` + +## SimpleDateFormatNeedsLocale +**Since:** 2.0 **Priority:** Medium (3) -The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. -Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. +Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate +formatting is used. **Example(s):** ``` public class Foo { - void good() { - List foo = getList(); - if (foo.isEmpty()) { - // blah - } - } - - void bad() { - List foo = getList(); - if (foo.size() == 0) { - // blah - } - } + // Should specify Locale.US (or whatever) + private SimpleDateFormat sdf = new SimpleDateFormat("pattern"); } ``` -**This rule has the following properties:** +## SimplifyBooleanExpressions +**Since:** 1.05 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium (3) -## ClassWithOnlyPrivateConstructorsShouldBeFinal -**Since:** 4.1 +Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. -**Priority:** High (1) +**Example(s):** +``` +public class Bar { + // can be simplified to + // bar = isFoo(); + private boolean bar = (isFoo() == true); -A class with only private constructors should be final, unless the private constructor -is invoked by a inner class. + public isFoo() { return false;} +} +``` + +## SimplifyBooleanReturns +**Since:** 0.9 + +**Priority:** Medium (3) + +Avoid unnecessary if-then-else statements when returning a boolean. The result of +the conditional test can be returned instead. **Example(s):** ``` -public class Foo { //Should be final - private Foo() { } +public boolean isBarEqualTo(int x) { + + if (bar == x) { // this bit of code... + return true; + } else { + return false; + } } -``` -**This rule has the following properties:** +public boolean isBarEqualTo(int x) { -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| + return bar == x; // can be replaced with this +} +``` -## EmptyMethodInAbstractClassShouldBeAbstract -**Since:** 4.1 +## SimplifyConditional +**Since:** 3.1 -**Priority:** High (1) +**Priority:** Medium (3) -Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate -usage by developers who should be implementing their own versions in the concrete subclasses. +No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. **Example(s):** ``` -public abstract class ShouldBeAbstract { - public Object couldBeAbstract() { - // Should be abstract method ? - return null; +class Foo { + void bar(Object x) { + if (x != null && x instanceof Bar) { + // just drop the "x != null" check } + } +} +``` - public void couldBeAbstract() { - } +## SingleMethodSingleton +**Since:** 5.4 + +**Priority:** Medium High (2) + +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, + for each call and new objects will be created for every invocation. + +**Example(s):** +``` +public class Singleton { + + private static Singleton singleton = new Singleton( ); + + private Singleton(){ } + +public static Singleton getInstance( ) { + return singleton; +} +public static Singleton getInstance(Object obj){ + Singleton singleton = (Singleton) obj; + return singleton; //violation +} } ``` -**This rule has the following properties:** +## SingletonClassReturningNewInstance +**Since:** 5.4 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) + +Some classes contain overloaded getInstance. The problem with overloaded getInstance methods +is that the instance created using the overloaded method is not cached and so, + for each call and new objects will be created for every invocation. + +**Example(s):** +``` +class Singleton { + private static Singleton instance = null; + public static Singleton getInstance() { + synchronized(Singleton.class){ + return new Singleton(); + } + } +} +``` ## SingularField **Since:** 3.1 @@ -1387,34 +1014,32 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |disallowNotAssignment|false|Disallow violations where the first usage is not an assignment| |checkInnerClasses|false|Check inner classes| -## ReturnEmptyArrayRatherThanNull -**Since:** 4.2 +## SwitchDensity +**Since:** 1.02 -**Priority:** High (1) +**Priority:** Medium (3) -For any method that returns an array, it is a better to return an empty array rather than a -null reference. This removes the need for null checking all results and avoids inadvertent -NullPointerExceptions. +A high ratio of statements to labels in a switch statement implies that the switch statement +is overloaded. Consider moving the statements into new methods or creating subclasses based +on the switch variable. **Example(s):** ``` -public class Example { - // Not a good idea... - public int[] badBehavior() { - // ... - return null; - } - - // Good behavior - public String[] bonnePratique() { - //... - return new String[0]; +public class Foo { + public void bar(int x) { + switch (x) { + case 1: { + // lots of statements + break; + } case 2: { + // lots of statements + break; + } } + } } ``` @@ -1422,37 +1047,29 @@ public class Example { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| -## AbstractClassWithoutAnyMethod -**Since:** 4.2 +## SwitchStmtsShouldHaveDefault +**Since:** 1.0 -**Priority:** High (1) +**Priority:** Medium (3) -If an abstract class does not provides any methods, it may be acting as a simple data container -that is not meant to be instantiated. In this case, it is probably better to use a private or -protected constructor in order to prevent instantiation than make the class misleadingly abstract. +All switch statements should include a default option to catch any unspecified values. **Example(s):** ``` -public class abstract Example { - String field; - int otherField; +public void bar() { + int x = 2; + switch (x) { + case 1: int j = 6; + case 2: int j = 8; + // missing default: here + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## TooFewBranchesForASwitchStatement **Since:** 4.2 @@ -1482,32 +1099,22 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |minimumNumberCaseForASwitch|3|Minimum number of branches for a switch| -## LogicInversion -**Since:** 5.0 +## UncommentedEmptyConstructor +**Since:** 3.4 **Priority:** Medium (3) -Use opposite operator instead of negating the whole expression with a logic complement operator. +Uncommented Empty Constructor finds instances where a constructor does not +contain statements, but there is no comment. By explicitly commenting empty +constructors it is easier to distinguish between intentional (commented) +and unintentional empty constructors. **Example(s):** ``` -public boolean bar(int a, int b) { - - if (!(a == b)) { // use != - return false; - } - - if (!(a < b)) { // use >= - return false; - } - - return true; +public Foo() { + // This constructor is intentionally empty. Nothing special is needed here. } ``` @@ -1515,29 +1122,37 @@ public boolean bar(int a, int b) { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not| -## UseVarargs -**Since:** 5.0 +## UncommentedEmptyMethodBody +**Since:** 3.4 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic -sugar provides flexibility for users of these methods and constructors, allowing them to avoid -having to deal with the creation of an array. +Uncommented Empty Method Body finds instances where a method body does not contain +statements, but there is no comment. By explicitly commenting empty method bodies +it is easier to distinguish between intentional (commented) and unintentional +empty methods. **Example(s):** ``` -public class Foo { - public void foo(String s, Object[] args) { - // Do something here... - } +public void doSomething() { +} +``` - public void bar(String s, Object... args) { - // Ahh, varargs tastes much better... +## UnnecessaryLocalBeforeReturn +**Since:** 3.3 + +**Priority:** Medium (3) + +Avoid the creation of unnecessary local variables + +**Example(s):** +``` +public class Foo { + public int foo() { + int x = doSomething(); + return x; // instead, just 'return doSomething();' } } ``` @@ -1546,163 +1161,138 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|statementOrderMatters|true|If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.| -## FieldDeclarationsShouldBeAtStartOfClass -**Since:** 5.0 +## UnsynchronizedStaticDateFormatter +**Since:** 3.6 **Priority:** Medium (3) -Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. +SimpleDateFormat instances are not synchronized. Sun recommends using separate format instances +for each thread. If multiple threads must access a static formatter, the formatter must be +synchronized either on method or block level. **Example(s):** ``` -public class HelloWorldBean { - - // Field declared before methods / inner classes - OK - private String _thing; - - public String getMessage() { - return "Hello World!"; - } - - // Field declared after methods / inner classes - avoid this - private String _fieldInWrongLocation; +public class Foo { + private static final SimpleDateFormat sdf = new SimpleDateFormat(); + void bar() { + sdf.format(); // poor, no thread-safety + } + synchronized void foo() { + sdf.format(); // preferred + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.| -|ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations| -|ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.| - -## GodClass -**Since:** 5.0 +## UseCollectionIsEmpty +**Since:** 3.9 **Priority:** Medium (3) -The God Class rule detects the God Class design flaw using metrics. God classes do too many things, -are very big and overly complex. They should be split apart to be more object-oriented. -The rule uses the detection strategy described in "Object-Oriented Metrics in Practice". -The violations are reported against the entire class. See also the references: -Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: -Using Software Metrics to Characterize, Evaluate, and Improve the Design -of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. +The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. +Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. -**This rule has the following properties:** +**Example(s):** +``` +public class Foo { + void good() { + List foo = getList(); + if (foo.isEmpty()) { + // blah + } + } -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + void bad() { + List foo = getList(); + if (foo.size() == 0) { + // blah + } + } +} +``` -## AvoidProtectedMethodInFinalClassNotExtending -**Since:** 5.1 +## UseLocaleWithCaseConversions +**Since:** 2.0 **Priority:** Medium (3) -Do not use protected methods in most final classes since they cannot be subclassed. This should -only be allowed in final classes that extend other classes with protected methods (whose -visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead. +When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that +have unusual conventions, i.e. Turkish. **Example(s):** ``` -public final class Foo { - private int bar() {} - protected int baz() {} // Foo cannot be subclassed, and doesn't extend anything, so is baz() really private or package visible? +class Foo { + // BAD + if (x.toLowerCase().equals("list")) { } + /* + This will not match "LIST" when in Turkish locale + The above could be + if (x.toLowerCase(Locale.US).equals("list")) { } + or simply + if (x.equalsIgnoreCase("list")) { } + */ + // GOOD + String z = a.toLowerCase(Locale.EN); } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ConstantsInInterface -**Since:** 5.5 +## UseNotifyAllInsteadOfNotify +**Since:** 3.0 **Priority:** Medium (3) -Avoid constants in interfaces. Interfaces should define types, constants are implementation details -better placed in classes or enums. See Effective Java, item 19. +Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only +one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. **Example(s):** ``` -public interface ConstantInterface { - public static final int CONST1 = 1; // violation, no fields allowed in interface! - static final int CONST2 = 1; // violation, no fields allowed in interface! - final int CONST3 = 1; // violation, no fields allowed in interface! - int CONST4 = 1; // violation, no fields allowed in interface! -} +void bar() { + x.notify(); + // If many threads are monitoring x, only one (and you won't know which) will be notified. + // use instead: + x.notifyAll(); + } +``` -// with ignoreIfHasMethods = false -public interface AnotherConstantInterface { - public static final int CONST1 = 1; // violation, no fields allowed in interface! +## UseUtilityClass +**Since:** 0.3 - int anyMethod(); -} +**Priority:** Medium (3) -// with ignoreIfHasMethods = true -public interface YetAnotherConstantInterface { - public static final int CONST1 = 1; // no violation +For classes that only have static methods, consider making them utility classes. +Note that this doesn't apply to abstract classes, since their subclasses may +well include non-static methods. Also, if you want this class to be a utility class, +remember to add a private constructor to prevent instantiation. +(Note, that this use was known before PMD 5.1.0 as UseSingleton). - int anyMethod(); +**Example(s):** +``` +public class MaybeAUtility { + public static void foo() {} + public static void bar() {} } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods| - -## AccessorMethodGeneration -**Since:** 5.5.4 +## UseVarargs +**Since:** 5.0 -**Priority:** Medium (3) +**Priority:** Medium Low (4) -When accessing a private field / method from another class, the Java compiler will generate a accessor methods -with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can -be avoided by changing the visibility of the field / method from private to package-private. +Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic +sugar provides flexibility for users of these methods and constructors, allowing them to avoid +having to deal with the creation of an array. **Example(s):** ``` -public class OuterClass { - private int counter; - /* package */ int id; - - public class InnerClass { - InnerClass() { - OuterClass.this.counter++; // wrong accessor method will be generated - } +public class Foo { + public void foo(String s, Object[] args) { + // Do something here... + } - public int getOuterClassId() { - return OuterClass.this.id; // id is package-private, no accessor method needed - } - } + public void bar(String s, Object... args) { + // Ahh, varargs tastes much better... + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/java/empty.md b/docs/pages/pmd/rules/java/empty.md index ad906487c..55767f44d 100644 --- a/docs/pages/pmd/rules/java/empty.md +++ b/docs/pages/pmd/rules/java/empty.md @@ -30,13 +30,29 @@ public void doSomething() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |allowCommentedBlocks|false|Empty blocks containing comments will be skipped| |allowExceptionNameRegex|^$|Empty blocks catching exceptions with names matching this regular expression will be skipped| +## EmptyFinallyBlock +**Since:** 0.4 + +**Priority:** Medium (3) + +Empty finally blocks serve no purpose and should be removed. + +**Example(s):** +``` +public class Foo { + public void bar() { + try { + int x=2; + } finally { + // empty! + } + } +} +``` + ## EmptyIfStmt **Since:** 0.1 @@ -55,99 +71,80 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## EmptyWhileStmt -**Since:** 0.2 +## EmptyInitializer +**Since:** 5.0 **Priority:** Medium (3) -Empty While Statement finds all instances where a while statement does nothing. -If it is a timing loop, then you should use Thread.sleep() for it; if it is -a while loop that does a lot in the exit expression, rewrite it to make it clearer. +Empty initializers serve no purpose and should be removed. **Example(s):** ``` -void bar(int a, int b) { - while (a == b) { - // empty! - } -} -``` +public class Foo { -**This rule has the following properties:** + static {} // Why ? -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| + {} // Again, why ? -## EmptyTryBlock -**Since:** 0.4 +} +``` + +## EmptyStatementBlock +**Since:** 5.0 **Priority:** Medium (3) -Avoid empty try blocks - what's the point? +Empty block statements serve no purpose and should be removed. **Example(s):** ``` public class Foo { - public void bar() { - try { - } catch (Exception e) { - e.printStackTrace(); - } - } + + private int _bar; + + public void setBar(int bar) { + { _bar = bar; } // Why not? + {} // But remove this. + } + } ``` -**This rule has the following properties:** +## EmptyStatementNotInLoop +**Since:** 1.5 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## EmptyFinallyBlock -**Since:** 0.4 +An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' +or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose +and should be removed. + +**Example(s):** +``` +public void doit() { + // this is probably not what you meant to do + ; + // the extra semicolon here this is not necessary + System.out.println("look at the extra semicolon");; +} +``` + +## EmptyStaticInitializer +**Since:** 1.5 **Priority:** Medium (3) -Empty finally blocks serve no purpose and should be removed. +An empty static initializer serve no purpose and should be removed. **Example(s):** ``` public class Foo { - public void bar() { - try { - int x=2; - } finally { - // empty! - } - } + static { + // empty + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## EmptySwitchStatements **Since:** 1.0 @@ -166,15 +163,6 @@ public void bar() { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## EmptySynchronizedBlock **Since:** 1.3 @@ -193,122 +181,40 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## EmptyStatementNotInLoop -**Since:** 1.5 - -**Priority:** Medium (3) - -An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' -or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose -and should be removed. - -**Example(s):** -``` -public void doit() { - // this is probably not what you meant to do - ; - // the extra semicolon here this is not necessary - System.out.println("look at the extra semicolon");; -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## EmptyInitializer -**Since:** 5.0 - -**Priority:** Medium (3) - -Empty initializers serve no purpose and should be removed. - -**Example(s):** -``` -public class Foo { - - static {} // Why ? - - {} // Again, why ? - -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## EmptyStatementBlock -**Since:** 5.0 +## EmptyTryBlock +**Since:** 0.4 **Priority:** Medium (3) -Empty block statements serve no purpose and should be removed. +Avoid empty try blocks - what's the point? **Example(s):** ``` public class Foo { - - private int _bar; - - public void setBar(int bar) { - { _bar = bar; } // Why not? - {} // But remove this. - } - + public void bar() { + try { + } catch (Exception e) { + e.printStackTrace(); + } + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## EmptyStaticInitializer -**Since:** 1.5 +## EmptyWhileStmt +**Since:** 0.2 **Priority:** Medium (3) -An empty static initializer serve no purpose and should be removed. +Empty While Statement finds all instances where a while statement does nothing. +If it is a timing loop, then you should use Thread.sleep() for it; if it is +a while loop that does a lot in the exit expression, rewrite it to make it clearer. **Example(s):** ``` -public class Foo { - static { - // empty +void bar(int a, int b) { + while (a == b) { + // empty! } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/finalizers.md b/docs/pages/pmd/rules/java/finalizers.md index ae09ccf33..903ece8be 100644 --- a/docs/pages/pmd/rules/java/finalizers.md +++ b/docs/pages/pmd/rules/java/finalizers.md @@ -6,6 +6,22 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/finalizers.xml --- +## AvoidCallingFinalize +**Since:** 3.0 + +**Priority:** Medium (3) + +The method Object.finalize() is called by the garbage collector on an object when garbage collection determines +that there are no more references to the object. It should not be invoked by application logic. + +**Example(s):** +``` +void foo() { + Bar b = new Bar(); + b.finalize(); +} +``` + ## EmptyFinalizer **Since:** 1.5 @@ -20,14 +36,20 @@ public class Foo { } ``` -**This rule has the following properties:** +## FinalizeDoesNotCallSuperFinalize +**Since:** 1.5 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) + +If the finalize() is implemented, its last action should be to call super.finalize. + +**Example(s):** +``` +protected void finalize() { + something(); + // neglected to call super.finalize() +} +``` ## FinalizeOnlyCallsSuperFinalize **Since:** 1.5 @@ -43,15 +65,6 @@ protected void finalize() { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## FinalizeOverloaded **Since:** 1.5 @@ -69,39 +82,6 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## FinalizeDoesNotCallSuperFinalize -**Since:** 1.5 - -**Priority:** Medium (3) - -If the finalize() is implemented, its last action should be to call super.finalize. - -**Example(s):** -``` -protected void finalize() { - something(); - // neglected to call super.finalize() -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## FinalizeShouldBeProtected **Since:** 1.1 @@ -117,35 +97,3 @@ public void finalize() { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidCallingFinalize -**Since:** 3.0 - -**Priority:** Medium (3) - -The method Object.finalize() is called by the garbage collector on an object when garbage collection determines -that there are no more references to the object. It should not be invoked by application logic. - -**Example(s):** -``` -void foo() { - Bar b = new Bar(); - b.finalize(); -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/java/imports.md b/docs/pages/pmd/rules/java/imports.md index 1bcbc5328..7403ab773 100644 --- a/docs/pages/pmd/rules/java/imports.md +++ b/docs/pages/pmd/rules/java/imports.md @@ -6,27 +6,6 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/imports.xml --- -## DuplicateImports -**Since:** 0.5 - -**Priority:** Medium Low (4) - -Duplicate or overlapping import statements should be avoided. - -**Example(s):** -``` -import java.lang.String; -import java.lang.*; -public class Foo {} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## DontImportJavaLang **Since:** 0.5 @@ -47,34 +26,20 @@ import java.lang.*; // this is bad public class Foo {} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnusedImports -**Since:** 1.0 +## DuplicateImports +**Since:** 0.5 **Priority:** Medium Low (4) -Avoid the use of unused import statements to prevent unwanted dependencies. +Duplicate or overlapping import statements should be avoided. **Example(s):** ``` -// this is bad -import java.io.File; +import java.lang.String; +import java.lang.*; public class Foo {} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## ImportFromSamePackage **Since:** 1.02 @@ -92,13 +57,6 @@ package foo; public class Bar{} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## TooManyStaticImports **Since:** 4.1 @@ -122,10 +80,6 @@ import static Yoko; // Too much ! |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |maximumStaticImports|4|All static imports can be disallowed by setting this to 0| ## UnnecessaryFullyQualifiedName @@ -146,10 +100,17 @@ public class Foo { } ``` -**This rule has the following properties:** +## UnusedImports +**Since:** 1.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium Low (4) + +Avoid the use of unused import statements to prevent unwanted dependencies. + +**Example(s):** +``` +// this is bad +import java.io.File; +public class Foo {} +``` diff --git a/docs/pages/pmd/rules/java/j2ee.md b/docs/pages/pmd/rules/java/j2ee.md index 257f2d3fd..5b1714cec 100644 --- a/docs/pages/pmd/rules/java/j2ee.md +++ b/docs/pages/pmd/rules/java/j2ee.md @@ -6,76 +6,60 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/j2ee.xml --- -## UseProperClassLoader -**Since:** 3.7 +## DoNotCallSystemExit +**Since:** 4.1 **Priority:** Medium (3) -In J2EE, the getClassLoader() method might not work as expected. Use -Thread.currentThread().getContextClassLoader() instead. +Web applications should not call System.exit(), since only the web container or the +application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). **Example(s):** ``` -public class Foo { - ClassLoader cl = Bar.class.getClassLoader(); +public void bar() { + System.exit(0); // never call this when running in an application server! +} +public void foo() { + Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this. } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## MDBAndSessionBeanNamingConvention -**Since:** 4.0 +## DoNotUseThreads +**Since:** 4.1 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. +The J2EE specification explicitly forbids the use of threads. **Example(s):** ``` -public class SomeBean implements SessionBean{} // proper name +// This is not allowed +public class UsingThread extends Thread { -public class MissingTheProperSuffix implements SessionBean {} // non-standard name + } + // Neither this, +public class OtherThread implements Runnable { + // Nor this ... + public void methode() { + Runnable thread = new Thread(); thread.run(); + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## RemoteSessionInterfaceNamingConvention +## LocalHomeNamingConvention **Since:** 4.0 **Priority:** Medium Low (4) -A Remote Home interface type of a Session EJB should be suffixed by 'Home'. +The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. **Example(s):** ``` -public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper name +public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper name -public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standard name + public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-standard name ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## LocalInterfaceSessionNamingConvention **Since:** 4.0 @@ -90,38 +74,20 @@ public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name public interface MissingProperSuffix extends javax.ejb.EJBLocalObject {} // non-standard name ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## LocalHomeNamingConvention +## MDBAndSessionBeanNamingConvention **Since:** 4.0 **Priority:** Medium Low (4) -The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. +The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. **Example(s):** ``` -public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper name +public class SomeBean implements SessionBean{} // proper name - public interface MissingProperSuffix extends javax.ejb.EJBLocalHome {} // non-standard name +public class MissingTheProperSuffix implements SessionBean {} // non-standard name ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## RemoteInterfaceNamingConvention **Since:** 4.0 @@ -141,41 +107,19 @@ Remote Interface of a Session EJB should not have a suffix. public interface BadSuffixBean extends javax.ejb.EJBObject {} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## DoNotCallSystemExit -**Since:** 4.1 +## RemoteSessionInterfaceNamingConvention +**Since:** 4.0 -**Priority:** Medium (3) +**Priority:** Medium Low (4) -Web applications should not call System.exit(), since only the web container or the -application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). +A Remote Home interface type of a Session EJB should be suffixed by 'Home'. **Example(s):** ``` -public void bar() { - System.exit(0); // never call this when running in an application server! -} -public void foo() { - Runtime.getRuntime().exit(0); // never stop the JVM manually, the container will do this. -} -``` - -**This rule has the following properties:** +public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper name -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standard name +``` ## StaticEJBFieldShouldBeFinal **Since:** 4.1 @@ -196,43 +140,18 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## DoNotUseThreads -**Since:** 4.1 +## UseProperClassLoader +**Since:** 3.7 **Priority:** Medium (3) -The J2EE specification explicitly forbids the use of threads. +In J2EE, the getClassLoader() method might not work as expected. Use +Thread.currentThread().getContextClassLoader() instead. **Example(s):** ``` -// This is not allowed -public class UsingThread extends Thread { - - } - // Neither this, -public class OtherThread implements Runnable { - // Nor this ... - public void methode() { - Runnable thread = new Thread(); thread.run(); - } +public class Foo { + ClassLoader cl = Bar.class.getClassLoader(); } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/javabeans.md b/docs/pages/pmd/rules/java/javabeans.md index 3bb0a891f..5a2edfc82 100644 --- a/docs/pages/pmd/rules/java/javabeans.md +++ b/docs/pages/pmd/rules/java/javabeans.md @@ -36,8 +36,6 @@ private int getMoreFoo(){ |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |prefix||A variable prefix to skip, i.e., m_| ## MissingSerialVersionUID @@ -56,12 +54,3 @@ public class Foo implements java.io.Serializable { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/junit.md b/docs/pages/pmd/rules/java/junit.md index dec705c3f..7e0f3c143 100644 --- a/docs/pages/pmd/rules/java/junit.md +++ b/docs/pages/pmd/rules/java/junit.md @@ -6,32 +6,26 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/junit.xml --- -## JUnitStaticSuite -**Since:** 1.0 +## JUnitAssertionsShouldIncludeMessage +**Since:** 1.04 **Priority:** Medium (3) -The suite() method in a JUnit test needs to be both public and static. +JUnit assertions should include an informative message - i.e., use the three-argument version of +assertEquals(), not the two-argument version. **Example(s):** ``` -import junit.framework.*; - public class Foo extends TestCase { - public void suite() {} // oops, should be static - private static void suite() {} // oops, should be public + public void testSomething() { + assertEquals("foo", "bar"); + // Use the form: + // assertEquals("Foo does not equals bar", "foo", "bar"); + // instead + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## JUnitSpelling **Since:** 1.0 @@ -49,32 +43,47 @@ public class Foo extends TestCase { } ``` -**This rule has the following properties:** +## JUnitStaticSuite +**Since:** 1.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## JUnitAssertionsShouldIncludeMessage -**Since:** 1.04 +The suite() method in a JUnit test needs to be both public and static. + +**Example(s):** +``` +import junit.framework.*; + +public class Foo extends TestCase { + public void suite() {} // oops, should be static + private static void suite() {} // oops, should be public +} +``` + +## JUnitTestContainsTooManyAsserts +**Since:** 5.0 **Priority:** Medium (3) -JUnit assertions should include an informative message - i.e., use the three-argument version of -assertEquals(), not the two-argument version. +JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which +it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios. +Customize the maximum number of assertions used by this Rule to suit your needs. **Example(s):** ``` -public class Foo extends TestCase { - public void testSomething() { - assertEquals("foo", "bar"); - // Use the form: - // assertEquals("Foo does not equals bar", "foo", "bar"); - // instead - } +public class MyTestCase extends TestCase { + // Ok + public void testMyCaseWithOneAssert() { + boolean myVar = false; + assertFalse("should be false", myVar); + } + + // Bad, too many asserts (assuming max=1) + public void testMyCaseWithMoreAsserts() { + boolean myVar = false; + assertFalse("myVar should be false", myVar); + assertEquals("should equals false", false, myVar); + } } ``` @@ -82,8 +91,7 @@ public class Foo extends TestCase { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|maximumAsserts|1|Maximum number of Asserts in a test method| ## JUnitTestsShouldIncludeAssert **Since:** 2.0 @@ -105,12 +113,30 @@ public class Foo extends TestCase { } ``` -**This rule has the following properties:** +## SimplifyBooleanAssertion +**Since:** 3.6 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium (3) + +Avoid negation in an assertTrue or assertFalse test. + +For example, rephrase: + + assertTrue(!expr); + +as: + + assertFalse(expr); + +**Example(s):** +``` +public class SimpleTest extends TestCase { + public void testX() { + assertTrue("not empty", !r.isEmpty()); // replace with assertFalse("not empty", r.isEmpty()) + assertFalse(!r.isEmpty()); // replace with assertTrue(r.isEmpty()) + } +} +``` ## TestClassWithoutTestCases **Since:** 3.0 @@ -132,13 +158,6 @@ public class CarTest { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## UnnecessaryBooleanAssertion **Since:** 3.0 @@ -158,15 +177,6 @@ public class SimpleTest extends TestCase { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## UseAssertEqualsInsteadOfAssertTrue **Since:** 3.1 @@ -185,43 +195,6 @@ public class FooTest extends TestCase { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UseAssertSameInsteadOfAssertTrue -**Since:** 3.1 - -**Priority:** Medium (3) - -This rule detects JUnit assertions in object references equality. These assertions should be made -by more specific methods, like assertSame, assertNotSame. - -**Example(s):** -``` -public class FooTest extends TestCase { - void testCode() { - Object a, b; - assertTrue(a == b); // bad usage - assertSame(a, b); // good usage - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## UseAssertNullInsteadOfAssertTrue **Since:** 3.5 @@ -243,86 +216,25 @@ public class FooTest extends TestCase { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## SimplifyBooleanAssertion -**Since:** 3.6 - -**Priority:** Medium (3) - -Avoid negation in an assertTrue or assertFalse test. - -For example, rephrase: - - assertTrue(!expr); - -as: - - assertFalse(expr); - -**Example(s):** -``` -public class SimpleTest extends TestCase { - public void testX() { - assertTrue("not empty", !r.isEmpty()); // replace with assertFalse("not empty", r.isEmpty()) - assertFalse(!r.isEmpty()); // replace with assertTrue(r.isEmpty()) - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## JUnitTestContainsTooManyAsserts -**Since:** 5.0 +## UseAssertSameInsteadOfAssertTrue +**Since:** 3.1 **Priority:** Medium (3) -JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, for which -it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios. -Customize the maximum number of assertions used by this Rule to suit your needs. +This rule detects JUnit assertions in object references equality. These assertions should be made +by more specific methods, like assertSame, assertNotSame. **Example(s):** ``` -public class MyTestCase extends TestCase { - // Ok - public void testMyCaseWithOneAssert() { - boolean myVar = false; - assertFalse("should be false", myVar); - } - - // Bad, too many asserts (assuming max=1) - public void testMyCaseWithMoreAsserts() { - boolean myVar = false; - assertFalse("myVar should be false", myVar); - assertEquals("should equals false", false, myVar); - } +public class FooTest extends TestCase { + void testCode() { + Object a, b; + assertTrue(a == b); // bad usage + assertSame(a, b); // good usage + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|maximumAsserts|1|Maximum number of Asserts in a test method| - ## UseAssertTrueInsteadOfAssertEquals **Since:** 5.0 @@ -349,12 +261,3 @@ public class MyTestCase extends TestCase { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/logging-jakarta-commons.md b/docs/pages/pmd/rules/java/logging-jakarta-commons.md index 2250bb325..f826983d6 100644 --- a/docs/pages/pmd/rules/java/logging-jakarta-commons.md +++ b/docs/pages/pmd/rules/java/logging-jakarta-commons.md @@ -6,66 +6,6 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-jakarta-commons.xml --- -## UseCorrectExceptionLogging -**Since:** 3.2 - -**Priority:** Medium (3) - -To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. - -**Example(s):** -``` -public class Main { - private static final Log _LOG = LogFactory.getLog( Main.class ); - void bar() { - try { - } catch( Exception e ) { - _LOG.error( e ); //Wrong! - } catch( OtherException oe ) { - _LOG.error( oe.getMessage(), oe ); //Correct - } - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ProperLogger -**Since:** 3.3 - -**Priority:** Medium (3) - -A logger should normally be defined private static final and be associated with the correct class. -Private final Log log; is also allowed for rare cases where loggers need to be passed around, -with the restriction that the logger needs to be passed into the constructor. - -**Example(s):** -``` -public class Foo { - - private static final Log LOG = LogFactory.getLog(Foo.class); // proper way - - protected Log LOG = LogFactory.getLog(Testclass.class); // wrong approach -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|staticLoggerName|LOG|Name of the static Logger variable| - ## GuardDebugLogging **Since:** 4.3 @@ -103,8 +43,6 @@ public class Test { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| @@ -127,8 +65,53 @@ otherwise skip the associate String creation and manipulation. |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| +## ProperLogger +**Since:** 3.3 + +**Priority:** Medium (3) + +A logger should normally be defined private static final and be associated with the correct class. +Private final Log log; is also allowed for rare cases where loggers need to be passed around, +with the restriction that the logger needs to be passed into the constructor. + +**Example(s):** +``` +public class Foo { + + private static final Log LOG = LogFactory.getLog(Foo.class); // proper way + + protected Log LOG = LogFactory.getLog(Testclass.class); // wrong approach +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|staticLoggerName|LOG|Name of the static Logger variable| + +## UseCorrectExceptionLogging +**Since:** 3.2 + +**Priority:** Medium (3) + +To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. + +**Example(s):** +``` +public class Main { + private static final Log _LOG = LogFactory.getLog( Main.class ); + void bar() { + try { + } catch( Exception e ) { + _LOG.error( e ); //Wrong! + } catch( OtherException oe ) { + _LOG.error( oe.getMessage(), oe ); //Correct + } + } +} +``` + diff --git a/docs/pages/pmd/rules/java/logging-java.md b/docs/pages/pmd/rules/java/logging-java.md index 1f3dc02fe..7095fad41 100644 --- a/docs/pages/pmd/rules/java/logging-java.md +++ b/docs/pages/pmd/rules/java/logging-java.md @@ -6,85 +6,6 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-java.xml --- -## MoreThanOneLogger -**Since:** 2.0 - -**Priority:** Medium High (2) - -Normally only one logger is used in each class. - -**Example(s):** -``` -public class Foo { - Logger log = Logger.getLogger(Foo.class.getName()); - // It is very rare to see two loggers on a class, normally - // log information is multiplexed by levels - Logger log2= Logger.getLogger(Foo.class.getName()); -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## LoggerIsNotStaticFinal -**Since:** 2.0 - -**Priority:** Medium High (2) - -In most cases, the Logger reference can be declared as static and final. - -**Example(s):** -``` -public class Foo{ - Logger log = Logger.getLogger(Foo.class.getName()); // not recommended - - static final Logger log = Logger.getLogger(Foo.class.getName()); // preferred approach -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## SystemPrintln -**Since:** 2.1 - -**Priority:** Medium High (2) - -References to System.(out|err).print are usually intended for debugging purposes and can remain in -the codebase even in production code. By using a logger one can enable/disable this behaviour at -will (and by priority) and avoid clogging the Standard out log. - -**Example(s):** -``` -class Foo{ - Logger log = Logger.getLogger(Foo.class.getName()); - public void testA () { - System.out.println("Entering test"); - // Better use this - log.fine("Entering test"); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## AvoidPrintStackTrace **Since:** 3.2 @@ -105,15 +26,6 @@ class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## GuardLogStatementJavaUtil **Since:** 5.1.0 @@ -133,8 +45,6 @@ otherwise skip the associate String creation and manipulation. |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |guardsMethods|[]|method use to guard the log statement| |logLevels|[]|LogLevels to guard| @@ -152,10 +62,57 @@ LOGGER.error("too many args {}", "arg1", "arg2"); LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The exception is shown separately, so is correct. ``` -**This rule has the following properties:** +## LoggerIsNotStaticFinal +**Since:** 2.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium High (2) + +In most cases, the Logger reference can be declared as static and final. + +**Example(s):** +``` +public class Foo{ + Logger log = Logger.getLogger(Foo.class.getName()); // not recommended + + static final Logger log = Logger.getLogger(Foo.class.getName()); // preferred approach +} +``` + +## MoreThanOneLogger +**Since:** 2.0 + +**Priority:** Medium High (2) + +Normally only one logger is used in each class. + +**Example(s):** +``` +public class Foo { + Logger log = Logger.getLogger(Foo.class.getName()); + // It is very rare to see two loggers on a class, normally + // log information is multiplexed by levels + Logger log2= Logger.getLogger(Foo.class.getName()); +} +``` + +## SystemPrintln +**Since:** 2.1 + +**Priority:** Medium High (2) + +References to System.(out|err).print are usually intended for debugging purposes and can remain in +the codebase even in production code. By using a logger one can enable/disable this behaviour at +will (and by priority) and avoid clogging the Standard out log. + +**Example(s):** +``` +class Foo{ + Logger log = Logger.getLogger(Foo.class.getName()); + public void testA () { + System.out.println("Entering test"); + // Better use this + log.fine("Entering test"); + } +} +``` diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md index 034988971..90a2a37d0 100644 --- a/docs/pages/pmd/rules/java/migrating.md +++ b/docs/pages/pmd/rules/java/migrating.md @@ -6,85 +6,22 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml --- -## ReplaceVectorWithList -**Since:** 3.4 - -**Priority:** Medium (3) - -Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. - -**Example(s):** -``` -public class Foo { - void bar() { - Vector v = new Vector(); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ReplaceHashtableWithMap +## AvoidAssertAsIdentifier **Since:** 3.4 -**Priority:** Medium (3) +**Priority:** Medium High (2) -Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. +Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. **Example(s):** ``` -public class Foo { - void bar() { - Hashtable h = new Hashtable(); +public class A { + public class foo { + String assert = "foo"; } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ReplaceEnumerationWithIterator -**Since:** 3.4 - -**Priority:** Medium (3) - -Consider replacing Enumeration usages with the newer java.util.Iterator - -**Example(s):** -``` -public class Foo implements Enumeration { - private int x = 42; - public boolean hasMoreElements() { - return true; - } - public Object nextElement() { - return String.valueOf(i++); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## AvoidEnumAsIdentifier **Since:** 3.4 @@ -101,40 +38,21 @@ public class A { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidAssertAsIdentifier -**Since:** 3.4 +## ByteInstantiation +**Since:** 4.0 **Priority:** Medium High (2) -Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. +Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. **Example(s):** ``` -public class A { - public class foo { - String assert = "foo"; - } +public class Foo { + private Byte i = new Byte(0); // change to Byte i = Byte.valueOf(0); } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## IntegerInstantiation **Since:** 3.5 @@ -150,87 +68,51 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ByteInstantiation +## JUnit4SuitesShouldUseSuiteAnnotation **Since:** 4.0 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). -It makes use of an internal cache that recycles earlier instances making it more memory efficient. +In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated +through the @RunWith(Suite.class) annotation. **Example(s):** ``` -public class Foo { - private Byte i = new Byte(0); // change to Byte i = Byte.valueOf(0); -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## ShortInstantiation -**Since:** 4.0 - -**Priority:** Medium High (2) +public class BadExample extends TestCase{ -Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). -It makes use of an internal cache that recycles earlier instances making it more memory efficient. + public static Test suite(){ + return new Suite(); + } +} -**Example(s):** -``` -public class Foo { - private Short i = new Short(0); // change to Short i = Short.valueOf(0); +@RunWith(Suite.class) +@SuiteClasses( { TestOne.class, TestTwo.class }) +public class GoodTest { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## LongInstantiation +## JUnit4TestShouldUseAfterAnnotation **Since:** 4.0 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). -It makes use of an internal cache that recycles earlier instances making it more memory efficient. +In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. +JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test **Example(s):** ``` -public class Foo { - private Long i = new Long(0); // change to Long i = Long.valueOf(0); +public class MyTest { + public void tearDown() { + bad(); + } +} +public class MyTest2 { + @After public void tearDown() { + good(); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## JUnit4TestShouldUseBeforeAnnotation **Since:** 4.0 @@ -253,139 +135,133 @@ public class MyTest2 { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## JUnit4TestShouldUseAfterAnnotation +## JUnit4TestShouldUseTestAnnotation **Since:** 4.0 **Priority:** Medium (3) -In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. -JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test +In JUnit 3, the framework executed all methods which started with the word test as a unit test. +In JUnit 4, only methods annotated with the @Test annotation are executed. **Example(s):** ``` public class MyTest { - public void tearDown() { - bad(); + public void testBad() { + doSomething(); } -} -public class MyTest2 { - @After public void tearDown() { - good(); + + @Test + public void testGood() { + doSomething(); } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## JUnit4TestShouldUseTestAnnotation +## JUnitUseExpected **Since:** 4.0 **Priority:** Medium (3) -In JUnit 3, the framework executed all methods which started with the word test as a unit test. -In JUnit 4, only methods annotated with the @Test annotation are executed. +In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. **Example(s):** ``` public class MyTest { + @Test public void testBad() { - doSomething(); + try { + doSomething(); + fail("should have thrown an exception"); + } catch (Exception e) { + } } - @Test + @Test(expected=Exception.class) public void testGood() { doSomething(); } } ``` -**This rule has the following properties:** +## LongInstantiation +**Since:** 4.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) -## JUnit4SuitesShouldUseSuiteAnnotation -**Since:** 4.0 +Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Long i = new Long(0); // change to Long i = Long.valueOf(0); +} +``` + +## ReplaceEnumerationWithIterator +**Since:** 3.4 **Priority:** Medium (3) -In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated -through the @RunWith(Suite.class) annotation. +Consider replacing Enumeration usages with the newer java.util.Iterator **Example(s):** ``` -public class BadExample extends TestCase{ - - public static Test suite(){ - return new Suite(); +public class Foo implements Enumeration { + private int x = 42; + public boolean hasMoreElements() { + return true; + } + public Object nextElement() { + return String.valueOf(i++); } -} - -@RunWith(Suite.class) -@SuiteClasses( { TestOne.class, TestTwo.class }) -public class GoodTest { } ``` -**This rule has the following properties:** +## ReplaceHashtableWithMap +**Since:** 3.4 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## JUnitUseExpected -**Since:** 4.0 +Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. + +**Example(s):** +``` +public class Foo { + void bar() { + Hashtable h = new Hashtable(); + } +} +``` + +## ReplaceVectorWithList +**Since:** 3.4 **Priority:** Medium (3) -In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. +Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. **Example(s):** ``` -public class MyTest { - @Test - public void testBad() { - try { - doSomething(); - fail("should have thrown an exception"); - } catch (Exception e) { - } - } - - @Test(expected=Exception.class) - public void testGood() { - doSomething(); - } +public class Foo { + void bar() { + Vector v = new Vector(); + } } ``` -**This rule has the following properties:** +## ShortInstantiation +**Since:** 4.0 + +**Priority:** Medium High (2) -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). +It makes use of an internal cache that recycles earlier instances making it more memory efficient. + +**Example(s):** +``` +public class Foo { + private Short i = new Short(0); // change to Short i = Short.valueOf(0); +} +``` diff --git a/docs/pages/pmd/rules/java/naming.md b/docs/pages/pmd/rules/java/naming.md index c3d171472..9164a66e9 100644 --- a/docs/pages/pmd/rules/java/naming.md +++ b/docs/pages/pmd/rules/java/naming.md @@ -6,26 +6,16 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/naming.xml --- -## ShortVariable -**Since:** 0.3 +## AbstractNaming +**Since:** 1.4 **Priority:** Medium (3) -Fields, local variables, or parameter names that are very short are not helpful to the reader. +Abstract classes should be named 'AbstractXXX'. **Example(s):** ``` -public class Something { - private int q = 15; // field - too short - public static void main( String as[] ) { // formal arg - too short - int r = 20 + q; // local var - too short - for (int i = 0; i < 10; i++) { // not a violation (inside 'for' loop) - r += q; - } - for (Integer i : numbers) { // not a violation (inside 'for-each' loop) - r += q; - } - } +public abstract class Foo { // should be AbstractFoo } ``` @@ -33,126 +23,76 @@ public class Something { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|minimum|3|Number of characters that are required as a minimum for a variable name.| +|strict|true|Also flag classes, that are named Abstract, but are not abstract.| -## LongVariable -**Since:** 0.3 +## AvoidDollarSigns +**Since:** 1.5 **Priority:** Medium (3) -Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. +Avoid using dollar signs in variable/method/class/interface names. **Example(s):** ``` -public class Something { - int reallyLongIntName = -3; // VIOLATION - Field - public static void main( String argumentsList[] ) { // VIOLATION - Formal - int otherReallyLongName = -5; // VIOLATION - Local - for (int interestingIntIndex = 0; // VIOLATION - For - interestingIntIndex < 10; - interestingIntIndex ++ ) { - } +public class Fo$o { // not a recommended name } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|minimum|17|The variable length reporting threshold| - -## ShortMethodName -**Since:** 0.3 +## AvoidFieldNameMatchingMethodName +**Since:** 3.0 **Priority:** Medium (3) -Method names that are very short are not helpful to the reader. +It can be confusing to have a field name with the same name as a method. While this is permitted, +having information (field) and actions (method) is not clear naming. Developers versed in +Smalltalk often prefer this approach as the methods denote accessor methods. **Example(s):** ``` -public class ShortMethod { - public void a( int i ) { // Violation +public class Foo { + Object bar; + // bar is data or an action or both? + void bar() { } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|minimum|3|Number of characters that are required as a minimum for a method name.| - -## VariableNamingConventions -**Since:** 1.2 +## AvoidFieldNameMatchingTypeName +**Since:** 3.0 -**Priority:** High (1) +**Priority:** Medium (3) -A variable naming conventions rule - customize this to your liking. Currently, it -checks for final variables that should be fully capitalized and non-final variables -that should not include underscores. +It is somewhat confusing to have a field name matching the declaring class name. +This probably means that type and/or field names should be chosen more carefully. **Example(s):** ``` -public class Foo { - public static final int MY_NUM = 0; - public String myTest = ""; - DataModule dmTest = new DataModule(); +public class Foo extends Bar { + int foo; // There is probably a better name that can be used } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|parameterSuffix|[]|Method parameter variable suffixes| -|parameterPrefix|[]|Method parameter variable prefixes| -|localSuffix|[]|Local variable suffixes| -|localPrefix|[]|Local variable prefixes| -|memberSuffix|[]|Member variable suffixes| -|memberPrefix|[]|Member variable prefixes| -|staticSuffix|[]|Static variable suffixes| -|checkParameters|true|Check constructor and method parameter variables| -|checkNativeMethodParameters|true|Check method parameter of native methods| -|staticPrefix|[]|Static variable prefixes| -|checkLocals|true|Check local variables| -|checkMembers|true|Check member variables| - -## MethodNamingConventions -**Since:** 1.2 +## BooleanGetMethodName +**Since:** 4.0 -**Priority:** High (1) +**Priority:** Medium Low (4) -Method names should always begin with a lower case character, and should not contain underscores. +Methods that return boolean results should be named as predicate statements to denote this. +I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get' +prefix for these methods. **Example(s):** ``` -public class Foo { - public void fooStuff() { - } -} +public boolean getFoo(); // bad +public boolean isFoo(); // ok +public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|checkNativeMethods|true|Check native methods| +|checkParameterizedMethods|false|Check parameterized methods| ## ClassNamingConventions **Since:** 1.2 @@ -166,46 +106,49 @@ Class names should always begin with an upper case character. public class Foo {} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AbstractNaming -**Since:** 1.4 +## GenericsNaming +**Since:** 4.2.6 -**Priority:** Medium (3) +**Priority:** Medium Low (4) -Abstract classes should be named 'AbstractXXX'. +Names for references to generic values should be limited to a single uppercase letter. **Example(s):** ``` -public abstract class Foo { // should be AbstractFoo +public interface GenericDao<E extends BaseModel, K extends Serializable> extends BaseDao { + // This is ok... } -``` -**This rule has the following properties:** +public interface GenericDao<E extends BaseModel, K extends Serializable> { + // Also this +} -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|strict|true|Also flag classes, that are named Abstract, but are not abstract.| +public interface GenericDao<e extends BaseModel, K extends Serializable> { + // 'e' should be an 'E' +} -## AvoidDollarSigns -**Since:** 1.5 +public interface GenericDao<EF extends BaseModel, K extends Serializable> { + // 'EF' is not ok. +} +``` + +## LongVariable +**Since:** 0.3 **Priority:** Medium (3) -Avoid using dollar signs in variable/method/class/interface names. +Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. **Example(s):** ``` -public class Fo$o { // not a recommended name +public class Something { + int reallyLongIntName = -3; // VIOLATION - Field + public static void main( String argumentsList[] ) { // VIOLATION - Formal + int otherReallyLongName = -5; // VIOLATION - Local + for (int interestingIntIndex = 0; // VIOLATION - For + interestingIntIndex < 10; + interestingIntIndex ++ ) { + } } ``` @@ -213,23 +156,20 @@ public class Fo$o { // not a recommended name |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|minimum|17|The variable length reporting threshold| -## MethodWithSameNameAsEnclosingClass -**Since:** 1.5 +## MethodNamingConventions +**Since:** 1.2 -**Priority:** Medium (3) +**Priority:** High (1) -Non-constructor methods should not have the same name as the enclosing class. +Method names should always begin with a lower case character, and should not contain underscores. **Example(s):** ``` -public class MyClass { - - public MyClass() {} // this is OK because it is a constructor - - public void MyClass() {} // this is bad because it is a method +public class Foo { + public void fooStuff() { + } } ``` @@ -237,130 +177,81 @@ public class MyClass { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkNativeMethods|true|Check native methods| -## SuspiciousHashcodeMethodName +## MethodWithSameNameAsEnclosingClass **Since:** 1.5 **Priority:** Medium (3) -The method name and return type are suspiciously close to hashCode(), which may denote an intention -to override the hashCode() method. +Non-constructor methods should not have the same name as the enclosing class. **Example(s):** ``` -public class Foo { - public int hashcode() { // oops, this probably was supposed to be 'hashCode' +public class MyClass { + + public MyClass() {} // this is OK because it is a constructor - } + public void MyClass() {} // this is bad because it is a method } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SuspiciousConstantFieldName -**Since:** 2.0 +## MisleadingVariableName +**Since:** 3.4 **Priority:** Medium (3) -Field names using all uppercase characters - Sun's Java naming conventions indicating constants - should -be declared as final. +Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing. **Example(s):** ``` public class Foo { - // this is bad, since someone could accidentally - // do PI = 2.71828; which is actually e - // final double PI = 3.16; is ok - double PI = 3.16; + private int m_foo; // OK + public void bar(String m_baz) { // Bad + int m_boz = 42; // Bad + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## SuspiciousEqualsMethodName -**Since:** 2.0 +## NoPackage +**Since:** 3.3 -**Priority:** Medium High (2) +**Priority:** Medium (3) -The method name and parameter number are suspiciously close to equals(Object), which can denote an -intention to override the equals(Object) method. +Detects when a class or interface does not have a package definition. **Example(s):** ``` -public class Foo { - public int equals(Object o) { - // oops, this probably was supposed to be boolean equals - } - public boolean equals(String s) { - // oops, this probably was supposed to be equals(Object) - } - public boolean equals(Object o1, Object o2) { - // oops, this probably was supposed to be equals(Object) - } +// no package declaration +public class ClassInDefaultPackage { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidFieldNameMatchingTypeName -**Since:** 3.0 +## PackageCase +**Since:** 3.3 **Priority:** Medium (3) -It is somewhat confusing to have a field name matching the declaring class name. -This probably means that type and/or field names should be chosen more carefully. +Detects when a package definition contains uppercase characters. **Example(s):** ``` -public class Foo extends Bar { - int foo; // There is probably a better name that can be used +package com.MyCompany; // should be lowercase name + +public class SomeClass { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AvoidFieldNameMatchingMethodName -**Since:** 3.0 +## ShortClassName +**Since:** 5.0 -**Priority:** Medium (3) +**Priority:** Medium Low (4) -It can be confusing to have a field name with the same name as a method. While this is permitted, -having information (field) and actions (method) is not clear naming. Developers versed in -Smalltalk often prefer this approach as the methods denote accessor methods. +Short Classnames with fewer than e.g. five characters are not recommended. **Example(s):** ``` public class Foo { - Object bar; - // bar is data or an action or both? - void bar() { - } } ``` @@ -368,20 +259,20 @@ public class Foo { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|minimum|5|Number of characters that are required as a minimum for a class name.| -## NoPackage -**Since:** 3.3 +## ShortMethodName +**Since:** 0.3 **Priority:** Medium (3) -Detects when a class or interface does not have a package definition. +Method names that are very short are not helpful to the reader. **Example(s):** ``` -// no package declaration -public class ClassInDefaultPackage { +public class ShortMethod { + public void a( int i ) { // Violation + } } ``` @@ -389,23 +280,28 @@ public class ClassInDefaultPackage { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|minimum|3|Number of characters that are required as a minimum for a method name.| -## PackageCase -**Since:** 3.3 +## ShortVariable +**Since:** 0.3 **Priority:** Medium (3) -Detects when a package definition contains uppercase characters. +Fields, local variables, or parameter names that are very short are not helpful to the reader. **Example(s):** ``` -package com.MyCompany; // should be lowercase name - -public class SomeClass { +public class Something { + private int q = 15; // field - too short + public static void main( String as[] ) { // formal arg - too short + int r = 20 + q; // local var - too short + for (int i = 0; i < 10; i++) { // not a violation (inside 'for' loop) + r += q; + } + for (Integer i : numbers) { // not a violation (inside 'for-each' loop) + r += q; + } + } } ``` @@ -413,109 +309,81 @@ public class SomeClass { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|minimum|3|Number of characters that are required as a minimum for a variable name.| -## MisleadingVariableName -**Since:** 3.4 +## SuspiciousConstantFieldName +**Since:** 2.0 **Priority:** Medium (3) -Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing. +Field names using all uppercase characters - Sun's Java naming conventions indicating constants - should +be declared as final. **Example(s):** ``` public class Foo { - private int m_foo; // OK - public void bar(String m_baz) { // Bad - int m_boz = 42; // Bad - } + // this is bad, since someone could accidentally + // do PI = 2.71828; which is actually e + // final double PI = 3.16; is ok + double PI = 3.16; } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## BooleanGetMethodName -**Since:** 4.0 +## SuspiciousEqualsMethodName +**Since:** 2.0 -**Priority:** Medium Low (4) +**Priority:** Medium High (2) -Methods that return boolean results should be named as predicate statements to denote this. -I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get' -prefix for these methods. +The method name and parameter number are suspiciously close to equals(Object), which can denote an +intention to override the equals(Object) method. **Example(s):** ``` -public boolean getFoo(); // bad -public boolean isFoo(); // ok -public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true +public class Foo { + public int equals(Object o) { + // oops, this probably was supposed to be boolean equals + } + public boolean equals(String s) { + // oops, this probably was supposed to be equals(Object) + } + public boolean equals(Object o1, Object o2) { + // oops, this probably was supposed to be equals(Object) + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|checkParameterizedMethods|false|Check parameterized methods| - -## ShortClassName -**Since:** 5.0 +## SuspiciousHashcodeMethodName +**Since:** 1.5 -**Priority:** Medium Low (4) +**Priority:** Medium (3) -Short Classnames with fewer than e.g. five characters are not recommended. +The method name and return type are suspiciously close to hashCode(), which may denote an intention +to override the hashCode() method. **Example(s):** ``` public class Foo { + public int hashcode() { // oops, this probably was supposed to be 'hashCode' + + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|minimum|5|Number of characters that are required as a minimum for a class name.| - -## GenericsNaming -**Since:** 4.2.6 +## VariableNamingConventions +**Since:** 1.2 -**Priority:** Medium Low (4) +**Priority:** High (1) -Names for references to generic values should be limited to a single uppercase letter. +A variable naming conventions rule - customize this to your liking. Currently, it +checks for final variables that should be fully capitalized and non-final variables +that should not include underscores. **Example(s):** ``` -public interface GenericDao<E extends BaseModel, K extends Serializable> extends BaseDao { - // This is ok... -} - -public interface GenericDao<E extends BaseModel, K extends Serializable> { - // Also this -} - -public interface GenericDao<e extends BaseModel, K extends Serializable> { - // 'e' should be an 'E' -} - -public interface GenericDao<EF extends BaseModel, K extends Serializable> { - // 'EF' is not ok. +public class Foo { + public static final int MY_NUM = 0; + public String myTest = ""; + DataModule dmTest = new DataModule(); } ``` @@ -523,8 +391,16 @@ public interface GenericDao<EF extends BaseModel, K extends Serializable> { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|parameterSuffix|[]|Method parameter variable suffixes| +|parameterPrefix|[]|Method parameter variable prefixes| +|localSuffix|[]|Local variable suffixes| +|localPrefix|[]|Local variable prefixes| +|memberSuffix|[]|Member variable suffixes| +|memberPrefix|[]|Member variable prefixes| +|staticSuffix|[]|Static variable suffixes| +|checkParameters|true|Check constructor and method parameter variables| +|checkNativeMethodParameters|true|Check method parameter of native methods| +|staticPrefix|[]|Static variable prefixes| +|checkLocals|true|Check local variables| +|checkMembers|true|Check member variables| diff --git a/docs/pages/pmd/rules/java/optimizations.md b/docs/pages/pmd/rules/java/optimizations.md index 9d3a8bf34..b2632fe38 100644 --- a/docs/pages/pmd/rules/java/optimizations.md +++ b/docs/pages/pmd/rules/java/optimizations.md @@ -6,55 +6,47 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/optimizations.xml --- -## LocalVariableCouldBeFinal -**Since:** 2.2 +## AddEmptyString +**Since:** 4.0 **Priority:** Medium (3) -A local variable assigned only once can be declared final. +The conversion of literals to strings by concatenating them with empty strings is inefficient. +It is much better to use one of the type-specific toString() methods instead. **Example(s):** ``` -public class Bar { - public void foo () { - String txtA = "a"; // if txtA will not be assigned again it is better to do this: - final String txtB = "b"; - } -} +String s = "" + 123; // inefficient +String t = Integer.toString(456); // preferred approach ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## MethodArgumentCouldBeFinal -**Since:** 2.2 +## AvoidArrayLoops +**Since:** 3.5 **Priority:** Medium (3) -A method argument that is never re-assigned within the method can be declared final. +Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead. **Example(s):** ``` -public void foo1 (String param) { // do stuff with param never assigning it - +public class Test { + public void bar() { + int[] a = new int[10]; + int[] b = new int[10]; + for (int i=0;i<10;i++) { + b[i]=a[i]; + } + } } + // this will trigger the rule + for (int i=0;i<10;i++) { + b[i]=a[c[i]]; + } -public void foo2 (final String param) { // better, do stuff with param never assigning it - + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## AvoidInstantiatingObjectsInLoops **Since:** 2.2 @@ -73,169 +65,117 @@ public class Something { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UseArrayListInsteadOfVector -**Since:** 3.0 +## LocalVariableCouldBeFinal +**Since:** 2.2 **Priority:** Medium (3) -ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. +A local variable assigned only once can be declared final. **Example(s):** ``` -public class SimpleTest extends TestCase { - public void testX() { - Collection c1 = new Vector(); - Collection c2 = new ArrayList(); // achieves the same with much better performance +public class Bar { + public void foo () { + String txtA = "a"; // if txtA will not be assigned again it is better to do this: + final String txtB = "b"; } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## SimplifyStartsWith -**Since:** 3.1 +## MethodArgumentCouldBeFinal +**Since:** 2.2 **Priority:** Medium (3) -Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0) -at the expense of some readability. +A method argument that is never re-assigned within the method can be declared final. **Example(s):** ``` -public class Foo { +public void foo1 (String param) { // do stuff with param never assigning it + +} - boolean checkIt(String x) { - return x.startsWith("a"); // suboptimal - } +public void foo2 (final String param) { // better, do stuff with param never assigning it - boolean fasterCheckIt(String x) { - return x.charAt(0) == 'a'; // faster approach - } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UseStringBufferForStringAppends -**Since:** 3.1 +## PrematureDeclaration +**Since:** 5.0 **Priority:** Medium (3) -The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer. -If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or -threadsafe StringBuffer is recommended to avoid this. +Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception. **Example(s):** ``` -public class Foo { - void bar() { - String a; - a = "foo"; - a += " bar"; - // better would be: - // StringBuilder a = new StringBuilder("foo"); - // a.append(" bar); - } -} -``` +public int getLength(String[] strings) { + + int length = 0; // declared prematurely -**This rule has the following properties:** + if (strings == null || strings.length == 0) return 0; + + for (String str : strings) { + length += str.length(); + } -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| + return length; +} +``` -## UseArraysAsList -**Since:** 3.5 +## RedundantFieldInitializer +**Since:** 5.0 **Priority:** Medium (3) -The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from -an array of objects. It is faster than executing a loop to copy all the elements of the array one by one. +Java will initialize fields with known default values so any explicit initialization of those same defaults +is redundant and results in a larger class file (approximately three additional bytecode instructions per field). **Example(s):** ``` -public class Test { - public void foo(Integer[] ints) { - // could just use Arrays.asList(ints) - List l= new ArrayList(10); - for (int i=0; i< 100; i++) { - l.add(ints[i]); - } - for (int i=0; i< 100; i++) { - l.add(a[i].toString()); // won't trigger the rule - } - } +public class C { + boolean b = false; // examples of redundant initializers + byte by = 0; + short s = 0; + char c = 0; + int i = 0; + long l = 0; + + float f = .0f; // all possible float literals + doable d = 0d; // all possible double literals + Object o = null; + + MyClass mca[] = null; + int i1 = 0, ia1[] = null; + + class Nested { + boolean b = false; + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidArrayLoops -**Since:** 3.5 +## SimplifyStartsWith +**Since:** 3.1 **Priority:** Medium (3) -Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead. +Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0) +at the expense of some readability. **Example(s):** ``` -public class Test { - public void bar() { - int[] a = new int[10]; - int[] b = new int[10]; - for (int i=0;i<10;i++) { - b[i]=a[i]; - } - } -} - // this will trigger the rule - for (int i=0;i<10;i++) { - b[i]=a[c[i]]; - } +public class Foo { - } + boolean checkIt(String x) { + return x.startsWith("a"); // suboptimal + } + + boolean fasterCheckIt(String x) { + return x.charAt(0) == 'a'; // faster approach + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## UnnecessaryWrapperObjectCreation **Since:** 3.8 @@ -263,101 +203,67 @@ public int convert(String s) { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AddEmptyString -**Since:** 4.0 +## UseArrayListInsteadOfVector +**Since:** 3.0 **Priority:** Medium (3) -The conversion of literals to strings by concatenating them with empty strings is inefficient. -It is much better to use one of the type-specific toString() methods instead. +ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. **Example(s):** ``` -String s = "" + 123; // inefficient -String t = Integer.toString(456); // preferred approach +public class SimpleTest extends TestCase { + public void testX() { + Collection c1 = new Vector(); + Collection c2 = new ArrayList(); // achieves the same with much better performance + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## RedundantFieldInitializer -**Since:** 5.0 +## UseArraysAsList +**Since:** 3.5 **Priority:** Medium (3) -Java will initialize fields with known default values so any explicit initialization of those same defaults -is redundant and results in a larger class file (approximately three additional bytecode instructions per field). +The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from +an array of objects. It is faster than executing a loop to copy all the elements of the array one by one. **Example(s):** ``` -public class C { - boolean b = false; // examples of redundant initializers - byte by = 0; - short s = 0; - char c = 0; - int i = 0; - long l = 0; - - float f = .0f; // all possible float literals - doable d = 0d; // all possible double literals - Object o = null; - - MyClass mca[] = null; - int i1 = 0, ia1[] = null; - - class Nested { - boolean b = false; - } +public class Test { + public void foo(Integer[] ints) { + // could just use Arrays.asList(ints) + List l= new ArrayList(10); + for (int i=0; i< 100; i++) { + l.add(ints[i]); + } + for (int i=0; i< 100; i++) { + l.add(a[i].toString()); // won't trigger the rule + } + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## PrematureDeclaration -**Since:** 5.0 +## UseStringBufferForStringAppends +**Since:** 3.1 **Priority:** Medium (3) -Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception. +The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer. +If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or +threadsafe StringBuffer is recommended to avoid this. **Example(s):** ``` -public int getLength(String[] strings) { - - int length = 0; // declared prematurely - - if (strings == null || strings.length == 0) return 0; - - for (String str : strings) { - length += str.length(); - } - - return length; +public class Foo { + void bar() { + String a; + a = "foo"; + a += " bar"; + // better would be: + // StringBuilder a = new StringBuilder("foo"); + // a.append(" bar); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/java/strictexception.md b/docs/pages/pmd/rules/java/strictexception.md index 967fab482..83a3bc630 100644 --- a/docs/pages/pmd/rules/java/strictexception.md +++ b/docs/pages/pmd/rules/java/strictexception.md @@ -6,138 +6,129 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/strictexception.xml --- -## AvoidCatchingThrowable -**Since:** 1.2 +## AvoidCatchingGenericException +**Since:** 4.2.6 **Priority:** Medium (3) -Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as -OutOfMemoryError that should be exposed and managed separately. +Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block **Example(s):** ``` -public void bar() { - try { - // do something - } catch (Throwable th) { // should not catch Throwable - th.printStackTrace(); +package com.igate.primitive; + +public class PrimitiveType { + + public void downCastPrimitiveType() { + try { + System.out.println(" i [" + i + "]"); + } catch(Exception e) { + e.printStackTrace(); + } catch(RuntimeException e) { + e.printStackTrace(); + } catch(NullPointerException e) { + e.printStackTrace(); } - } + } +} ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## SignatureDeclareThrowsException -**Since:** 1.2 +## AvoidCatchingNPE +**Since:** 1.8 **Priority:** Medium (3) -Methods that declare the generic Exception as a possible throwable are not very helpful since their -failure modes are unclear. Use a class derived from RuntimeException or a more specific checked exception. +Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the +original error, causing other, more subtle problems later on. **Example(s):** ``` -public void foo() throws Exception { +public class Foo { + void bar() { + try { + // do something + } catch (NullPointerException npe) { + } + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## ExceptionAsFlowControl -**Since:** 1.8 +## AvoidCatchingThrowable +**Since:** 1.2 **Priority:** Medium (3) -Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging. -Either add the necessary validation or use an alternate control structure. +Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as +OutOfMemoryError that should be exposed and managed separately. **Example(s):** ``` public void bar() { - try { - try { - } catch (Exception e) { - throw new WrapperException(e); - // this is essentially a GOTO to the WrapperException catch block - } - } catch (WrapperException e) { - // do some more stuff + try { + // do something + } catch (Throwable th) { // should not catch Throwable + th.printStackTrace(); } } ``` -**This rule has the following properties:** +## AvoidLosingExceptionInformation +**Since:** 4.2.6 + +**Priority:** Medium High (2) -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +Statements in a catch block that invoke accessors on the exception without using the information +only add to code size. Either remove the invocation, or use the return result. -## AvoidCatchingNPE -**Since:** 1.8 +**Example(s):** +``` +public void bar() { + try { + // do something + } catch (SomeException se) { + se.getMessage(); + } +} +``` + +## AvoidRethrowingException +**Since:** 3.8 **Priority:** Medium (3) -Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the -original error, causing other, more subtle problems later on. +Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. **Example(s):** ``` -public class Foo { - void bar() { +public void bar() { try { - // do something - } catch (NullPointerException npe) { + // do something + } catch (SomeException se) { + throw se; } - } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidThrowingRawExceptionTypes -**Since:** 1.8 +## AvoidThrowingNewInstanceOfSameException +**Since:** 4.2.5 -**Priority:** High (1) +**Priority:** Medium (3) -Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, -Exception, or Error, use a subclassed exception or error instead. +Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to +code size and runtime complexity. **Example(s):** ``` -public class Foo { - public void bar() throws Exception { - throw new Exception(); - } +public void bar() { + try { + // do something + } catch (SomeException se) { + // harmless comment + throw new SomeException(se); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## AvoidThrowingNullPointerException **Since:** 1.8 @@ -156,42 +147,23 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidRethrowingException -**Since:** 3.8 +## AvoidThrowingRawExceptionTypes +**Since:** 1.8 -**Priority:** Medium (3) +**Priority:** High (1) -Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. +Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, +Exception, or Error, use a subclassed exception or error instead. **Example(s):** ``` -public void bar() { - try { - // do something - } catch (SomeException se) { - throw se; - } +public class Foo { + public void bar() throws Exception { + throw new Exception(); + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## DoNotExtendJavaLangError **Since:** 4.0 @@ -204,15 +176,6 @@ Errors are system exceptions. Do not extend them. public class Foo extends Error { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## DoNotThrowExceptionInFinally **Since:** 4.2 @@ -238,105 +201,40 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidThrowingNewInstanceOfSameException -**Since:** 4.2.5 +## ExceptionAsFlowControl +**Since:** 1.8 **Priority:** Medium (3) -Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to -code size and runtime complexity. +Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging. +Either add the necessary validation or use an alternate control structure. **Example(s):** ``` public void bar() { - try { - // do something - } catch (SomeException se) { - // harmless comment - throw new SomeException(se); - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidCatchingGenericException -**Since:** 4.2.6 - -**Priority:** Medium (3) - -Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block - -**Example(s):** -``` -package com.igate.primitive; - -public class PrimitiveType { - - public void downCastPrimitiveType() { try { - System.out.println(" i [" + i + "]"); - } catch(Exception e) { - e.printStackTrace(); - } catch(RuntimeException e) { - e.printStackTrace(); - } catch(NullPointerException e) { - e.printStackTrace(); + try { + } catch (Exception e) { + throw new WrapperException(e); + // this is essentially a GOTO to the WrapperException catch block + } + } catch (WrapperException e) { + // do some more stuff } - } -} + } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## AvoidLosingExceptionInformation -**Since:** 4.2.6 +## SignatureDeclareThrowsException +**Since:** 1.2 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Statements in a catch block that invoke accessors on the exception without using the information -only add to code size. Either remove the invocation, or use the return result. +Methods that declare the generic Exception as a possible throwable are not very helpful since their +failure modes are unclear. Use a class derived from RuntimeException or a more specific checked exception. **Example(s):** ``` -public void bar() { - try { - // do something - } catch (SomeException se) { - se.getMessage(); - } +public void foo() throws Exception { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/java/strings.md b/docs/pages/pmd/rules/java/strings.md index d2a7e2a65..f1ad1c9d2 100644 --- a/docs/pages/pmd/rules/java/strings.md +++ b/docs/pages/pmd/rules/java/strings.md @@ -6,6 +6,22 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/strings.xml --- +## AppendCharacterWithChar +**Since:** 3.5 + +**Priority:** Medium (3) + +Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. + +**Example(s):** +``` +StringBuffer sb = new StringBuffer(); +sb.append("a"); // avoid this + +StringBuffer sb = new StringBuffer(); +sb.append('a'); // use this instead +``` + ## AvoidDuplicateLiterals **Since:** 1.0 @@ -28,8 +44,6 @@ private void bar() { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |exceptionfile||File containing strings to skip (one string per line), only used if ignore list is not set| |separator|,|Ignore list separator| |exceptionList||Strings to ignore| @@ -37,140 +51,21 @@ private void bar() { |minimumLength|3|Minimum string length to check| |skipAnnotations|false|Skip literals within annotations| -## StringInstantiation -**Since:** 1.0 - -**Priority:** Medium High (2) - -Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared. - -**Example(s):** -``` -private String bar = new String("bar"); // just do a String bar = "bar"; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## StringToString -**Since:** 1.0 +## AvoidStringBufferField +**Since:** 4.2 **Priority:** Medium (3) -Avoid calling toString() on objects already known to be string instances; this is unnecessary. +StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks +if held within objects with long lifetimes. **Example(s):** ``` -private String baz() { - String bar = "howdy"; - return bar.toString(); +public class Foo { + private StringBuffer buffer; // potential memory leak as an instance variable; } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## InefficientStringBuffering -**Since:** 3.4 - -**Priority:** Medium (3) - -Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will -need to be be created and destroyed by the JVM. - -**Example(s):** -``` -// Avoid this, two buffers are actually being created here -StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir")); - - // do this instead -StringBuffer sb = new StringBuffer("tmp = "); -sb.append(System.getProperty("java.io.tmpdir")); -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnnecessaryCaseChange -**Since:** 3.3 - -**Priority:** Medium (3) - -Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() - -**Example(s):** -``` -boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz") - -boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase() -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UseStringBufferLength -**Since:** 3.4 - -**Priority:** Medium (3) - -Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") -or StringBuffer.toString().length() == ... - -**Example(s):** -``` -StringBuffer sb = new StringBuffer(); - -if (sb.toString().equals("")) {} // inefficient - -if (sb.length() == 0) {} // preferred -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## AppendCharacterWithChar -**Since:** 3.5 - -**Priority:** Medium (3) - -Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. - -**Example(s):** -``` -StringBuffer sb = new StringBuffer(); -sb.append("a"); // avoid this - -StringBuffer sb = new StringBuffer(); -sb.append('a'); // use this instead -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## ConsecutiveAppendsShouldReuse **Since:** 5.1 @@ -192,13 +87,6 @@ StringBuffer buf = new StringBuffer(); buf.append("Hello").append(foo).append("World"); // good ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## ConsecutiveLiteralAppends **Since:** 3.5 @@ -217,33 +105,8 @@ buf.append("Hello World"); // good |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |threshold|1|Max consecutive appends| -## UseIndexOfChar -**Since:** 3.5 - -**Priority:** Medium (3) - -Use String.indexOf(char) when checking for the index of a single character; it executes faster. - -**Example(s):** -``` -String s = "hello world"; - // avoid this -if (s.indexOf("d") {} - // instead do this -if (s.indexOf('d') {} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## InefficientEmptyStringCheck **Since:** 3.6 @@ -264,12 +127,23 @@ public void bar(String string) { } ``` -**This rule has the following properties:** +## InefficientStringBuffering +**Since:** 3.4 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium (3) + +Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will +need to be be created and destroyed by the JVM. + +**Example(s):** +``` +// Avoid this, two buffers are actually being created here +StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir")); + + // do this instead +StringBuffer sb = new StringBuffer("tmp = "); +sb.append(System.getProperty("java.io.tmpdir")); +``` ## InsufficientStringBufferDeclaration **Since:** 3.6 @@ -291,37 +165,6 @@ StringBuffer good = new StringBuffer(41); good.append("This is a long string, which is pre-sized"); ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UselessStringValueOf -**Since:** 3.8 - -**Priority:** Medium (3) - -No need to call String.valueOf to append to a string; just use the valueOf() argument directly. - -**Example(s):** -``` -public String convert(int i) { - String s; - s = "a" + String.valueOf(i); // not required - s = "a" + i; // preferred approach - return s; -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## StringBufferInstantiationWithChar **Since:** 3.9 @@ -354,14 +197,46 @@ StringBuffer sb3 = new StringBuffer("c"); StringBuilder sb4 = new StringBuilder("c"); ``` -**This rule has the following properties:** +## StringInstantiation +**Since:** 1.0 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) + +Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared. + +**Example(s):** +``` +private String bar = new String("bar"); // just do a String bar = "bar"; +``` + +## StringToString +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid calling toString() on objects already known to be string instances; this is unnecessary. + +**Example(s):** +``` +private String baz() { + String bar = "howdy"; + return bar.toString(); +} +``` + +## UnnecessaryCaseChange +**Since:** 3.3 + +**Priority:** Medium (3) + +Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() + +**Example(s):** +``` +boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz") + +boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unnecessary toUpperCase() +``` ## UseEqualsToCompareStrings **Since:** 4.1 @@ -380,36 +255,53 @@ public boolean test(String s) { } ``` -**This rule has the following properties:** +## UseIndexOfChar +**Since:** 3.5 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) -## AvoidStringBufferField -**Since:** 4.2 +Use String.indexOf(char) when checking for the index of a single character; it executes faster. + +**Example(s):** +``` +String s = "hello world"; + // avoid this +if (s.indexOf("d") {} + // instead do this +if (s.indexOf('d') {} +``` + +## UselessStringValueOf +**Since:** 3.8 **Priority:** Medium (3) -StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks -if held within objects with long lifetimes. +No need to call String.valueOf to append to a string; just use the valueOf() argument directly. **Example(s):** ``` -public class Foo { - private StringBuffer buffer; // potential memory leak as an instance variable; +public String convert(int i) { + String s; + s = "a" + String.valueOf(i); // not required + s = "a" + i; // preferred approach + return s; } ``` -**This rule has the following properties:** +## UseStringBufferLength +**Since:** 3.4 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium (3) + +Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") +or StringBuffer.toString().length() == ... + +**Example(s):** +``` +StringBuffer sb = new StringBuffer(); + +if (sb.toString().equals("")) {} // inefficient + +if (sb.length() == 0) {} // preferred +``` diff --git a/docs/pages/pmd/rules/java/sunsecure.md b/docs/pages/pmd/rules/java/sunsecure.md index cee12eeed..8010bec6f 100644 --- a/docs/pages/pmd/rules/java/sunsecure.md +++ b/docs/pages/pmd/rules/java/sunsecure.md @@ -6,32 +6,6 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/sunsecure.xml --- -## MethodReturnsInternalArray -**Since:** 2.2 - -**Priority:** Medium (3) - -Exposing internal arrays to the caller violates object encapsulation since elements can be -removed or replaced outside of the object that owns it. It is safer to return a copy of the array. - -**Example(s):** -``` -public class SecureSystem { - UserData [] ud; - public UserData [] getUserData() { - // Don't return directly the internal array, return a copy - return ud; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## ArrayIsStoredDirectly **Since:** 2.2 @@ -51,10 +25,22 @@ public class Foo { } ``` -**This rule has the following properties:** +## MethodReturnsInternalArray +**Since:** 2.2 + +**Priority:** Medium (3) -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +Exposing internal arrays to the caller violates object encapsulation since elements can be +removed or replaced outside of the object that owns it. It is safer to return a copy of the array. + +**Example(s):** +``` +public class SecureSystem { + UserData [] ud; + public UserData [] getUserData() { + // Don't return directly the internal array, return a copy + return ud; + } +} +``` diff --git a/docs/pages/pmd/rules/java/unnecessary.md b/docs/pages/pmd/rules/java/unnecessary.md index 47d325c5b..bd12faff7 100644 --- a/docs/pages/pmd/rules/java/unnecessary.md +++ b/docs/pages/pmd/rules/java/unnecessary.md @@ -23,37 +23,6 @@ public String convert(int x) { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnnecessaryReturn -**Since:** 1.3 - -**Priority:** Medium (3) - -Avoid the use of unnecessary return statements. - -**Example(s):** -``` -public class Foo { - public void bar() { - int x = 42; - return; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## UnnecessaryFinalModifier **Since:** 3.0 @@ -73,77 +42,56 @@ public final class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UselessOverridingMethod -**Since:** 3.3 +## UnnecessaryModifier +**Since:** 1.02 **Priority:** Medium (3) -The overriding method merely calls the same method defined in a superclass. +Fields in interfaces and annotations are automatically `public static final`, and methods are `public abstract`. +Classes, interfaces or annotations nested in an interface or annotation are automatically `public static` +(all nested interfaces and annotations are automatically static). +Nested enums are automatically `static`. +For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous. **Example(s):** ``` -public void foo(String bar) { - super.foo(bar); // why bother overriding? +public @interface Annotation { + public abstract void bar(); // both abstract and public are ignored by the compiler + public static final int X = 0; // public, static, and final all ignored + public static class Bar {} // public, static ignored + public static interface Baz {} // ditto } - -public String foo() { - return super.foo(); // why bother overriding? +public interface Foo { + public abstract void bar(); // both abstract and public are ignored by the compiler + public static final int X = 0; // public, static, and final all ignored + public static class Bar {} // public, static ignored + public static interface Baz {} // ditto } - -@Id -public Long getId() { - return super.getId(); // OK if 'ignoreAnnotations' is false, which is the default behavior +public class Bar { + public static interface Baz {} // static ignored + public static enum FoorBar { // static ignored + FOO; + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|ignoreAnnotations|false|Ignore annotations| - -## UselessOperationOnImmutable -**Since:** 3.5 +## UnnecessaryReturn +**Since:** 1.3 **Priority:** Medium (3) -An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself -since the result of the operation is a new object. Therefore, ignoring the operation result is an error. +Avoid the use of unnecessary return statements. **Example(s):** ``` -import java.math.*; - -class Test { - void method1() { - BigDecimal bd=new BigDecimal(10); - bd.add(new BigDecimal(5)); // this will trigger the rule - } - void method2() { - BigDecimal bd=new BigDecimal(10); - bd = bd.add(new BigDecimal(5)); // this won't trigger the rule +public class Foo { + public void bar() { + int x = 42; + return; } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## UnusedNullCheckInEquals **Since:** 3.5 @@ -190,14 +138,58 @@ public class Test { } ``` +## UselessOperationOnImmutable +**Since:** 3.5 + +**Priority:** Medium (3) + +An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself +since the result of the operation is a new object. Therefore, ignoring the operation result is an error. + +**Example(s):** +``` +import java.math.*; + +class Test { + void method1() { + BigDecimal bd=new BigDecimal(10); + bd.add(new BigDecimal(5)); // this will trigger the rule + } + void method2() { + BigDecimal bd=new BigDecimal(10); + bd = bd.add(new BigDecimal(5)); // this won't trigger the rule + } +} +``` + +## UselessOverridingMethod +**Since:** 3.3 + +**Priority:** Medium (3) + +The overriding method merely calls the same method defined in a superclass. + +**Example(s):** +``` +public void foo(String bar) { + super.foo(bar); // why bother overriding? +} + +public String foo() { + return super.foo(); // why bother overriding? +} + +@Id +public Long getId() { + return super.getId(); // OK if 'ignoreAnnotations' is false, which is the default behavior +} +``` + **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|ignoreAnnotations|false|Ignore annotations| ## UselessParentheses **Since:** 5.0 @@ -221,15 +213,6 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## UselessQualifiedThis **Since:** 5.4.0 @@ -265,52 +248,3 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## UnnecessaryModifier -**Since:** 1.02 - -**Priority:** Medium (3) - -Fields in interfaces and annotations are automatically `public static final`, and methods are `public abstract`. -Classes, interfaces or annotations nested in an interface or annotation are automatically `public static` -(all nested interfaces and annotations are automatically static). -Nested enums are automatically `static`. -For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous. - -**Example(s):** -``` -public @interface Annotation { - public abstract void bar(); // both abstract and public are ignored by the compiler - public static final int X = 0; // public, static, and final all ignored - public static class Bar {} // public, static ignored - public static interface Baz {} // ditto -} -public interface Foo { - public abstract void bar(); // both abstract and public are ignored by the compiler - public static final int X = 0; // public, static, and final all ignored - public static class Bar {} // public, static ignored - public static interface Baz {} // ditto -} -public class Bar { - public static interface Baz {} // static ignored - public static enum FoorBar { // static ignored - FOO; - } -} -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/java/unusedcode.md b/docs/pages/pmd/rules/java/unusedcode.md index 9944476ce..c605268a5 100644 --- a/docs/pages/pmd/rules/java/unusedcode.md +++ b/docs/pages/pmd/rules/java/unusedcode.md @@ -6,22 +6,19 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/unusedcode.xml --- -## UnusedPrivateField -**Since:** 0.1 +## UnusedFormalParameter +**Since:** 0.8 **Priority:** Medium (3) -Detects when a private field is declared and/or assigned a value, but not used. +Avoid passing parameters to methods or constructors without actually referencing them in the method body. **Example(s):** ``` -public class Something { - private static int FOO = 2; // Unused - private int i = 5; // Unused - private int j = 6; - public int addOne() { - return j++; - } +public class Foo { + private void bar(String howdy) { + // howdy is not used + } } ``` @@ -29,8 +26,7 @@ public class Something { |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|checkAll|false|Check all methods, including non-private ones| ## UnusedLocalVariable **Since:** 0.1 @@ -48,55 +44,36 @@ public class Foo { } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnusedPrivateMethod -**Since:** 0.7 +## UnusedPrivateField +**Since:** 0.1 **Priority:** Medium (3) -Unused Private Method detects when a private method is declared but is unused. +Detects when a private field is declared and/or assigned a value, but not used. **Example(s):** ``` public class Something { - private void foo() {} // unused + private static int FOO = 2; // Unused + private int i = 5; // Unused + private int j = 6; + public int addOne() { + return j++; + } } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnusedFormalParameter -**Since:** 0.8 +## UnusedPrivateMethod +**Since:** 0.7 **Priority:** Medium (3) -Avoid passing parameters to methods or constructors without actually referencing them in the method body. +Unused Private Method detects when a private method is declared but is unused. **Example(s):** ``` -public class Foo { - private void bar(String howdy) { - // howdy is not used - } +public class Something { + private void foo() {} // unused } ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|checkAll|false|Check all methods, including non-private ones| - diff --git a/docs/pages/pmd/rules/jsp/basic-jsf.md b/docs/pages/pmd/rules/jsp/basic-jsf.md index ddf417e7f..c3f09b6d5 100644 --- a/docs/pages/pmd/rules/jsp/basic-jsf.md +++ b/docs/pages/pmd/rules/jsp/basic-jsf.md @@ -22,12 +22,3 @@ Do not nest JSF component custom actions inside a custom action that iterates ov </ul> </body> </html> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/jsp/basic.md b/docs/pages/pmd/rules/jsp/basic.md index f5e1a205c..e3ddb2f59 100644 --- a/docs/pages/pmd/rules/jsp/basic.md +++ b/docs/pages/pmd/rules/jsp/basic.md @@ -6,96 +6,53 @@ folder: pmd/rules/jsp sidebaractiveurl: /pmd_rules_jsp.html editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic.xml --- -## NoLongScripts -**Since:** 3.6 +## DuplicateJspImports +**Since:** 3.7 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Scripts should be part of Tag Libraries, rather than part of JSP pages. +Avoid duplicate import statements inside JSP's. **Example(s):** ``` -<HTML> -<BODY> -<!--Java Script--> -<SCRIPT language="JavaScript" type="text/javascript"> -<!-- -function calcDays(){ - var date1 = document.getElementById('d1').lastChild.data; - var date2 = document.getElementById('d2').lastChild.data; - date1 = date1.split("-"); - date2 = date2.split("-"); - var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]); - var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]); - var daysApart = Math.abs(Math.round((sDate-eDate)/86400000)); - document.getElementById('diffDays').lastChild.data = daysApart; -} - -onload=calcDays; -//--> -</SCRIPT> -</BODY> -</HTML> +<%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%><html><body><b><img src=\"<%=Some.get()%>/foo\">xx</img>text</b></body></html> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## NoScriptlets +## IframeMissingSrcAttribute **Since:** 3.6 -**Priority:** Medium (3) +**Priority:** Medium High (2) -Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. +IFrames which are missing a src element can cause security information popups in IE if you are accessing the page +through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 **Example(s):** ``` -<HTML> -<HEAD> -<% -response.setHeader("Pragma", "No-cache"); -%> -</HEAD> - <BODY> - <jsp:scriptlet>String title = "Hello world!";</jsp:scriptlet> - </BODY> -</HTML> -``` - -**This rule has the following properties:** +<HTML><title>bad example><BODY> +<iframe></iframe> +</BODY> </HTML> -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +<HTML><title>good example><BODY> +<iframe src="foo"></iframe> +</BODY> </HTML> +``` -## NoInlineStyleInformation -**Since:** 3.6 +## JspEncoding +**Since:** 4.0 **Priority:** Medium (3) -Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FONT> tags, or attributes like "align='center'". +A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. **Example(s):** ``` -<html><body><p align='center'><b>text</b></p></body></html> +Most browsers should be able to interpret the following headers: + + <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + + <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## NoClassAttribute **Since:** 3.6 @@ -110,64 +67,6 @@ Do not use an attribute called 'class'. Use "styleclass" for CSS styles. </BODY> </HTML> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## NoJspForward -**Since:** 3.6 - -**Priority:** Medium (3) - -Do not do a forward from within a JSP file. - -**Example(s):** -``` -<jsp:forward page='UnderConstruction.jsp'/> -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## IframeMissingSrcAttribute -**Since:** 3.6 - -**Priority:** Medium High (2) - -IFrames which are missing a src element can cause security information popups in IE if you are accessing the page -through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 - -**Example(s):** -``` -<HTML><title>bad example><BODY> -<iframe></iframe> -</BODY> </HTML> - -<HTML><title>good example><BODY> -<iframe src="foo"></iframe> -</BODY> </HTML> -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## NoHtmlComments **Since:** 3.6 @@ -188,85 +87,100 @@ In a production system, HTML comments increase the payload </BODY> </HTML> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## DuplicateJspImports -**Since:** 3.7 +## NoInlineScript +**Since:** 4.0 **Priority:** Medium (3) -Avoid duplicate import statements inside JSP's. +Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the "script" element. +Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth. **Example(s):** ``` -<%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%><html><body><b><img src=\"<%=Some.get()%>/foo\">xx</img>text</b></body></html> +Most browsers should be able to interpret the following headers: + + <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + + <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> ``` -**This rule has the following properties:** +## NoInlineStyleInformation +**Since:** 3.6 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +**Priority:** Medium (3) -## JspEncoding -**Since:** 4.0 +Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FONT> tags, or attributes like "align='center'". + +**Example(s):** +``` +<html><body><p align='center'><b>text</b></p></body></html> +``` + +## NoJspForward +**Since:** 3.6 **Priority:** Medium (3) -A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. +Do not do a forward from within a JSP file. **Example(s):** ``` -Most browsers should be able to interpret the following headers: - - <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> - - <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> +<jsp:forward page='UnderConstruction.jsp'/> ``` -**This rule has the following properties:** +## NoLongScripts +**Since:** 3.6 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) -## NoInlineScript -**Since:** 4.0 +Scripts should be part of Tag Libraries, rather than part of JSP pages. + +**Example(s):** +``` +<HTML> +<BODY> +<!--Java Script--> +<SCRIPT language="JavaScript" type="text/javascript"> +<!-- +function calcDays(){ + var date1 = document.getElementById('d1').lastChild.data; + var date2 = document.getElementById('d2').lastChild.data; + date1 = date1.split("-"); + date2 = date2.split("-"); + var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]); + var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]); + var daysApart = Math.abs(Math.round((sDate-eDate)/86400000)); + document.getElementById('diffDays').lastChild.data = daysApart; +} + +onload=calcDays; +//--> +</SCRIPT> +</BODY> +</HTML> +``` + +## NoScriptlets +**Since:** 3.6 **Priority:** Medium (3) -Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the "script" element. -Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth. +Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. **Example(s):** ``` -Most browsers should be able to interpret the following headers: - - <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> - - <meta http-equiv="Content-Type"  content="text/html; charset=UTF-8" /> +<HTML> +<HEAD> +<% +response.setHeader("Pragma", "No-cache"); +%> +</HEAD> + <BODY> + <jsp:scriptlet>String title = "Hello world!";</jsp:scriptlet> + </BODY> +</HTML> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## NoUnsanitizedJSPExpression **Since:** 5.1.4 @@ -284,10 +198,3 @@ ${fn:escapeXml(expression)} <!-- instead, escape it --> <c:out value="${expression}" /> <!-- or use c:out --> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/plsql/TomKytesDespair.md b/docs/pages/pmd/rules/plsql/TomKytesDespair.md index 6f9784c8b..62dd24c3c 100644 --- a/docs/pages/pmd/rules/plsql/TomKytesDespair.md +++ b/docs/pages/pmd/rules/plsql/TomKytesDespair.md @@ -57,12 +57,3 @@ END update_planned_hrs; / ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/plsql/codesize.md b/docs/pages/pmd/rules/plsql/codesize.md index 405da0ba8..851ee09d8 100644 --- a/docs/pages/pmd/rules/plsql/codesize.md +++ b/docs/pages/pmd/rules/plsql/codesize.md @@ -6,48 +6,131 @@ folder: pmd/rules/plsql sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/codesize.xml --- -## NPathComplexity +## CyclomaticComplexity **Since:** 5.1 **Priority:** Medium (3) -The NPath complexity of a method is the number of acyclic execution paths through that method. -A threshold of 200 is generally considered the point where measures should be taken to reduce -complexity and increase readability. +Complexity directly affects maintenance costs is determined by the number of decision points in a method +plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. +Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote +high complexity, and 11+ is very high complexity. **Example(s):** ``` -CREATE OR REPLACE -PROCEDURE bar AS BEGIN -- this is something more complex than it needs to be, - if (y) THEN -- it should be broken down into smaller methods or functions - for j IN 0 .. j-1 LOOP - if (j > r) THEN - doSomething; - while (f < 5 ) LOOP - anotherThing; - f := f - 27; - END LOOP; - else - tryThis(); - END IF; - END LOOP; - END IF; - if ( r - n > 45) THEN - while (doMagic) LOOP - findRabbits; - END LOOP; - END IF; - BEGIN - doSomethingDangerous(); - EXCEPTION WHEN FooException THEN - makeAmends; - BEGIN - dontDoItAgain; - EXCEPTION - WHEN OTHERS THEN - log_problem; - END; - END; +-- Cyclomatic Complexity of 25 +CREATE OR REPLACE PACKAGE BODY pkg_pmd_working_sequence AS +1 PROCEDURE ty_logger IS BEGIN +2 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +3 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +4 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +5 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +6 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +7 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +8 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +9 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +10 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + END IF; +11 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +12 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +13 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +14 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +15 ELSIF false + THEN +16 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +17 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +18 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +19 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +20 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; +21 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +22 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +23 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); +24 IF true + THEN + DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); +25 ELSIF false + THEN + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + ELSE + DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); + END IF; + END IF; + END IF; +END; + END; ``` @@ -55,11 +138,9 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| +|showMethodsComplexity|true|Add method average violations to the report| +|showClassesComplexity|true|Add class average violations to the report| +|reportLevel|10|Cyclomatic Complexity reporting threshold| ## ExcessiveMethodLength **Since:** 5.1 @@ -85,43 +166,6 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| - -## ExcessiveParameterList -**Since:** 5.1 - -**Priority:** Medium (3) - -Methods with numerous parameters are a challenge to maintain, especially if most of them share the -same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. - -**Example(s):** -``` -CREATE OR REPLACE -PROCEDURE addPerson( -- too many arguments liable to be mixed up - birthYear pls_integer, birthMonth pls_integer, birthDate pls_integer, height pls_integer, weight pls_integer, ssn pls_integer) { - - . . . . -END ADDPERSON; - -CREATE OR REPLACE -PROCEDURE addPerson( -- preferred approach - birthdate DATE, measurements BodyMeasurements , ssn INTEGER) BEGIN - - . . . . -END; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -160,48 +204,6 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| - -## ExcessiveTypeLength -**Since:** 5.1 - -**Priority:** Medium (3) - -Excessive class file lengths are usually indications that the class may be burdened with excessive -responsibilities that could be provided by external classes or functions. In breaking these methods -apart the code becomes more managable and ripe for reuse. - -**Example(s):** -``` -CREATE OR REPLACE -TYPE BODY Foo AS - MEMBER PROCEDURE bar1 IS BEGIN - -- 1000 lines of code - END bar1; - MEMBER PROCEDURE bar2 IS BEGIN - -- 1000 lines of code - END bar2; - MEMBER PROCEDURE bar3 IS BEGIN - -- 1000 lines of code - END bar3; - - - MEMBER PROCEDURE barN IS BEGIN - -- 1000 lines of code - END barn; -END; -``` - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -240,8 +242,6 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -273,137 +273,32 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| -## CyclomaticComplexity +## ExcessiveParameterList **Since:** 5.1 **Priority:** Medium (3) -Complexity directly affects maintenance costs is determined by the number of decision points in a method -plus one for the method entry. The decision points include 'if', 'while', 'for', and 'case labels' calls. -Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote -high complexity, and 11+ is very high complexity. +Methods with numerous parameters are a challenge to maintain, especially if most of them share the +same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. **Example(s):** ``` --- Cyclomatic Complexity of 25 -CREATE OR REPLACE PACKAGE BODY pkg_pmd_working_sequence AS -1 PROCEDURE ty_logger IS BEGIN -2 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -3 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -4 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -5 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; -6 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -7 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -8 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -9 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -10 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - END IF; -11 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -12 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -13 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -14 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; -15 ELSIF false - THEN -16 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -17 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -18 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -19 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -20 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; -21 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -22 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -23 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); -24 IF true - THEN - DBMS_OUTPUT.PUT_LINE('IF/THEN l_Integer='||l_integer); -25 ELSIF false - THEN - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - ELSE - DBMS_OUTPUT.PUT_LINE('ELSIF l_Integer='||l_integer); - END IF; - END IF; - END IF; -END; - +CREATE OR REPLACE +PROCEDURE addPerson( -- too many arguments liable to be mixed up + birthYear pls_integer, birthMonth pls_integer, birthDate pls_integer, height pls_integer, weight pls_integer, ssn pls_integer) { + + . . . . +END ADDPERSON; + +CREATE OR REPLACE +PROCEDURE addPerson( -- preferred approach + birthdate DATE, measurements BodyMeasurements , ssn INTEGER) BEGIN + + . . . . END; ``` @@ -411,38 +306,47 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|showMethodsComplexity|true|Add method average violations to the report| -|showClassesComplexity|true|Add class average violations to the report| -|reportLevel|10|Cyclomatic Complexity reporting threshold| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| -## TooManyFields +## ExcessiveTypeLength **Since:** 5.1 **Priority:** Medium (3) -Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, -possibly through grouping related fields in new objects. For example, a class with individual -city/state/zip fields could park them within a single Address field. +Excessive class file lengths are usually indications that the class may be burdened with excessive +responsibilities that could be provided by external classes or functions. In breaking these methods +apart the code becomes more managable and ripe for reuse. **Example(s):** ``` -CREATE OR REPLACE PACKAGE pkg_too_many_fields AS - C_CHAR_A CONSTANT CHAR(1 CHAR) := 'A'; - C_CHAR_B CONSTANT CHAR(1 CHAR) := 'B'; - ... - C_CHAR_Z CONSTANT CHAR(1 CHAR) := 'Z'; -END pkg_too_many_fields; +CREATE OR REPLACE +TYPE BODY Foo AS + MEMBER PROCEDURE bar1 IS BEGIN + -- 1000 lines of code + END bar1; + MEMBER PROCEDURE bar2 IS BEGIN + -- 1000 lines of code + END bar2; + MEMBER PROCEDURE bar3 IS BEGIN + -- 1000 lines of code + END bar3; + + + MEMBER PROCEDURE barN IS BEGIN + -- 1000 lines of code + END barn; +END; ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|maxfields|15|Max allowable fields| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| ## NcssMethodCount **Since:** 5.1 @@ -467,8 +371,6 @@ END; |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| @@ -498,12 +400,88 @@ CREATE OR REPLACE PACKAGE pkg_ |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |topscore||Top score value| |minimum||Minimum reporting threshold| |sigma||Sigma value| +## NPathComplexity +**Since:** 5.1 + +**Priority:** Medium (3) + +The NPath complexity of a method is the number of acyclic execution paths through that method. +A threshold of 200 is generally considered the point where measures should be taken to reduce +complexity and increase readability. + +**Example(s):** +``` +CREATE OR REPLACE +PROCEDURE bar AS BEGIN -- this is something more complex than it needs to be, + if (y) THEN -- it should be broken down into smaller methods or functions + for j IN 0 .. j-1 LOOP + if (j > r) THEN + doSomething; + while (f < 5 ) LOOP + anotherThing; + f := f - 27; + END LOOP; + else + tryThis(); + END IF; + END LOOP; + END IF; + if ( r - n > 45) THEN + while (doMagic) LOOP + findRabbits; + END LOOP; + END IF; + BEGIN + doSomethingDangerous(); + EXCEPTION WHEN FooException THEN + makeAmends; + BEGIN + dontDoItAgain; + EXCEPTION + WHEN OTHERS THEN + log_problem; + END; + END; +END; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| + +## TooManyFields +**Since:** 5.1 + +**Priority:** Medium (3) + +Classes that have too many fields can become unwieldy and could be redesigned to have fewer fields, +possibly through grouping related fields in new objects. For example, a class with individual +city/state/zip fields could park them within a single Address field. + +**Example(s):** +``` +CREATE OR REPLACE PACKAGE pkg_too_many_fields AS + C_CHAR_A CONSTANT CHAR(1 CHAR) := 'A'; + C_CHAR_B CONSTANT CHAR(1 CHAR) := 'B'; + ... + C_CHAR_Z CONSTANT CHAR(1 CHAR) := 'Z'; +END pkg_too_many_fields; +``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|maxfields|15|Max allowable fields| + ## TooManyMethods **Since:** 5.1 @@ -516,9 +494,5 @@ have more fine grained objects. |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| |maxmethods|1|The method count reporting threshold| diff --git a/docs/pages/pmd/rules/plsql/dates.md b/docs/pages/pmd/rules/plsql/dates.md index 756465f62..98bd3424c 100644 --- a/docs/pages/pmd/rules/plsql/dates.md +++ b/docs/pages/pmd/rules/plsql/dates.md @@ -6,12 +6,12 @@ folder: pmd/rules/plsql sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/dates.xml --- -## TO_DATEWithoutDateFormat +## TO_DATE_TO_CHAR **Since:** 5.1 **Priority:** Medium (3) -TO_DATE without date format- use TO_DATE(expression, date-format) +TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) **Example(s):** ``` @@ -19,45 +19,23 @@ CREATE OR REPLACE PACKAGE BODY date_utilities IS -- Take single parameter, relyimg on current default NLS date format -FUNCTION to_date_single_parameter (p_date_string IN VARCHAR2) RETURN DATE -IS -BEGIN - RETURN TO_DATE(p_date_string); -END to_date_single_parameter ; - --- Take 2 parameters, using an explicit date format string -FUNCTION to_date_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE +FUNCTION strip_time (p_date IN DATE) RETURN DATE IS BEGIN - TO_DATE(p_date_string, p_date_format); -END to_date_two_parameters ; + RETURN TO_DATE(TO_CHAR(p_date)); +END strip_time ; --- Take 3 parameters, using an explicit date format string and an explicit language -FUNCTION to_date_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE -IS -BEGIN - TO_DATE(p_date_string, p_format_mask, p_nls_language); -END to_date_three_parameters ; END date_utilities ; / ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - -## TO_DATE_TO_CHAR +## TO_DATEWithoutDateFormat **Since:** 5.1 **Priority:** Medium (3) -TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) +TO_DATE without date format- use TO_DATE(expression, date-format) **Example(s):** ``` @@ -65,26 +43,30 @@ CREATE OR REPLACE PACKAGE BODY date_utilities IS -- Take single parameter, relyimg on current default NLS date format -FUNCTION strip_time (p_date IN DATE) RETURN DATE +FUNCTION to_date_single_parameter (p_date_string IN VARCHAR2) RETURN DATE IS BEGIN - RETURN TO_DATE(TO_CHAR(p_date)); -END strip_time ; + RETURN TO_DATE(p_date_string); +END to_date_single_parameter ; + +-- Take 2 parameters, using an explicit date format string +FUNCTION to_date_two_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2) RETURN DATE +IS +BEGIN + TO_DATE(p_date_string, p_date_format); +END to_date_two_parameters ; +-- Take 3 parameters, using an explicit date format string and an explicit language +FUNCTION to_date_three_parameters (p_date_string IN VARCHAR2, p_format_mask IN VARCHAR2, p_nls_language VARCHAR2 ) RETURN DATE +IS +BEGIN + TO_DATE(p_date_string, p_format_mask, p_nls_language); +END to_date_three_parameters ; END date_utilities ; / ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - ## TO_TIMESTAMPWithoutDateFormat **Since:** 5.1 @@ -122,12 +104,3 @@ END date_utilities ; / ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/plsql/strictsyntax.md b/docs/pages/pmd/rules/plsql/strictsyntax.md index dc408f128..a2095dc21 100644 --- a/docs/pages/pmd/rules/plsql/strictsyntax.md +++ b/docs/pages/pmd/rules/plsql/strictsyntax.md @@ -35,12 +35,3 @@ end inline_pragma_error; / ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/vf/security.md b/docs/pages/pmd/rules/vf/security.md index fe133ea91..6839cd39c 100644 --- a/docs/pages/pmd/rules/vf/security.md +++ b/docs/pages/pmd/rules/vf/security.md @@ -6,41 +6,27 @@ folder: pmd/rules/vf sidebaractiveurl: /pmd_rules_vf.html editmepath: ../pmd-visualforce/src/main/resources/rulesets/vf/security.xml --- -## VfUnescapeEl +## VfCsrf **Since:** 5.6.0 **Priority:** Medium (3) -Avoid unescaped user controlled content in EL as it results in XSS. +Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. **Example(s):** ``` -<apex:outputText value="Potential XSS is {! here }" escape="false" /> +<apex:page controller="AcRestActionsController" action="{!csrfInitMethod}" > ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## VfCsrf +## VfUnescapeEl **Since:** 5.6.0 **Priority:** Medium (3) -Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. +Avoid unescaped user controlled content in EL as it results in XSS. **Example(s):** ``` -<apex:page controller="AcRestActionsController" action="{!csrfInitMethod}" > +<apex:outputText value="Potential XSS is {! here }" escape="false" /> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - diff --git a/docs/pages/pmd/rules/vm/basic.md b/docs/pages/pmd/rules/vm/basic.md index 7b32df8eb..6b51f70d2 100644 --- a/docs/pages/pmd/rules/vm/basic.md +++ b/docs/pages/pmd/rules/vm/basic.md @@ -17,54 +17,28 @@ Avoid creating deeply nested if-then statements since they are harder to read an |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| |problemDepth|3|The if statement depth reporting threshold| -## CollapsibleIfStatements +## AvoidReassigningParameters **Since:** 5.1 -**Priority:** Medium (3) - -Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. - -**This rule has the following properties:** +**Priority:** Medium High (2) -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. -## ExcessiveTemplateLength +## CollapsibleIfStatements **Since:** 5.1 **Priority:** Medium (3) -The template is too long. It should be broken up into smaller pieces. - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|topscore||Top score value| -|minimum||Minimum reporting threshold| -|sigma||Sigma value| +Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. -## AvoidReassigningParameters +## EmptyForeachStmt **Since:** 5.1 **Priority:** Medium High (2) -Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +Empty foreach statements should be deleted. ## EmptyIfStmt **Since:** 5.1 @@ -73,40 +47,20 @@ Reassigning values to incoming parameters is not recommended. Use temporary loc Empty if statements should be deleted. -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## EmptyForeachStmt -**Since:** 5.1 - -**Priority:** Medium High (2) - -Empty foreach statements should be deleted. - -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - -## UnusedMacroParameter +## ExcessiveTemplateLength **Since:** 5.1 -**Priority:** Medium High (2) +**Priority:** Medium (3) -Avoid unused macro parameters. They should be deleted. +The template is too long. It should be broken up into smaller pieces. **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| +|topscore||Top score value| +|minimum||Minimum reporting threshold| +|sigma||Sigma value| ## NoInlineJavaScript **Since:** 5.1 @@ -115,13 +69,6 @@ Avoid unused macro parameters. They should be deleted. Avoid inline JavaScript. Import .js files instead. -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| - ## NoInlineStyles **Since:** 5.1 @@ -129,12 +76,10 @@ Avoid inline JavaScript. Import .js files instead. Avoid inline styles. Use css classes instead. -**This rule has the following properties:** +## UnusedMacroParameter +**Since:** 5.1 -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +**Priority:** Medium High (2) + +Avoid unused macro parameters. They should be deleted. diff --git a/docs/pages/pmd/rules/xml/basic.md b/docs/pages/pmd/rules/xml/basic.md index 88bb206a5..49b48ff1c 100644 --- a/docs/pages/pmd/rules/xml/basic.md +++ b/docs/pages/pmd/rules/xml/basic.md @@ -18,12 +18,3 @@ An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and en An extra [ looks like <!CDATA[[]]>, and an extra ] looks like <!CDATA[]]]>. ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| - diff --git a/docs/pages/pmd/rules/xsl/xpath.md b/docs/pages/pmd/rules/xsl/xpath.md index 0cf411365..ddca5b7e9 100644 --- a/docs/pages/pmd/rules/xsl/xpath.md +++ b/docs/pages/pmd/rules/xsl/xpath.md @@ -6,47 +6,34 @@ folder: pmd/rules/xsl sidebaractiveurl: /pmd_rules_xsl.html editmepath: ../pmd-xml/src/main/resources/rulesets/xsl/xpath.xml --- -## UseConcatOnce +## AvoidAxisNavigation **Since:** 5.0 **Priority:** Medium (3) -The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)". +Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document. **Example(s):** ``` -<xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/> - <xsl:variable name="var" select="concat("Welcome","to you ",$name))"> +<xsl:variable name="var" select="//item/descendant::child"/> ``` **This rule has the following properties:** |Name|Default Value|Description| |----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| +|checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.| -## AvoidAxisNavigation +## UseConcatOnce **Since:** 5.0 **Priority:** Medium (3) -Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document. +The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)". **Example(s):** ``` -<xsl:variable name="var" select="//item/descendant::child"/> +<xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/> + <xsl:variable name="var" select="concat("Welcome","to you ",$name))"> ``` -**This rule has the following properties:** - -|Name|Default Value|Description| -|----|-------------|-----------| -|violationSuppressRegex||Suppress violations with messages matching a regular expression| -|violationSuppressXPath||Suppress violations on nodes which match a given relative XPath expression.| -|version|1.0|XPath specification version| -|xpath||XPath expression| -|checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.| - From 026691249407cdfd828bf63ed2536699f0b87bca Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Mon, 31 Jul 2017 21:14:15 +0200 Subject: [PATCH 08/24] [doc] Sort the rules also on the language index page --- .../pmd/docs/RuleDocGenerator.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 5749cc54b..562d2e43d 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -141,8 +141,8 @@ private void generateLanguageIndex(Map<Language, List<RuleSet>> rulesets) throws for (RuleSet ruleset : entry.getValue()) { lines.add("## " + ruleset.getName()); - - for (Rule rule : ruleset.getRules()) { + + for (Rule rule : getSortedRules(ruleset)) { String link = RULESET_INDEX_PERMALINK_PATTERN .replace("${language.tersename}", languageTersename) .replace("${ruleset.name}", getRuleSetFilename(ruleset)); @@ -218,15 +218,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add("editmepath: ../" + getRuleSetSourceFilepath(ruleset)); lines.add("---"); - List<Rule> sortedRules = new ArrayList<>(ruleset.getRules()); - Collections.sort(sortedRules, new Comparator<Rule>() { - @Override - public int compare(Rule o1, Rule o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }); - - for (Rule rule : sortedRules) { + for (Rule rule : getSortedRules(ruleset)) { lines.add("## " + rule.getName()); if (rule.getSince() != null) { lines.add("**Since:** " + rule.getSince()); @@ -276,6 +268,17 @@ public int compare(Rule o1, Rule o2) { } } + private List<Rule> getSortedRules(RuleSet ruleset) { + List<Rule> sortedRules = new ArrayList<>(ruleset.getRules()); + Collections.sort(sortedRules, new Comparator<Rule>() { + @Override + public int compare(Rule o1, Rule o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }); + return sortedRules; + } + /** * Searches for the source file of the given ruleset. This provides the information * for the "editme" link. From fece0cc702c727f06f6360e98fb9497197766f5a Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Mon, 31 Jul 2017 21:15:00 +0200 Subject: [PATCH 09/24] [doc] Update generated rule doc --- docs/pages/pmd/rules/apex.md | 34 +-- docs/pages/pmd/rules/ecmascript.md | 16 +- docs/pages/pmd/rules/java.md | 336 ++++++++++++++--------------- docs/pages/pmd/rules/jsp.md | 14 +- docs/pages/pmd/rules/plsql.md | 12 +- docs/pages/pmd/rules/vf.md | 2 +- docs/pages/pmd/rules/vm.md | 8 +- docs/pages/pmd/rules/xml.md | 2 +- docs/pages/pmd/rules/xsl.md | 2 +- 9 files changed, 213 insertions(+), 213 deletions(-) diff --git a/docs/pages/pmd/rules/apex.md b/docs/pages/pmd/rules/apex.md index 69a09cb34..6c4a2ae36 100644 --- a/docs/pages/pmd/rules/apex.md +++ b/docs/pages/pmd/rules/apex.md @@ -17,44 +17,44 @@ List of rulesets and rules contained in each ruleset. * [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_apexunit.html#apexunittestshouldnotuseseealldatatrue): Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database... ## Braces +* [ForLoopsMustUseBraces](pmd_rules_apex_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using surrounding braces. If the code formatting orindentati... +* [IfElseStmtsMustUseBraces](pmd_rules_apex_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formattingor indent... * [IfStmtsMustUseBraces](pmd_rules_apex_braces.html#ifstmtsmustusebraces): Avoid using if statements without using braces to surround the code block. If the codeformatting ... * [WhileLoopsMustUseBraces](pmd_rules_apex_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using braces to surround the code block. If the codeformat... -* [IfElseStmtsMustUseBraces](pmd_rules_apex_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formattingor indent... -* [ForLoopsMustUseBraces](pmd_rules_apex_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using surrounding braces. If the code formatting orindentati... ## Complexity * [AvoidDeeplyNestedIfStmts](pmd_rules_apex_complexity.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... -* [ExcessiveParameterList](pmd_rules_apex_complexity.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... * [ExcessiveClassLength](pmd_rules_apex_complexity.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... +* [ExcessiveParameterList](pmd_rules_apex_complexity.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... +* [ExcessivePublicCount](pmd_rules_apex_complexity.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... +* [NcssConstructorCount](pmd_rules_apex_complexity.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssMethodCount](pmd_rules_apex_complexity.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssTypeCount](pmd_rules_apex_complexity.html#ncsstypecount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... -* [NcssConstructorCount](pmd_rules_apex_complexity.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [StdCyclomaticComplexity](pmd_rules_apex_complexity.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... * [TooManyFields](pmd_rules_apex_complexity.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... -* [ExcessivePublicCount](pmd_rules_apex_complexity.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... ## Performance -* [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops): New objects created within loops should be checked to see if they can created outside them and re... * [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops): Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch ... +* [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops): New objects created within loops should be checked to see if they can created outside them and re... ## Security -* [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations): Detect classes declared without explicit sharing mode if DML methods are used. Thisforces the dev... -* [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect): Checks against redirects to user-controlled locations. This prevents attackers fromredirecting us... -* [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint): Checks against accessing endpoints under plain http. You should always usehttps for security. -* [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam): Makes sure that all values obtained from URL parameters are properly escaped / sanitizedto avoid ... -* [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse): Reports on calls to 'addError' with disabled escaping. The message passed to 'addError'will be di... * [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto): The rule makes sure you are using randomly generated IVs and keys for 'Crypto' calls.Hard-wiring ... -* [ApexCSRF](pmd_rules_apex_security.html#apexcsrf): Check to avoid making DML operations in Apex class constructor/init method. This preventsmodifica... -* [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection): Detects the usage of untrusted / unescaped variables in DML queries. * [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation): The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation.Since... +* [ApexCSRF](pmd_rules_apex_security.html#apexcsrf): Check to avoid making DML operations in Apex class constructor/init method. This preventsmodifica... * [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods): Checks against calling dangerous methods.For the time being, it reports: Against 'FinancialForce'... +* [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint): Checks against accessing endpoints under plain http. You should always usehttps for security. +* [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect): Checks against redirects to user-controlled locations. This prevents attackers fromredirecting us... +* [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations): Detect classes declared without explicit sharing mode if DML methods are used. Thisforces the dev... +* [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection): Detects the usage of untrusted / unescaped variables in DML queries. * [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred): Detects hardcoded credentials used in requests to an endpoint.You should refrain from hardcoding ... +* [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse): Reports on calls to 'addError' with disabled escaping. The message passed to 'addError'will be di... +* [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam): Makes sure that all values obtained from URL parameters are properly escaped / sanitizedto avoid ... ## Style -* [VariableNamingConventions](pmd_rules_apex_style.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... -* [MethodNamingConventions](pmd_rules_apex_style.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. +* [AvoidGlobalModifier](pmd_rules_apex_style.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... +* [AvoidLogicInTrigger](pmd_rules_apex_style.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... * [ClassNamingConventions](pmd_rules_apex_style.html#classnamingconventions): Class names should always begin with an upper case character. +* [MethodNamingConventions](pmd_rules_apex_style.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. * [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_style.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. -* [AvoidLogicInTrigger](pmd_rules_apex_style.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... -* [AvoidGlobalModifier](pmd_rules_apex_style.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... +* [VariableNamingConventions](pmd_rules_apex_style.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... diff --git a/docs/pages/pmd/rules/ecmascript.md b/docs/pages/pmd/rules/ecmascript.md index ae2fa9c98..2c3d5023b 100644 --- a/docs/pages/pmd/rules/ecmascript.md +++ b/docs/pages/pmd/rules/ecmascript.md @@ -11,23 +11,23 @@ List of rulesets and rules contained in each ruleset. ## Basic Ecmascript * [AssignmentInOperand](pmd_rules_ecmascript_basic.html#assignmentinoperand): Avoid assignments in operands; this can make code more complicated and harder to read. This is s... -* [UnreachableCode](pmd_rules_ecmascript_basic.html#unreachablecode): A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements a... -* [InnaccurateNumericLiteral](pmd_rules_ecmascript_basic.html#innaccuratenumericliteral): The numeric literal will have at different value at runtime, which can happen if you provide too ... +* [AvoidTrailingComma](pmd_rules_ecmascript_basic.html#avoidtrailingcomma): This rule helps improve code portability due to differences in browser treatment of trailing comm... * [ConsistentReturn](pmd_rules_ecmascript_basic.html#consistentreturn): ECMAScript does provide for return types on functions, and therefore there is no solid rule as to... -* [ScopeForInVariable](pmd_rules_ecmascript_basic.html#scopeforinvariable): A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the... * [EqualComparison](pmd_rules_ecmascript_basic.html#equalcomparison): Using == in condition may lead to unexpected results, as the variables are automatically casted t... * [GlobalVariable](pmd_rules_ecmascript_basic.html#globalvariable): This rule helps to avoid using accidently global variables by simply missing the "var" declaratio... -* [AvoidTrailingComma](pmd_rules_ecmascript_basic.html#avoidtrailingcomma): This rule helps improve code portability due to differences in browser treatment of trailing comm... +* [InnaccurateNumericLiteral](pmd_rules_ecmascript_basic.html#innaccuratenumericliteral): The numeric literal will have at different value at runtime, which can happen if you provide too ... +* [ScopeForInVariable](pmd_rules_ecmascript_basic.html#scopeforinvariable): A for-in loop in which the variable name is not explicitly scoped to the enclosing scope with the... +* [UnreachableCode](pmd_rules_ecmascript_basic.html#unreachablecode): A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements a... * [UseBaseWithParseInt](pmd_rules_ecmascript_basic.html#usebasewithparseint): TODO ## Braces -* [IfStmtsMustUseBraces](pmd_rules_ecmascript_braces.html#ifstmtsmustusebraces): Avoid using if statements without using curly braces. +* [ForLoopsMustUseBraces](pmd_rules_ecmascript_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. * [IfElseStmtsMustUseBraces](pmd_rules_ecmascript_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using curly braces. +* [IfStmtsMustUseBraces](pmd_rules_ecmascript_braces.html#ifstmtsmustusebraces): Avoid using if statements without using curly braces. * [WhileLoopsMustUseBraces](pmd_rules_ecmascript_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using curly braces. -* [ForLoopsMustUseBraces](pmd_rules_ecmascript_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. ## Unnecessary -* [UnnecessaryParentheses](pmd_rules_ecmascript_unnecessary.html#unnecessaryparentheses): Unnecessary parentheses should be removed. -* [UnnecessaryBlock](pmd_rules_ecmascript_unnecessary.html#unnecessaryblock): An unnecessary Block is present. Such Blocks are often used in other languages to introduce a... * [NoElseReturn](pmd_rules_ecmascript_unnecessary.html#noelsereturn): The else block in a if-else-construct is unnecessary if the 'if' block contains a return. Then... +* [UnnecessaryBlock](pmd_rules_ecmascript_unnecessary.html#unnecessaryblock): An unnecessary Block is present. Such Blocks are often used in other languages to introduce a... +* [UnnecessaryParentheses](pmd_rules_ecmascript_unnecessary.html#unnecessaryparentheses): Unnecessary parentheses should be removed. diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index cfc556a67..aa6b07fb8 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -37,329 +37,329 @@ List of rulesets and rules contained in each ruleset. * [DoNotHardCodeSDCard](pmd_rules_java_android.html#donothardcodesdcard): Use Environment.getExternalStorageDirectory() instead of "/sdcard" ## Basic -* [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. -* [ForLoopShouldBeWhileLoop](pmd_rules_java_basic.html#forloopshouldbewhileloop): Some for loops can be simplified to while loops, this makes them more concise. -* [OverrideBothEqualsAndHashcode](pmd_rules_java_basic.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... -* [DoubleCheckedLocking](pmd_rules_java_basic.html#doublecheckedlocking): Partially created objects can be returned by the Double Checked Locking pattern when used in Java... -* [ReturnFromFinallyBlock](pmd_rules_java_basic.html#returnfromfinallyblock): Avoid returning from a finally block, this can discard exceptions. -* [UnconditionalIfStatement](pmd_rules_java_basic.html#unconditionalifstatement): Do not use "if" statements whose conditionals are always true or always false. -* [BooleanInstantiation](pmd_rules_java_basic.html#booleaninstantiation): Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boole... -* [CollapsibleIfStatements](pmd_rules_java_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... -* [ClassCastExceptionWithToArray](pmd_rules_java_basic.html#classcastexceptionwithtoarray): When deriving an array of a specific class from your Collection, one should provide an array ofth... +* [AvoidBranchingStatementAsLastInLoop](pmd_rules_java_basic.html#avoidbranchingstatementaslastinloop): Using a branching statement as the last part of a loop may be a bug, and/or is confusing.Ensure t... * [AvoidDecimalLiteralsInBigDecimalConstructor](pmd_rules_java_basic.html#avoiddecimalliteralsinbigdecimalconstructor): One might assume that the result of "new BigDecimal(0.1)" is exactly equal to 0.1, but it is actu... -* [MisplacedNullCheck](pmd_rules_java_basic.html#misplacednullcheck): The null check here is misplaced. If the variable is null a NullPointerException will be thrown.E... +* [AvoidMultipleUnaryOperators](pmd_rules_java_basic.html#avoidmultipleunaryoperators): The use of multiple unary operators may be problematic, and/or confusing.Ensure that the intended... * [AvoidThreadGroup](pmd_rules_java_basic.html#avoidthreadgroup): Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environmentit... -* [BrokenNullCheck](pmd_rules_java_basic.html#brokennullcheck): The null check is broken since it will throw a NullPointerException itself.It is likely that you ... -* [BigIntegerInstantiation](pmd_rules_java_basic.html#bigintegerinstantiation): Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) andfor Ja... -* [AvoidUsingOctalValues](pmd_rules_java_basic.html#avoidusingoctalvalues): Integer literals should not start with zero since this denotes that the rest of literal will bein... * [AvoidUsingHardCodedIP](pmd_rules_java_basic.html#avoidusinghardcodedip): Application with hard-coded IP addresses can become impossible to deploy in some cases.Externaliz... +* [AvoidUsingOctalValues](pmd_rules_java_basic.html#avoidusingoctalvalues): Integer literals should not start with zero since this denotes that the rest of literal will bein... +* [BigIntegerInstantiation](pmd_rules_java_basic.html#bigintegerinstantiation): Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) andfor Ja... +* [BooleanInstantiation](pmd_rules_java_basic.html#booleaninstantiation): Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boole... +* [BrokenNullCheck](pmd_rules_java_basic.html#brokennullcheck): The null check is broken since it will throw a NullPointerException itself.It is likely that you ... * [CheckResultSet](pmd_rules_java_basic.html#checkresultset): Always check the return values of navigation methods (next, previous, first, last) of a ResultSet... -* [AvoidMultipleUnaryOperators](pmd_rules_java_basic.html#avoidmultipleunaryoperators): The use of multiple unary operators may be problematic, and/or confusing.Ensure that the intended... -* [ExtendsObject](pmd_rules_java_basic.html#extendsobject): No need to explicitly extend Object. * [CheckSkipResult](pmd_rules_java_basic.html#checkskipresult): The skip() method may skip a smaller number of bytes than requested. Check the returned value to ... -* [AvoidBranchingStatementAsLastInLoop](pmd_rules_java_basic.html#avoidbranchingstatementaslastinloop): Using a branching statement as the last part of a loop may be a bug, and/or is confusing.Ensure t... +* [ClassCastExceptionWithToArray](pmd_rules_java_basic.html#classcastexceptionwithtoarray): When deriving an array of a specific class from your Collection, one should provide an array ofth... +* [CollapsibleIfStatements](pmd_rules_java_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... * [DontCallThreadRun](pmd_rules_java_basic.html#dontcallthreadrun): Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, ... * [DontUseFloatTypeForLoopIndices](pmd_rules_java_basic.html#dontusefloattypeforloopindices): Don't use floating point for loop indices. If you must use floating point, use doubleunless you'r... +* [DoubleCheckedLocking](pmd_rules_java_basic.html#doublecheckedlocking): Partially created objects can be returned by the Double Checked Locking pattern when used in Java... +* [ExtendsObject](pmd_rules_java_basic.html#extendsobject): No need to explicitly extend Object. +* [ForLoopShouldBeWhileLoop](pmd_rules_java_basic.html#forloopshouldbewhileloop): Some for loops can be simplified to while loops, this makes them more concise. +* [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +* [MisplacedNullCheck](pmd_rules_java_basic.html#misplacednullcheck): The null check here is misplaced. If the variable is null a NullPointerException will be thrown.E... +* [OverrideBothEqualsAndHashcode](pmd_rules_java_basic.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... +* [ReturnFromFinallyBlock](pmd_rules_java_basic.html#returnfromfinallyblock): Avoid returning from a finally block, this can discard exceptions. * [SimplifiedTernary](pmd_rules_java_basic.html#simplifiedternary): Look for ternary operators with the form 'condition ? literalBoolean : foo'or 'condition ? foo : ... +* [UnconditionalIfStatement](pmd_rules_java_basic.html#unconditionalifstatement): Do not use "if" statements whose conditionals are always true or always false. ## Braces +* [ForLoopsMustUseBraces](pmd_rules_java_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. If the code formatting or indentation is... +* [IfElseStmtsMustUseBraces](pmd_rules_java_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formatting or inden... * [IfStmtsMustUseBraces](pmd_rules_java_braces.html#ifstmtsmustusebraces): Avoid using if statements without using braces to surround the code block. If the code formatting... * [WhileLoopsMustUseBraces](pmd_rules_java_braces.html#whileloopsmustusebraces): Avoid using 'while' statements without using braces to surround the code block. If the code forma... -* [IfElseStmtsMustUseBraces](pmd_rules_java_braces.html#ifelsestmtsmustusebraces): Avoid using if..else statements without using surrounding braces. If the code formatting or inden... -* [ForLoopsMustUseBraces](pmd_rules_java_braces.html#forloopsmustusebraces): Avoid using 'for' statements without using curly braces. If the code formatting or indentation is... ## Clone Implementation -* [ProperCloneImplementation](pmd_rules_java_clone.html#propercloneimplementation): Object clone() should be implemented with super.clone(). -* [CloneThrowsCloneNotSupportedException](pmd_rules_java_clone.html#clonethrowsclonenotsupportedexception): The method clone() should throw a CloneNotSupportedException. +* [CloneMethodMustBePublic](pmd_rules_java_clone.html#clonemethodmustbepublic): The java Manual says "By convention, classes that implement this interface should overrideObject.... * [CloneMethodMustImplementCloneable](pmd_rules_java_clone.html#clonemethodmustimplementcloneable): The method clone() should only be implemented if the class implements the Cloneable interface wit... * [CloneMethodReturnTypeMustMatchClassName](pmd_rules_java_clone.html#clonemethodreturntypemustmatchclassname): If a class implements cloneable the return type of the method clone() must be the class name. Tha... -* [CloneMethodMustBePublic](pmd_rules_java_clone.html#clonemethodmustbepublic): The java Manual says "By convention, classes that implement this interface should overrideObject.... +* [CloneThrowsCloneNotSupportedException](pmd_rules_java_clone.html#clonethrowsclonenotsupportedexception): The method clone() should throw a CloneNotSupportedException. +* [ProperCloneImplementation](pmd_rules_java_clone.html#propercloneimplementation): Object clone() should be implemented with super.clone(). ## Code Size -* [NPathComplexity](pmd_rules_java_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [CyclomaticComplexity](pmd_rules_java_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [ExcessiveClassLength](pmd_rules_java_codesize.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... * [ExcessiveMethodLength](pmd_rules_java_codesize.html#excessivemethodlength): When methods are excessively long this usually indicates that the method is doing more than itsna... * [ExcessiveParameterList](pmd_rules_java_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... -* [ExcessiveClassLength](pmd_rules_java_codesize.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... -* [CyclomaticComplexity](pmd_rules_java_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... -* [StdCyclomaticComplexity](pmd_rules_java_codesize.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... -* [ModifiedCyclomaticComplexity](pmd_rules_java_codesize.html#modifiedcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... * [ExcessivePublicCount](pmd_rules_java_codesize.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... -* [TooManyFields](pmd_rules_java_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... +* [ModifiedCyclomaticComplexity](pmd_rules_java_codesize.html#modifiedcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [NcssConstructorCount](pmd_rules_java_codesize.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssMethodCount](pmd_rules_java_codesize.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssTypeCount](pmd_rules_java_codesize.html#ncsstypecount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... -* [NcssConstructorCount](pmd_rules_java_codesize.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NPathComplexity](pmd_rules_java_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [StdCyclomaticComplexity](pmd_rules_java_codesize.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [TooManyFields](pmd_rules_java_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... * [TooManyMethods](pmd_rules_java_codesize.html#toomanymethods): A class with too many methods is probably a good suspect for refactoring, in order to reduce its ... ## Comments -* [CommentRequired](pmd_rules_java_comments.html#commentrequired): Denotes whether comments are required (or unwanted) for specific language elements. -* [CommentSize](pmd_rules_java_comments.html#commentsize): Determines whether the dimensions of non-header comments found are within the specified limits. * [CommentContent](pmd_rules_java_comments.html#commentcontent): A rule for the politically correct... we don't want to offend anyone. * [CommentDefaultAccessModifier](pmd_rules_java_comments.html#commentdefaultaccessmodifier): To avoid mistakes if we want that a Method, Field or Nested class have a default access modifier ... +* [CommentRequired](pmd_rules_java_comments.html#commentrequired): Denotes whether comments are required (or unwanted) for specific language elements. +* [CommentSize](pmd_rules_java_comments.html#commentsize): Determines whether the dimensions of non-header comments found are within the specified limits. ## Controversial -* [UnnecessaryConstructor](pmd_rules_java_controversial.html#unnecessaryconstructor): This rule detects when a constructor is not necessary; i.e., when there is only one constructor,i... -* [NullAssignment](pmd_rules_java_controversial.html#nullassignment): Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, th... -* [OnlyOneReturn](pmd_rules_java_controversial.html#onlyonereturn): A method should have only one exit point, and that should be the last statement in the method. * [AssignmentInOperand](pmd_rules_java_controversial.html#assignmentinoperand): Avoid assignments in operands; this can make code more complicated and harder to read. * [AtLeastOneConstructor](pmd_rules_java_controversial.html#atleastoneconstructor): Each class should declare at least one constructor. -* [DontImportSun](pmd_rules_java_controversial.html#dontimportsun): Avoid importing anything from the 'sun.' packages. These packages are not portable and are likel... -* [SuspiciousOctalEscape](pmd_rules_java_controversial.html#suspiciousoctalescape): A suspicious octal escape sequence was found inside a String literal.The Java language specificat... -* [CallSuperInConstructor](pmd_rules_java_controversial.html#callsuperinconstructor): It is a good practice to call super() in a constructor. If super() is not called butanother const... -* [UnnecessaryParentheses](pmd_rules_java_controversial.html#unnecessaryparentheses): Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. -* [DefaultPackage](pmd_rules_java_controversial.html#defaultpackage): Use explicit scoping instead of accidental usage of default package private level.The rule allows... -* [DataflowAnomalyAnalysis](pmd_rules_java_controversial.html#dataflowanomalyanalysis): The dataflow analysis tracks local definitions, undefinitions and references to variables on diff... +* [AvoidAccessibilityAlteration](pmd_rules_java_controversial.html#avoidaccessibilityalteration): Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(),as... * [AvoidFinalLocalVariable](pmd_rules_java_controversial.html#avoidfinallocalvariable): Avoid using final local variables, turn them into fields. +* [AvoidLiteralsInIfCondition](pmd_rules_java_controversial.html#avoidliteralsinifcondition): Avoid using hard-coded literals in conditional statements. By declaring them as static variableso... +* [AvoidPrefixingMethodParameters](pmd_rules_java_controversial.html#avoidprefixingmethodparameters): Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readab... +* [AvoidUsingNativeCode](pmd_rules_java_controversial.html#avoidusingnativecode): Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portabilit... * [AvoidUsingShortType](pmd_rules_java_controversial.html#avoidusingshorttype): Java uses the 'short' type to reduce memory usage, not to optimize calculation. In fact, the JVM ... * [AvoidUsingVolatile](pmd_rules_java_controversial.html#avoidusingvolatile): Use of the keyword 'volatile' is generally used to fine tune a Java application, and therefore, r... -* [AvoidUsingNativeCode](pmd_rules_java_controversial.html#avoidusingnativecode): Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portabilit... -* [AvoidAccessibilityAlteration](pmd_rules_java_controversial.html#avoidaccessibilityalteration): Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and setAccessible(),as... +* [CallSuperInConstructor](pmd_rules_java_controversial.html#callsuperinconstructor): It is a good practice to call super() in a constructor. If super() is not called butanother const... +* [DataflowAnomalyAnalysis](pmd_rules_java_controversial.html#dataflowanomalyanalysis): The dataflow analysis tracks local definitions, undefinitions and references to variables on diff... +* [DefaultPackage](pmd_rules_java_controversial.html#defaultpackage): Use explicit scoping instead of accidental usage of default package private level.The rule allows... * [DoNotCallGarbageCollectionExplicitly](pmd_rules_java_controversial.html#donotcallgarbagecollectionexplicitly): Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised. Co... +* [DontImportSun](pmd_rules_java_controversial.html#dontimportsun): Avoid importing anything from the 'sun.' packages. These packages are not portable and are likel... +* [NullAssignment](pmd_rules_java_controversial.html#nullassignment): Assigning a "null" to a variable (outside of its declaration) is usually bad form. Sometimes, th... * [OneDeclarationPerLine](pmd_rules_java_controversial.html#onedeclarationperline): Java allows the use of several variables declaration of the same type on one line. However, itcan... -* [AvoidPrefixingMethodParameters](pmd_rules_java_controversial.html#avoidprefixingmethodparameters): Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and reduces code readab... -* [AvoidLiteralsInIfCondition](pmd_rules_java_controversial.html#avoidliteralsinifcondition): Avoid using hard-coded literals in conditional statements. By declaring them as static variableso... -* [UseObjectForClearerAPI](pmd_rules_java_controversial.html#useobjectforclearerapi): When you write a public method, you should be thinking in terms of an API. If your method is publ... +* [OnlyOneReturn](pmd_rules_java_controversial.html#onlyonereturn): A method should have only one exit point, and that should be the last statement in the method. +* [SuspiciousOctalEscape](pmd_rules_java_controversial.html#suspiciousoctalescape): A suspicious octal escape sequence was found inside a String literal.The Java language specificat... +* [UnnecessaryConstructor](pmd_rules_java_controversial.html#unnecessaryconstructor): This rule detects when a constructor is not necessary; i.e., when there is only one constructor,i... +* [UnnecessaryParentheses](pmd_rules_java_controversial.html#unnecessaryparentheses): Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. * [UseConcurrentHashMap](pmd_rules_java_controversial.html#useconcurrenthashmap): Since Java5 brought a new implementation of the Map designed for multi-threaded access, you canpe... +* [UseObjectForClearerAPI](pmd_rules_java_controversial.html#useobjectforclearerapi): When you write a public method, you should be thinking in terms of an API. If your method is publ... ## Coupling * [CouplingBetweenObjects](pmd_rules_java_coupling.html#couplingbetweenobjects): This rule counts the number of unique attributes, local variables, and return types within an obj... * [ExcessiveImports](pmd_rules_java_coupling.html#excessiveimports): A high number of imports can indicate a high degree of coupling within an object. This rule count... +* [LawOfDemeter](pmd_rules_java_coupling.html#lawofdemeter): The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce couplin... * [LooseCoupling](pmd_rules_java_coupling.html#loosecoupling): The use of implementation types as object references limits your ability to use alternateimplemen... * [LoosePackageCoupling](pmd_rules_java_coupling.html#loosepackagecoupling): Avoid using classes from the configured package hierarchy outside of the package hierarchy, excep... -* [LawOfDemeter](pmd_rules_java_coupling.html#lawofdemeter): The Law of Demeter is a simple rule, that says "only talk to friends". It helps to reduce couplin... ## Design -* [UseUtilityClass](pmd_rules_java_design.html#useutilityclass): For classes that only have static methods, consider making them utility classes.Note that this do... -* [SimplifyBooleanReturns](pmd_rules_java_design.html#simplifybooleanreturns): Avoid unnecessary if-then-else statements when returning a boolean. The result ofthe conditional ... -* [SimplifyBooleanExpressions](pmd_rules_java_design.html#simplifybooleanexpressions): Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. -* [SwitchStmtsShouldHaveDefault](pmd_rules_java_design.html#switchstmtsshouldhavedefault): All switch statements should include a default option to catch any unspecified values. +* [AbstractClassWithoutAbstractMethod](pmd_rules_java_design.html#abstractclasswithoutabstractmethod): The abstract class does not contain any abstract methods. An abstract class suggestsan incomplete... +* [AbstractClassWithoutAnyMethod](pmd_rules_java_design.html#abstractclasswithoutanymethod): If an abstract class does not provides any methods, it may be acting as a simple data containerth... +* [AccessorClassGeneration](pmd_rules_java_design.html#accessorclassgeneration): Instantiation by way of private constructors from outside of the constructor's class often causes... +* [AccessorMethodGeneration](pmd_rules_java_design.html#accessormethodgeneration): When accessing a private field / method from another class, the Java compiler will generate a acc... +* [AssignmentToNonFinalStatic](pmd_rules_java_design.html#assignmenttononfinalstatic): Identifies a possible unsafe usage of a static field. * [AvoidDeeplyNestedIfStmts](pmd_rules_java_design.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... +* [AvoidInstanceofChecksInCatchClause](pmd_rules_java_design.html#avoidinstanceofchecksincatchclause): Each caught exception type should be handled in its own catch clause. +* [AvoidProtectedFieldInFinalClass](pmd_rules_java_design.html#avoidprotectedfieldinfinalclass): Do not use protected fields in final classes since they cannot be subclassed.Clarify your intent ... +* [AvoidProtectedMethodInFinalClassNotExtending](pmd_rules_java_design.html#avoidprotectedmethodinfinalclassnotextending): Do not use protected methods in most final classes since they cannot be subclassed. This shouldon... * [AvoidReassigningParameters](pmd_rules_java_design.html#avoidreassigningparameters): Reassigning values to incoming parameters is not recommended. Use temporary local variables inst... -* [SwitchDensity](pmd_rules_java_design.html#switchdensity): A high ratio of statements to labels in a switch statement implies that the switch statementis ov... -* [ConstructorCallsOverridableMethod](pmd_rules_java_design.html#constructorcallsoverridablemethod): Calling overridable methods during construction poses a risk of invoking methods on an incomplete... -* [AccessorClassGeneration](pmd_rules_java_design.html#accessorclassgeneration): Instantiation by way of private constructors from outside of the constructor's class often causes... -* [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic): If a final field is assigned to a compile-time constant, it could be made static, thus saving ove... +* [AvoidSynchronizedAtMethodLevel](pmd_rules_java_design.html#avoidsynchronizedatmethodlevel): Method-level synchronization can cause problems when new code is added to the method.Block-level ... +* [BadComparison](pmd_rules_java_design.html#badcomparison): Avoid equality comparisons with Double.NaN. Due to the implicit lack of representationprecision w... +* [ClassWithOnlyPrivateConstructorsShouldBeFinal](pmd_rules_java_design.html#classwithonlyprivateconstructorsshouldbefinal): A class with only private constructors should be final, unless the private constructoris invoked ... * [CloseResource](pmd_rules_java_design.html#closeresource): Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after... -* [NonStaticInitializer](pmd_rules_java_design.html#nonstaticinitializer): A non-static initializer block will be called any time a constructor is invoked (just prior toinv... +* [CompareObjectsWithEquals](pmd_rules_java_design.html#compareobjectswithequals): Use equals() to compare object references; avoid comparing them with ==. +* [ConfusingTernary](pmd_rules_java_design.html#confusingternary): Avoid negation within an "if" expression with an "else" clause. For example, rephrase: if (x !=... +* [ConstantsInInterface](pmd_rules_java_design.html#constantsininterface): Avoid constants in interfaces. Interfaces should define types, constants are implementation detai... +* [ConstructorCallsOverridableMethod](pmd_rules_java_design.html#constructorcallsoverridablemethod): Calling overridable methods during construction poses a risk of invoking methods on an incomplete... * [DefaultLabelNotLastInSwitchStmt](pmd_rules_java_design.html#defaultlabelnotlastinswitchstmt): By convention, the default label should be the last label in a switch statement. -* [NonCaseLabelInSwitchStatement](pmd_rules_java_design.html#noncaselabelinswitchstatement): A non-case label (e.g. a named break/continue label) was present in a switch statement.This legal... -* [OptimizableToArrayCall](pmd_rules_java_design.html#optimizabletoarraycall): Calls to a collection's toArray() method should specify target arrays sized to match the size of ... -* [BadComparison](pmd_rules_java_design.html#badcomparison): Avoid equality comparisons with Double.NaN. Due to the implicit lack of representationprecision w... +* [EmptyMethodInAbstractClassShouldBeAbstract](pmd_rules_java_design.html#emptymethodinabstractclassshouldbeabstract): Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to ... * [EqualsNull](pmd_rules_java_design.html#equalsnull): Tests for null should not use the equals() method. The '==' operator should be used instead. -* [ConfusingTernary](pmd_rules_java_design.html#confusingternary): Avoid negation within an "if" expression with an "else" clause. For example, rephrase: if (x !=... -* [InstantiationToGetClass](pmd_rules_java_design.html#instantiationtogetclass): Avoid instantiating an object just to call getClass() on it; use the .class public member instead. +* [FieldDeclarationsShouldBeAtStartOfClass](pmd_rules_java_design.html#fielddeclarationsshouldbeatstartofclass): Fields should be declared at the top of the class, before any method declarations, constructors, ... +* [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic): If a final field is assigned to a compile-time constant, it could be made static, thus saving ove... +* [GodClass](pmd_rules_java_design.html#godclass): The God Class rule detects the God Class design flaw using metrics. God classes do too many thing... * [IdempotentOperations](pmd_rules_java_design.html#idempotentoperations): Avoid idempotent operations - they have no effect. -* [SimpleDateFormatNeedsLocale](pmd_rules_java_design.html#simpledateformatneedslocale): Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-approp... * [ImmutableField](pmd_rules_java_design.html#immutablefield): Identifies private fields whose values never change once they are initialized either in the decla... -* [UseLocaleWithCaseConversions](pmd_rules_java_design.html#uselocalewithcaseconversions): When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with la... -* [AvoidProtectedFieldInFinalClass](pmd_rules_java_design.html#avoidprotectedfieldinfinalclass): Do not use protected fields in final classes since they cannot be subclassed.Clarify your intent ... -* [AssignmentToNonFinalStatic](pmd_rules_java_design.html#assignmenttononfinalstatic): Identifies a possible unsafe usage of a static field. -* [MissingStaticMethodInNonInstantiatableClass](pmd_rules_java_design.html#missingstaticmethodinnoninstantiatableclass): A class that has private constructors and does not have any static methods or fields cannot be used. -* [AvoidSynchronizedAtMethodLevel](pmd_rules_java_design.html#avoidsynchronizedatmethodlevel): Method-level synchronization can cause problems when new code is added to the method.Block-level ... +* [InstantiationToGetClass](pmd_rules_java_design.html#instantiationtogetclass): Avoid instantiating an object just to call getClass() on it; use the .class public member instead. +* [LogicInversion](pmd_rules_java_design.html#logicinversion): Use opposite operator instead of negating the whole expression with a logic complement operator. * [MissingBreakInSwitch](pmd_rules_java_design.html#missingbreakinswitch): Switch statements without break or return statements for each case optionmay indicate problematic... -* [UseNotifyAllInsteadOfNotify](pmd_rules_java_design.html#usenotifyallinsteadofnotify): Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, th... -* [AvoidInstanceofChecksInCatchClause](pmd_rules_java_design.html#avoidinstanceofchecksincatchclause): Each caught exception type should be handled in its own catch clause. -* [AbstractClassWithoutAbstractMethod](pmd_rules_java_design.html#abstractclasswithoutabstractmethod): The abstract class does not contain any abstract methods. An abstract class suggestsan incomplete... -* [SimplifyConditional](pmd_rules_java_design.html#simplifyconditional): No need to check for null before an instanceof; the instanceof keyword returns false when given a... -* [CompareObjectsWithEquals](pmd_rules_java_design.html#compareobjectswithequals): Use equals() to compare object references; avoid comparing them with ==. -* [PositionLiteralsFirstInComparisons](pmd_rules_java_design.html#positionliteralsfirstincomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... -* [PositionLiteralsFirstInCaseInsensitiveComparisons](pmd_rules_java_design.html#positionliteralsfirstincaseinsensitivecomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... -* [UnnecessaryLocalBeforeReturn](pmd_rules_java_design.html#unnecessarylocalbeforereturn): Avoid the creation of unnecessary local variables +* [MissingStaticMethodInNonInstantiatableClass](pmd_rules_java_design.html#missingstaticmethodinnoninstantiatableclass): A class that has private constructors and does not have any static methods or fields cannot be used. +* [NonCaseLabelInSwitchStatement](pmd_rules_java_design.html#noncaselabelinswitchstatement): A non-case label (e.g. a named break/continue label) was present in a switch statement.This legal... +* [NonStaticInitializer](pmd_rules_java_design.html#nonstaticinitializer): A non-static initializer block will be called any time a constructor is invoked (just prior toinv... * [NonThreadSafeSingleton](pmd_rules_java_design.html#nonthreadsafesingleton): Non-thread safe singletons can result in bad state changes. Eliminatestatic singletons if possibl... +* [OptimizableToArrayCall](pmd_rules_java_design.html#optimizabletoarraycall): Calls to a collection's toArray() method should specify target arrays sized to match the size of ... +* [PositionLiteralsFirstInCaseInsensitiveComparisons](pmd_rules_java_design.html#positionliteralsfirstincaseinsensitivecomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... +* [PositionLiteralsFirstInComparisons](pmd_rules_java_design.html#positionliteralsfirstincomparisons): Position literals first in comparisons, if the second argument is null then NullPointerExceptions... +* [PreserveStackTrace](pmd_rules_java_design.html#preservestacktrace): Throwing a new exception from a catch block without passing the original exception into thenew ex... +* [ReturnEmptyArrayRatherThanNull](pmd_rules_java_design.html#returnemptyarrayratherthannull): For any method that returns an array, it is a better to return an empty array rather than anull r... +* [SimpleDateFormatNeedsLocale](pmd_rules_java_design.html#simpledateformatneedslocale): Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-approp... +* [SimplifyBooleanExpressions](pmd_rules_java_design.html#simplifybooleanexpressions): Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. +* [SimplifyBooleanReturns](pmd_rules_java_design.html#simplifybooleanreturns): Avoid unnecessary if-then-else statements when returning a boolean. The result ofthe conditional ... +* [SimplifyConditional](pmd_rules_java_design.html#simplifyconditional): No need to check for null before an instanceof; the instanceof keyword returns false when given a... * [SingleMethodSingleton](pmd_rules_java_design.html#singlemethodsingleton): Some classes contain overloaded getInstance. The problem with overloaded getInstance methodsis th... * [SingletonClassReturningNewInstance](pmd_rules_java_design.html#singletonclassreturningnewinstance): Some classes contain overloaded getInstance. The problem with overloaded getInstance methodsis th... -* [UncommentedEmptyMethodBody](pmd_rules_java_design.html#uncommentedemptymethodbody): Uncommented Empty Method Body finds instances where a method body does not containstatements, but... +* [SingularField](pmd_rules_java_design.html#singularfield): Fields whose scopes are limited to just single methods do not rely on the containingobject to pro... +* [SwitchDensity](pmd_rules_java_design.html#switchdensity): A high ratio of statements to labels in a switch statement implies that the switch statementis ov... +* [SwitchStmtsShouldHaveDefault](pmd_rules_java_design.html#switchstmtsshouldhavedefault): All switch statements should include a default option to catch any unspecified values. +* [TooFewBranchesForASwitchStatement](pmd_rules_java_design.html#toofewbranchesforaswitchstatement): Switch statements are indended to be used to support complex branching behaviour. Using a switch ... * [UncommentedEmptyConstructor](pmd_rules_java_design.html#uncommentedemptyconstructor): Uncommented Empty Constructor finds instances where a constructor does notcontain statements, but... +* [UncommentedEmptyMethodBody](pmd_rules_java_design.html#uncommentedemptymethodbody): Uncommented Empty Method Body finds instances where a method body does not containstatements, but... +* [UnnecessaryLocalBeforeReturn](pmd_rules_java_design.html#unnecessarylocalbeforereturn): Avoid the creation of unnecessary local variables * [UnsynchronizedStaticDateFormatter](pmd_rules_java_design.html#unsynchronizedstaticdateformatter): SimpleDateFormat instances are not synchronized. Sun recommends using separate format instancesfo... -* [PreserveStackTrace](pmd_rules_java_design.html#preservestacktrace): Throwing a new exception from a catch block without passing the original exception into thenew ex... * [UseCollectionIsEmpty](pmd_rules_java_design.html#usecollectionisempty): The isEmpty() method on java.util.Collection is provided to determine if a collection has any ele... -* [ClassWithOnlyPrivateConstructorsShouldBeFinal](pmd_rules_java_design.html#classwithonlyprivateconstructorsshouldbefinal): A class with only private constructors should be final, unless the private constructoris invoked ... -* [EmptyMethodInAbstractClassShouldBeAbstract](pmd_rules_java_design.html#emptymethodinabstractclassshouldbeabstract): Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to ... -* [SingularField](pmd_rules_java_design.html#singularfield): Fields whose scopes are limited to just single methods do not rely on the containingobject to pro... -* [ReturnEmptyArrayRatherThanNull](pmd_rules_java_design.html#returnemptyarrayratherthannull): For any method that returns an array, it is a better to return an empty array rather than anull r... -* [AbstractClassWithoutAnyMethod](pmd_rules_java_design.html#abstractclasswithoutanymethod): If an abstract class does not provides any methods, it may be acting as a simple data containerth... -* [TooFewBranchesForASwitchStatement](pmd_rules_java_design.html#toofewbranchesforaswitchstatement): Switch statements are indended to be used to support complex branching behaviour. Using a switch ... -* [LogicInversion](pmd_rules_java_design.html#logicinversion): Use opposite operator instead of negating the whole expression with a logic complement operator. +* [UseLocaleWithCaseConversions](pmd_rules_java_design.html#uselocalewithcaseconversions): When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with la... +* [UseNotifyAllInsteadOfNotify](pmd_rules_java_design.html#usenotifyallinsteadofnotify): Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, th... +* [UseUtilityClass](pmd_rules_java_design.html#useutilityclass): For classes that only have static methods, consider making them utility classes.Note that this do... * [UseVarargs](pmd_rules_java_design.html#usevarargs): Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic... -* [FieldDeclarationsShouldBeAtStartOfClass](pmd_rules_java_design.html#fielddeclarationsshouldbeatstartofclass): Fields should be declared at the top of the class, before any method declarations, constructors, ... -* [GodClass](pmd_rules_java_design.html#godclass): The God Class rule detects the God Class design flaw using metrics. God classes do too many thing... -* [AvoidProtectedMethodInFinalClassNotExtending](pmd_rules_java_design.html#avoidprotectedmethodinfinalclassnotextending): Do not use protected methods in most final classes since they cannot be subclassed. This shouldon... -* [ConstantsInInterface](pmd_rules_java_design.html#constantsininterface): Avoid constants in interfaces. Interfaces should define types, constants are implementation detai... -* [AccessorMethodGeneration](pmd_rules_java_design.html#accessormethodgeneration): When accessing a private field / method from another class, the Java compiler will generate a acc... ## Empty Code * [EmptyCatchBlock](pmd_rules_java_empty.html#emptycatchblock): Empty Catch Block finds instances where an exception is caught, but nothing is done. In most cir... -* [EmptyIfStmt](pmd_rules_java_empty.html#emptyifstmt): Empty If Statement finds instances where a condition is checked but nothing is done about it. -* [EmptyWhileStmt](pmd_rules_java_empty.html#emptywhilestmt): Empty While Statement finds all instances where a while statement does nothing. If it is a timin... -* [EmptyTryBlock](pmd_rules_java_empty.html#emptytryblock): Avoid empty try blocks - what's the point? * [EmptyFinallyBlock](pmd_rules_java_empty.html#emptyfinallyblock): Empty finally blocks serve no purpose and should be removed. -* [EmptySwitchStatements](pmd_rules_java_empty.html#emptyswitchstatements): Empty switch statements serve no purpose and should be removed. -* [EmptySynchronizedBlock](pmd_rules_java_empty.html#emptysynchronizedblock): Empty synchronized blocks serve no purpose and should be removed. -* [EmptyStatementNotInLoop](pmd_rules_java_empty.html#emptystatementnotinloop): An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' or 'wh... +* [EmptyIfStmt](pmd_rules_java_empty.html#emptyifstmt): Empty If Statement finds instances where a condition is checked but nothing is done about it. * [EmptyInitializer](pmd_rules_java_empty.html#emptyinitializer): Empty initializers serve no purpose and should be removed. * [EmptyStatementBlock](pmd_rules_java_empty.html#emptystatementblock): Empty block statements serve no purpose and should be removed. +* [EmptyStatementNotInLoop](pmd_rules_java_empty.html#emptystatementnotinloop): An empty statement (or a semicolon by itself) that is not used as the sole body of a 'for' or 'wh... * [EmptyStaticInitializer](pmd_rules_java_empty.html#emptystaticinitializer): An empty static initializer serve no purpose and should be removed. +* [EmptySwitchStatements](pmd_rules_java_empty.html#emptyswitchstatements): Empty switch statements serve no purpose and should be removed. +* [EmptySynchronizedBlock](pmd_rules_java_empty.html#emptysynchronizedblock): Empty synchronized blocks serve no purpose and should be removed. +* [EmptyTryBlock](pmd_rules_java_empty.html#emptytryblock): Avoid empty try blocks - what's the point? +* [EmptyWhileStmt](pmd_rules_java_empty.html#emptywhilestmt): Empty While Statement finds all instances where a while statement does nothing. If it is a timin... ## Finalizer +* [AvoidCallingFinalize](pmd_rules_java_finalizers.html#avoidcallingfinalize): The method Object.finalize() is called by the garbage collector on an object when garbage collect... * [EmptyFinalizer](pmd_rules_java_finalizers.html#emptyfinalizer): Empty finalize methods serve no purpose and should be removed. +* [FinalizeDoesNotCallSuperFinalize](pmd_rules_java_finalizers.html#finalizedoesnotcallsuperfinalize): If the finalize() is implemented, its last action should be to call super.finalize. * [FinalizeOnlyCallsSuperFinalize](pmd_rules_java_finalizers.html#finalizeonlycallssuperfinalize): If the finalize() is implemented, it should do something besides just calling super.finalize(). * [FinalizeOverloaded](pmd_rules_java_finalizers.html#finalizeoverloaded): Methods named finalize() should not have parameters. It is confusing and most likely an attempt ... -* [FinalizeDoesNotCallSuperFinalize](pmd_rules_java_finalizers.html#finalizedoesnotcallsuperfinalize): If the finalize() is implemented, its last action should be to call super.finalize. * [FinalizeShouldBeProtected](pmd_rules_java_finalizers.html#finalizeshouldbeprotected): When overriding the finalize(), the new method should be set as protected. If made public, other... -* [AvoidCallingFinalize](pmd_rules_java_finalizers.html#avoidcallingfinalize): The method Object.finalize() is called by the garbage collector on an object when garbage collect... ## Import Statements -* [DuplicateImports](pmd_rules_java_imports.html#duplicateimports): Duplicate or overlapping import statements should be avoided. * [DontImportJavaLang](pmd_rules_java_imports.html#dontimportjavalang): Avoid importing anything from the package 'java.lang'. These classes are automatically imported ... -* [UnusedImports](pmd_rules_java_imports.html#unusedimports): Avoid the use of unused import statements to prevent unwanted dependencies. +* [DuplicateImports](pmd_rules_java_imports.html#duplicateimports): Duplicate or overlapping import statements should be avoided. * [ImportFromSamePackage](pmd_rules_java_imports.html#importfromsamepackage): There is no need to import a type that lives in the same package. * [TooManyStaticImports](pmd_rules_java_imports.html#toomanystaticimports): If you overuse the static import feature, it can make your program unreadable and unmaintainable,... * [UnnecessaryFullyQualifiedName](pmd_rules_java_imports.html#unnecessaryfullyqualifiedname): Import statements allow the use of non-fully qualified names. The use of a fully qualified namew... +* [UnusedImports](pmd_rules_java_imports.html#unusedimports): Avoid the use of unused import statements to prevent unwanted dependencies. ## J2EE -* [UseProperClassLoader](pmd_rules_java_j2ee.html#useproperclassloader): In J2EE, the getClassLoader() method might not work as expected. Use Thread.currentThread().getCo... -* [MDBAndSessionBeanNamingConvention](pmd_rules_java_j2ee.html#mdbandsessionbeannamingconvention): The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. -* [RemoteSessionInterfaceNamingConvention](pmd_rules_java_j2ee.html#remotesessioninterfacenamingconvention): A Remote Home interface type of a Session EJB should be suffixed by 'Home'. -* [LocalInterfaceSessionNamingConvention](pmd_rules_java_j2ee.html#localinterfacesessionnamingconvention): The Local Interface of a Session EJB should be suffixed by 'Local'. +* [DoNotCallSystemExit](pmd_rules_java_j2ee.html#donotcallsystemexit): Web applications should not call System.exit(), since only the web container or theapplication se... +* [DoNotUseThreads](pmd_rules_java_j2ee.html#donotusethreads): The J2EE specification explicitly forbids the use of threads. * [LocalHomeNamingConvention](pmd_rules_java_j2ee.html#localhomenamingconvention): The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. +* [LocalInterfaceSessionNamingConvention](pmd_rules_java_j2ee.html#localinterfacesessionnamingconvention): The Local Interface of a Session EJB should be suffixed by 'Local'. +* [MDBAndSessionBeanNamingConvention](pmd_rules_java_j2ee.html#mdbandsessionbeannamingconvention): The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. * [RemoteInterfaceNamingConvention](pmd_rules_java_j2ee.html#remoteinterfacenamingconvention): Remote Interface of a Session EJB should not have a suffix. -* [DoNotCallSystemExit](pmd_rules_java_j2ee.html#donotcallsystemexit): Web applications should not call System.exit(), since only the web container or theapplication se... +* [RemoteSessionInterfaceNamingConvention](pmd_rules_java_j2ee.html#remotesessioninterfacenamingconvention): A Remote Home interface type of a Session EJB should be suffixed by 'Home'. * [StaticEJBFieldShouldBeFinal](pmd_rules_java_j2ee.html#staticejbfieldshouldbefinal): According to the J2EE specification, an EJB should not have any static fieldswith write access. H... -* [DoNotUseThreads](pmd_rules_java_j2ee.html#donotusethreads): The J2EE specification explicitly forbids the use of threads. +* [UseProperClassLoader](pmd_rules_java_j2ee.html#useproperclassloader): In J2EE, the getClassLoader() method might not work as expected. Use Thread.currentThread().getCo... ## Jakarta Commons Logging -* [UseCorrectExceptionLogging](pmd_rules_java_logging-jakarta-commons.html#usecorrectexceptionlogging): To make sure the full stacktrace is printed out, use the logging statement with two arguments: a ... -* [ProperLogger](pmd_rules_java_logging-jakarta-commons.html#properlogger): A logger should normally be defined private static final and be associated with the correct class... * [GuardDebugLogging](pmd_rules_java_logging-jakarta-commons.html#guarddebuglogging): When log messages are composed by concatenating strings, the whole section should be guarded ... * [GuardLogStatement](pmd_rules_java_logging-jakarta-commons.html#guardlogstatement): Whenever using a log level, one should check if the loglevel is actually enabled, orotherwise ski... +* [ProperLogger](pmd_rules_java_logging-jakarta-commons.html#properlogger): A logger should normally be defined private static final and be associated with the correct class... +* [UseCorrectExceptionLogging](pmd_rules_java_logging-jakarta-commons.html#usecorrectexceptionlogging): To make sure the full stacktrace is printed out, use the logging statement with two arguments: a ... ## Java Logging -* [MoreThanOneLogger](pmd_rules_java_logging-java.html#morethanonelogger): Normally only one logger is used in each class. -* [LoggerIsNotStaticFinal](pmd_rules_java_logging-java.html#loggerisnotstaticfinal): In most cases, the Logger reference can be declared as static and final. -* [SystemPrintln](pmd_rules_java_logging-java.html#systemprintln): References to System.(out\|err).print are usually intended for debugging purposes and can remain ... * [AvoidPrintStackTrace](pmd_rules_java_logging-java.html#avoidprintstacktrace): Avoid printStackTrace(); use a logger call instead. * [GuardLogStatementJavaUtil](pmd_rules_java_logging-java.html#guardlogstatementjavautil): Whenever using a log level, one should check if the loglevel is actually enabled, orotherwise ski... * [InvalidSlf4jMessageFormat](pmd_rules_java_logging-java.html#invalidslf4jmessageformat): Check for messages in slf4j loggers with non matching number of arguments and placeholders. +* [LoggerIsNotStaticFinal](pmd_rules_java_logging-java.html#loggerisnotstaticfinal): In most cases, the Logger reference can be declared as static and final. +* [MoreThanOneLogger](pmd_rules_java_logging-java.html#morethanonelogger): Normally only one logger is used in each class. +* [SystemPrintln](pmd_rules_java_logging-java.html#systemprintln): References to System.(out\|err).print are usually intended for debugging purposes and can remain ... ## JavaBeans * [BeanMembersShouldSerialize](pmd_rules_java_javabeans.html#beanmembersshouldserialize): If a class is a bean, or is referenced by a bean directly or indirectly it needs to be serializab... * [MissingSerialVersionUID](pmd_rules_java_javabeans.html#missingserialversionuid): Serializable classes should provide a serialVersionUID field. ## JUnit -* [JUnitStaticSuite](pmd_rules_java_junit.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static. -* [JUnitSpelling](pmd_rules_java_junit.html#junitspelling): Some JUnit framework methods are easy to misspell. * [JUnitAssertionsShouldIncludeMessage](pmd_rules_java_junit.html#junitassertionsshouldincludemessage): JUnit assertions should include an informative message - i.e., use the three-argument version of ... +* [JUnitSpelling](pmd_rules_java_junit.html#junitspelling): Some JUnit framework methods are easy to misspell. +* [JUnitStaticSuite](pmd_rules_java_junit.html#junitstaticsuite): The suite() method in a JUnit test needs to be both public and static. +* [JUnitTestContainsTooManyAsserts](pmd_rules_java_junit.html#junittestcontainstoomanyasserts): JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, ... * [JUnitTestsShouldIncludeAssert](pmd_rules_java_junit.html#junittestsshouldincludeassert): JUnit tests should include at least one assertion. This makes the tests more robust, and using a... +* [SimplifyBooleanAssertion](pmd_rules_java_junit.html#simplifybooleanassertion): Avoid negation in an assertTrue or assertFalse test.For example, rephrase: assertTrue(!expr); ... * [TestClassWithoutTestCases](pmd_rules_java_junit.html#testclasswithouttestcases): Test classes end with the suffix Test. Having a non-test class with that name is not a good pract... * [UnnecessaryBooleanAssertion](pmd_rules_java_junit.html#unnecessarybooleanassertion): A JUnit test assertion with a boolean literal is unnecessary since it always will evaluate to the... * [UseAssertEqualsInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertequalsinsteadofasserttrue): This rule detects JUnit assertions in object equality. These assertions should be made by more sp... -* [UseAssertSameInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertsameinsteadofasserttrue): This rule detects JUnit assertions in object references equality. These assertions should be made... * [UseAssertNullInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertnullinsteadofasserttrue): This rule detects JUnit assertions in object references equality. These assertions should be made... -* [SimplifyBooleanAssertion](pmd_rules_java_junit.html#simplifybooleanassertion): Avoid negation in an assertTrue or assertFalse test.For example, rephrase: assertTrue(!expr); ... -* [JUnitTestContainsTooManyAsserts](pmd_rules_java_junit.html#junittestcontainstoomanyasserts): JUnit tests should not contain too many asserts. Many asserts are indicative of a complex test, ... +* [UseAssertSameInsteadOfAssertTrue](pmd_rules_java_junit.html#useassertsameinsteadofasserttrue): This rule detects JUnit assertions in object references equality. These assertions should be made... * [UseAssertTrueInsteadOfAssertEquals](pmd_rules_java_junit.html#useasserttrueinsteadofassertequals): When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, ins... ## Migration -* [ReplaceVectorWithList](pmd_rules_java_migrating.html#replacevectorwithlist): Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe oper... -* [ReplaceHashtableWithMap](pmd_rules_java_migrating.html#replacehashtablewithmap): Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. -* [ReplaceEnumerationWithIterator](pmd_rules_java_migrating.html#replaceenumerationwithiterator): Consider replacing Enumeration usages with the newer java.util.Iterator -* [AvoidEnumAsIdentifier](pmd_rules_java_migrating.html#avoidenumasidentifier): Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. * [AvoidAssertAsIdentifier](pmd_rules_java_migrating.html#avoidassertasidentifier): Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. -* [IntegerInstantiation](pmd_rules_java_migrating.html#integerinstantiation): Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(... +* [AvoidEnumAsIdentifier](pmd_rules_java_migrating.html#avoidenumasidentifier): Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. * [ByteInstantiation](pmd_rules_java_migrating.html#byteinstantiation): Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf().It m... -* [ShortInstantiation](pmd_rules_java_migrating.html#shortinstantiation): Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf().It... -* [LongInstantiation](pmd_rules_java_migrating.html#longinstantiation): Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf().It m... -* [JUnit4TestShouldUseBeforeAnnotation](pmd_rules_java_migrating.html#junit4testshouldusebeforeannotation): In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUni... +* [IntegerInstantiation](pmd_rules_java_migrating.html#integerinstantiation): Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(... +* [JUnit4SuitesShouldUseSuiteAnnotation](pmd_rules_java_migrating.html#junit4suitesshouldusesuiteannotation): In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicatedthro... * [JUnit4TestShouldUseAfterAnnotation](pmd_rules_java_migrating.html#junit4testshoulduseafterannotation): In JUnit 3, the tearDown method was used to clean up all data entities required in running tests.... +* [JUnit4TestShouldUseBeforeAnnotation](pmd_rules_java_migrating.html#junit4testshouldusebeforeannotation): In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUni... * [JUnit4TestShouldUseTestAnnotation](pmd_rules_java_migrating.html#junit4testshouldusetestannotation): In JUnit 3, the framework executed all methods which started with the word test as a unit test. I... -* [JUnit4SuitesShouldUseSuiteAnnotation](pmd_rules_java_migrating.html#junit4suitesshouldusesuiteannotation): In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicatedthro... * [JUnitUseExpected](pmd_rules_java_migrating.html#junituseexpected): In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. +* [LongInstantiation](pmd_rules_java_migrating.html#longinstantiation): Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf().It m... +* [ReplaceEnumerationWithIterator](pmd_rules_java_migrating.html#replaceenumerationwithiterator): Consider replacing Enumeration usages with the newer java.util.Iterator +* [ReplaceHashtableWithMap](pmd_rules_java_migrating.html#replacehashtablewithmap): Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. +* [ReplaceVectorWithList](pmd_rules_java_migrating.html#replacevectorwithlist): Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe oper... +* [ShortInstantiation](pmd_rules_java_migrating.html#shortinstantiation): Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf().It... ## Naming -* [ShortVariable](pmd_rules_java_naming.html#shortvariable): Fields, local variables, or parameter names that are very short are not helpful to the reader. -* [LongVariable](pmd_rules_java_naming.html#longvariable): Fields, formal arguments, or local variable names that are too long can make the code difficult t... -* [ShortMethodName](pmd_rules_java_naming.html#shortmethodname): Method names that are very short are not helpful to the reader. -* [VariableNamingConventions](pmd_rules_java_naming.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... -* [MethodNamingConventions](pmd_rules_java_naming.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. -* [ClassNamingConventions](pmd_rules_java_naming.html#classnamingconventions): Class names should always begin with an upper case character. * [AbstractNaming](pmd_rules_java_naming.html#abstractnaming): Abstract classes should be named 'AbstractXXX'. * [AvoidDollarSigns](pmd_rules_java_naming.html#avoiddollarsigns): Avoid using dollar signs in variable/method/class/interface names. -* [MethodWithSameNameAsEnclosingClass](pmd_rules_java_naming.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. -* [SuspiciousHashcodeMethodName](pmd_rules_java_naming.html#suspicioushashcodemethodname): The method name and return type are suspiciously close to hashCode(), which may denote an intenti... -* [SuspiciousConstantFieldName](pmd_rules_java_naming.html#suspiciousconstantfieldname): Field names using all uppercase characters - Sun's Java naming conventions indicating constants -... -* [SuspiciousEqualsMethodName](pmd_rules_java_naming.html#suspiciousequalsmethodname): The method name and parameter number are suspiciously close to equals(Object), which can denote a... -* [AvoidFieldNameMatchingTypeName](pmd_rules_java_naming.html#avoidfieldnamematchingtypename): It is somewhat confusing to have a field name matching the declaring class name.This probably mea... * [AvoidFieldNameMatchingMethodName](pmd_rules_java_naming.html#avoidfieldnamematchingmethodname): It can be confusing to have a field name with the same name as a method. While this is permitted,... +* [AvoidFieldNameMatchingTypeName](pmd_rules_java_naming.html#avoidfieldnamematchingtypename): It is somewhat confusing to have a field name matching the declaring class name.This probably mea... +* [BooleanGetMethodName](pmd_rules_java_naming.html#booleangetmethodname): Methods that return boolean results should be named as predicate statements to denote this.I.e, '... +* [ClassNamingConventions](pmd_rules_java_naming.html#classnamingconventions): Class names should always begin with an upper case character. +* [GenericsNaming](pmd_rules_java_naming.html#genericsnaming): Names for references to generic values should be limited to a single uppercase letter. +* [LongVariable](pmd_rules_java_naming.html#longvariable): Fields, formal arguments, or local variable names that are too long can make the code difficult t... +* [MethodNamingConventions](pmd_rules_java_naming.html#methodnamingconventions): Method names should always begin with a lower case character, and should not contain underscores. +* [MethodWithSameNameAsEnclosingClass](pmd_rules_java_naming.html#methodwithsamenameasenclosingclass): Non-constructor methods should not have the same name as the enclosing class. +* [MisleadingVariableName](pmd_rules_java_naming.html#misleadingvariablename): Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could b... * [NoPackage](pmd_rules_java_naming.html#nopackage): Detects when a class or interface does not have a package definition. * [PackageCase](pmd_rules_java_naming.html#packagecase): Detects when a package definition contains uppercase characters. -* [MisleadingVariableName](pmd_rules_java_naming.html#misleadingvariablename): Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could b... -* [BooleanGetMethodName](pmd_rules_java_naming.html#booleangetmethodname): Methods that return boolean results should be named as predicate statements to denote this.I.e, '... * [ShortClassName](pmd_rules_java_naming.html#shortclassname): Short Classnames with fewer than e.g. five characters are not recommended. -* [GenericsNaming](pmd_rules_java_naming.html#genericsnaming): Names for references to generic values should be limited to a single uppercase letter. +* [ShortMethodName](pmd_rules_java_naming.html#shortmethodname): Method names that are very short are not helpful to the reader. +* [ShortVariable](pmd_rules_java_naming.html#shortvariable): Fields, local variables, or parameter names that are very short are not helpful to the reader. +* [SuspiciousConstantFieldName](pmd_rules_java_naming.html#suspiciousconstantfieldname): Field names using all uppercase characters - Sun's Java naming conventions indicating constants -... +* [SuspiciousEqualsMethodName](pmd_rules_java_naming.html#suspiciousequalsmethodname): The method name and parameter number are suspiciously close to equals(Object), which can denote a... +* [SuspiciousHashcodeMethodName](pmd_rules_java_naming.html#suspicioushashcodemethodname): The method name and return type are suspiciously close to hashCode(), which may denote an intenti... +* [VariableNamingConventions](pmd_rules_java_naming.html#variablenamingconventions): A variable naming conventions rule - customize this to your liking. Currently, itchecks for fina... ## Optimization +* [AddEmptyString](pmd_rules_java_optimizations.html#addemptystring): The conversion of literals to strings by concatenating them with empty strings is inefficient.It ... +* [AvoidArrayLoops](pmd_rules_java_optimizations.html#avoidarrayloops): Instead of manually copying data between two arrays, use the efficient System.arraycopy method in... +* [AvoidInstantiatingObjectsInLoops](pmd_rules_java_optimizations.html#avoidinstantiatingobjectsinloops): New objects created within loops should be checked to see if they can created outside them and re... * [LocalVariableCouldBeFinal](pmd_rules_java_optimizations.html#localvariablecouldbefinal): A local variable assigned only once can be declared final. * [MethodArgumentCouldBeFinal](pmd_rules_java_optimizations.html#methodargumentcouldbefinal): A method argument that is never re-assigned within the method can be declared final. -* [AvoidInstantiatingObjectsInLoops](pmd_rules_java_optimizations.html#avoidinstantiatingobjectsinloops): New objects created within loops should be checked to see if they can created outside them and re... -* [UseArrayListInsteadOfVector](pmd_rules_java_optimizations.html#usearraylistinsteadofvector): ArrayList is a much better Collection implementation than Vector if thread-safe operation is not ... +* [PrematureDeclaration](pmd_rules_java_optimizations.html#prematuredeclaration): Checks for variables that are defined before they might be used. A reference is deemed to be prem... +* [RedundantFieldInitializer](pmd_rules_java_optimizations.html#redundantfieldinitializer): Java will initialize fields with known default values so any explicit initialization of those sam... * [SimplifyStartsWith](pmd_rules_java_optimizations.html#simplifystartswith): Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (st... -* [UseStringBufferForStringAppends](pmd_rules_java_optimizations.html#usestringbufferforstringappends): The use of the '+=' operator for appending strings causes the JVM to create and use an internal S... -* [UseArraysAsList](pmd_rules_java_optimizations.html#usearraysaslist): The java.util.Arrays class has a "asList" method that should be used when you want to create a ne... -* [AvoidArrayLoops](pmd_rules_java_optimizations.html#avoidarrayloops): Instead of manually copying data between two arrays, use the efficient System.arraycopy method in... * [UnnecessaryWrapperObjectCreation](pmd_rules_java_optimizations.html#unnecessarywrapperobjectcreation): Most wrapper classes provide static conversion methods that avoid the need to create intermediate... -* [AddEmptyString](pmd_rules_java_optimizations.html#addemptystring): The conversion of literals to strings by concatenating them with empty strings is inefficient.It ... -* [RedundantFieldInitializer](pmd_rules_java_optimizations.html#redundantfieldinitializer): Java will initialize fields with known default values so any explicit initialization of those sam... -* [PrematureDeclaration](pmd_rules_java_optimizations.html#prematuredeclaration): Checks for variables that are defined before they might be used. A reference is deemed to be prem... +* [UseArrayListInsteadOfVector](pmd_rules_java_optimizations.html#usearraylistinsteadofvector): ArrayList is a much better Collection implementation than Vector if thread-safe operation is not ... +* [UseArraysAsList](pmd_rules_java_optimizations.html#usearraysaslist): The java.util.Arrays class has a "asList" method that should be used when you want to create a ne... +* [UseStringBufferForStringAppends](pmd_rules_java_optimizations.html#usestringbufferforstringappends): The use of the '+=' operator for appending strings causes the JVM to create and use an internal S... ## Security Code Guidelines -* [MethodReturnsInternalArray](pmd_rules_java_sunsecure.html#methodreturnsinternalarray): Exposing internal arrays to the caller violates object encapsulation since elements can be remove... * [ArrayIsStoredDirectly](pmd_rules_java_sunsecure.html#arrayisstoreddirectly): Constructors and methods receiving arrays should clone objects and store the copy.This prevents f... +* [MethodReturnsInternalArray](pmd_rules_java_sunsecure.html#methodreturnsinternalarray): Exposing internal arrays to the caller violates object encapsulation since elements can be remove... ## Strict Exceptions -* [AvoidCatchingThrowable](pmd_rules_java_strictexception.html#avoidcatchingthrowable): Catching Throwable errors is not recommended since its scope is very broad. It includes runtime i... -* [SignatureDeclareThrowsException](pmd_rules_java_strictexception.html#signaturedeclarethrowsexception): Methods that declare the generic Exception as a possible throwable are not very helpful since the... -* [ExceptionAsFlowControl](pmd_rules_java_strictexception.html#exceptionasflowcontrol): Using Exceptions as form of flow control is not recommended as they obscure true exceptions when ... +* [AvoidCatchingGenericException](pmd_rules_java_strictexception.html#avoidcatchinggenericexception): Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in tr... * [AvoidCatchingNPE](pmd_rules_java_strictexception.html#avoidcatchingnpe): Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide... -* [AvoidThrowingRawExceptionTypes](pmd_rules_java_strictexception.html#avoidthrowingrawexceptiontypes): Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable,Excep... -* [AvoidThrowingNullPointerException](pmd_rules_java_strictexception.html#avoidthrowingnullpointerexception): Avoid throwing NullPointerExceptions. These are confusing because most people will assume that th... +* [AvoidCatchingThrowable](pmd_rules_java_strictexception.html#avoidcatchingthrowable): Catching Throwable errors is not recommended since its scope is very broad. It includes runtime i... +* [AvoidLosingExceptionInformation](pmd_rules_java_strictexception.html#avoidlosingexceptioninformation): Statements in a catch block that invoke accessors on the exception without using the informationo... * [AvoidRethrowingException](pmd_rules_java_strictexception.html#avoidrethrowingexception): Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. +* [AvoidThrowingNewInstanceOfSameException](pmd_rules_java_strictexception.html#avoidthrowingnewinstanceofsameexception): Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same typ... +* [AvoidThrowingNullPointerException](pmd_rules_java_strictexception.html#avoidthrowingnullpointerexception): Avoid throwing NullPointerExceptions. These are confusing because most people will assume that th... +* [AvoidThrowingRawExceptionTypes](pmd_rules_java_strictexception.html#avoidthrowingrawexceptiontypes): Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable,Excep... * [DoNotExtendJavaLangError](pmd_rules_java_strictexception.html#donotextendjavalangerror): Errors are system exceptions. Do not extend them. * [DoNotThrowExceptionInFinally](pmd_rules_java_strictexception.html#donotthrowexceptioninfinally): Throwing exceptions within a 'finally' block is confusing since they may mask other exceptions or... -* [AvoidThrowingNewInstanceOfSameException](pmd_rules_java_strictexception.html#avoidthrowingnewinstanceofsameexception): Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same typ... -* [AvoidCatchingGenericException](pmd_rules_java_strictexception.html#avoidcatchinggenericexception): Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in tr... -* [AvoidLosingExceptionInformation](pmd_rules_java_strictexception.html#avoidlosingexceptioninformation): Statements in a catch block that invoke accessors on the exception without using the informationo... +* [ExceptionAsFlowControl](pmd_rules_java_strictexception.html#exceptionasflowcontrol): Using Exceptions as form of flow control is not recommended as they obscure true exceptions when ... +* [SignatureDeclareThrowsException](pmd_rules_java_strictexception.html#signaturedeclarethrowsexception): Methods that declare the generic Exception as a possible throwable are not very helpful since the... ## String and StringBuffer -* [AvoidDuplicateLiterals](pmd_rules_java_strings.html#avoidduplicateliterals): Code containing duplicate String literals can usually be improved by declaring the String as a co... -* [StringInstantiation](pmd_rules_java_strings.html#stringinstantiation): Avoid instantiating String objects; this is usually unnecessary since they are immutable and can ... -* [StringToString](pmd_rules_java_strings.html#stringtostring): Avoid calling toString() on objects already known to be string instances; this is unnecessary. -* [InefficientStringBuffering](pmd_rules_java_strings.html#inefficientstringbuffering): Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buf... -* [UnnecessaryCaseChange](pmd_rules_java_strings.html#unnecessarycasechange): Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() -* [UseStringBufferLength](pmd_rules_java_strings.html#usestringbufferlength): Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toStrin... * [AppendCharacterWithChar](pmd_rules_java_strings.html#appendcharacterwithchar): Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. +* [AvoidDuplicateLiterals](pmd_rules_java_strings.html#avoidduplicateliterals): Code containing duplicate String literals can usually be improved by declaring the String as a co... +* [AvoidStringBufferField](pmd_rules_java_strings.html#avoidstringbufferfield): StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ... * [ConsecutiveAppendsShouldReuse](pmd_rules_java_strings.html#consecutiveappendsshouldreuse): Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target obj... * [ConsecutiveLiteralAppends](pmd_rules_java_strings.html#consecutiveliteralappends): Consecutively calling StringBuffer/StringBuilder.append with String literals -* [UseIndexOfChar](pmd_rules_java_strings.html#useindexofchar): Use String.indexOf(char) when checking for the index of a single character; it executes faster. * [InefficientEmptyStringCheck](pmd_rules_java_strings.html#inefficientemptystringcheck): String.trim().length() is an inefficient way to check if a String is really empty, as itcreates a... +* [InefficientStringBuffering](pmd_rules_java_strings.html#inefficientstringbuffering): Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buf... * [InsufficientStringBufferDeclaration](pmd_rules_java_strings.html#insufficientstringbufferdeclaration): Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many times... -* [UselessStringValueOf](pmd_rules_java_strings.html#uselessstringvalueof): No need to call String.valueOf to append to a string; just use the valueOf() argument directly. * [StringBufferInstantiationWithChar](pmd_rules_java_strings.html#stringbufferinstantiationwithchar): Individual character values provided as initialization arguments will be converted into integers.... +* [StringInstantiation](pmd_rules_java_strings.html#stringinstantiation): Avoid instantiating String objects; this is usually unnecessary since they are immutable and can ... +* [StringToString](pmd_rules_java_strings.html#stringtostring): Avoid calling toString() on objects already known to be string instances; this is unnecessary. +* [UnnecessaryCaseChange](pmd_rules_java_strings.html#unnecessarycasechange): Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() * [UseEqualsToCompareStrings](pmd_rules_java_strings.html#useequalstocomparestrings): Using '==' or '!=' to compare strings only works if intern version is used on both sides.Use the ... -* [AvoidStringBufferField](pmd_rules_java_strings.html#avoidstringbufferfield): StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ... +* [UseIndexOfChar](pmd_rules_java_strings.html#useindexofchar): Use String.indexOf(char) when checking for the index of a single character; it executes faster. +* [UselessStringValueOf](pmd_rules_java_strings.html#uselessstringvalueof): No need to call String.valueOf to append to a string; just use the valueOf() argument directly. +* [UseStringBufferLength](pmd_rules_java_strings.html#usestringbufferlength): Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toStrin... ## Unnecessary * [UnnecessaryConversionTemporary](pmd_rules_java_unnecessary.html#unnecessaryconversiontemporary): Avoid the use temporary objects when converting primitives to Strings. Use the static conversion ... -* [UnnecessaryReturn](pmd_rules_java_unnecessary.html#unnecessaryreturn): Avoid the use of unnecessary return statements. * [UnnecessaryFinalModifier](pmd_rules_java_unnecessary.html#unnecessaryfinalmodifier): When a class has the final modifier, all the methods are automatically final and do not need to b... -* [UselessOverridingMethod](pmd_rules_java_unnecessary.html#uselessoverridingmethod): The overriding method merely calls the same method defined in a superclass. -* [UselessOperationOnImmutable](pmd_rules_java_unnecessary.html#uselessoperationonimmutable): An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object it... +* [UnnecessaryModifier](pmd_rules_java_unnecessary.html#unnecessarymodifier): Fields in interfaces and annotations are automatically 'public static final', and methods are 'pu... +* [UnnecessaryReturn](pmd_rules_java_unnecessary.html#unnecessaryreturn): Avoid the use of unnecessary return statements. * [UnusedNullCheckInEquals](pmd_rules_java_unnecessary.html#unusednullcheckinequals): After checking an object reference for null, you should invoke equals() on that object rather tha... +* [UselessOperationOnImmutable](pmd_rules_java_unnecessary.html#uselessoperationonimmutable): An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object it... +* [UselessOverridingMethod](pmd_rules_java_unnecessary.html#uselessoverridingmethod): The overriding method merely calls the same method defined in a superclass. * [UselessParentheses](pmd_rules_java_unnecessary.html#uselessparentheses): Useless parentheses should be removed. * [UselessQualifiedThis](pmd_rules_java_unnecessary.html#uselessqualifiedthis): Look for qualified this usages in the same class. -* [UnnecessaryModifier](pmd_rules_java_unnecessary.html#unnecessarymodifier): Fields in interfaces and annotations are automatically 'public static final', and methods are 'pu... ## Unused Code -* [UnusedPrivateField](pmd_rules_java_unusedcode.html#unusedprivatefield): Detects when a private field is declared and/or assigned a value, but not used. +* [UnusedFormalParameter](pmd_rules_java_unusedcode.html#unusedformalparameter): Avoid passing parameters to methods or constructors without actually referencing them in the meth... * [UnusedLocalVariable](pmd_rules_java_unusedcode.html#unusedlocalvariable): Detects when a local variable is declared and/or assigned, but not used. +* [UnusedPrivateField](pmd_rules_java_unusedcode.html#unusedprivatefield): Detects when a private field is declared and/or assigned a value, but not used. * [UnusedPrivateMethod](pmd_rules_java_unusedcode.html#unusedprivatemethod): Unused Private Method detects when a private method is declared but is unused. -* [UnusedFormalParameter](pmd_rules_java_unusedcode.html#unusedformalparameter): Avoid passing parameters to methods or constructors without actually referencing them in the meth... diff --git a/docs/pages/pmd/rules/jsp.md b/docs/pages/pmd/rules/jsp.md index cd46ce419..11eb83394 100644 --- a/docs/pages/pmd/rules/jsp.md +++ b/docs/pages/pmd/rules/jsp.md @@ -12,15 +12,15 @@ List of rulesets and rules contained in each ruleset. * [DontNestJsfInJstlIteration](pmd_rules_jsp_basic-jsf.html#dontnestjsfinjstliteration): Do not nest JSF component custom actions inside a custom action that iterates over its body. ## Basic JSP -* [NoLongScripts](pmd_rules_jsp_basic.html#nolongscripts): Scripts should be part of Tag Libraries, rather than part of JSP pages. -* [NoScriptlets](pmd_rules_jsp_basic.html#noscriptlets): Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of J... -* [NoInlineStyleInformation](pmd_rules_jsp_basic.html#noinlinestyleinformation): Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FON... -* [NoClassAttribute](pmd_rules_jsp_basic.html#noclassattribute): Do not use an attribute called 'class'. Use "styleclass" for CSS styles. -* [NoJspForward](pmd_rules_jsp_basic.html#nojspforward): Do not do a forward from within a JSP file. -* [IframeMissingSrcAttribute](pmd_rules_jsp_basic.html#iframemissingsrcattribute): IFrames which are missing a src element can cause security information popups in IE if you are ac... -* [NoHtmlComments](pmd_rules_jsp_basic.html#nohtmlcomments): In a production system, HTML comments increase the payload between the application server to th... * [DuplicateJspImports](pmd_rules_jsp_basic.html#duplicatejspimports): Avoid duplicate import statements inside JSP's. +* [IframeMissingSrcAttribute](pmd_rules_jsp_basic.html#iframemissingsrcattribute): IFrames which are missing a src element can cause security information popups in IE if you are ac... * [JspEncoding](pmd_rules_jsp_basic.html#jspencoding): A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. +* [NoClassAttribute](pmd_rules_jsp_basic.html#noclassattribute): Do not use an attribute called 'class'. Use "styleclass" for CSS styles. +* [NoHtmlComments](pmd_rules_jsp_basic.html#nohtmlcomments): In a production system, HTML comments increase the payload between the application server to th... * [NoInlineScript](pmd_rules_jsp_basic.html#noinlinescript): Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attri... +* [NoInlineStyleInformation](pmd_rules_jsp_basic.html#noinlinestyleinformation): Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FON... +* [NoJspForward](pmd_rules_jsp_basic.html#nojspforward): Do not do a forward from within a JSP file. +* [NoLongScripts](pmd_rules_jsp_basic.html#nolongscripts): Scripts should be part of Tag Libraries, rather than part of JSP pages. +* [NoScriptlets](pmd_rules_jsp_basic.html#noscriptlets): Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of J... * [NoUnsanitizedJSPExpression](pmd_rules_jsp_basic.html#nounsanitizedjspexpression): Avoid using expressions without escaping / sanitizing. This could lead to cross site scripting - ... diff --git a/docs/pages/pmd/rules/plsql.md b/docs/pages/pmd/rules/plsql.md index a4091e0d6..8263aac1d 100644 --- a/docs/pages/pmd/rules/plsql.md +++ b/docs/pages/pmd/rules/plsql.md @@ -11,22 +11,22 @@ List of rulesets and rules contained in each ruleset. * [Tom Kyte's Despair](pmd_rules_plsql_TomKytesDespair.html): Rules based on Thomas Kyte's recommendations on http://asktom.oracle.com/ and http://tkyte.blogspot.com/. ## Code Size -* [NPathComplexity](pmd_rules_plsql_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [CyclomaticComplexity](pmd_rules_plsql_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... * [ExcessiveMethodLength](pmd_rules_plsql_codesize.html#excessivemethodlength): When methods are excessively long this usually indicates that the method is doing more than itsna... -* [ExcessiveParameterList](pmd_rules_plsql_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... * [ExcessiveObjectLength](pmd_rules_plsql_codesize.html#excessiveobjectlength): Excessive object line lengths are usually indications that the object may be burdened with excess... -* [ExcessiveTypeLength](pmd_rules_plsql_codesize.html#excessivetypelength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... * [ExcessivePackageBodyLength](pmd_rules_plsql_codesize.html#excessivepackagebodylength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... * [ExcessivePackageSpecificationLength](pmd_rules_plsql_codesize.html#excessivepackagespecificationlength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... -* [CyclomaticComplexity](pmd_rules_plsql_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... -* [TooManyFields](pmd_rules_plsql_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... +* [ExcessiveParameterList](pmd_rules_plsql_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... +* [ExcessiveTypeLength](pmd_rules_plsql_codesize.html#excessivetypelength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... * [NcssMethodCount](pmd_rules_plsql_codesize.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssObjectCount](pmd_rules_plsql_codesize.html#ncssobjectcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... +* [NPathComplexity](pmd_rules_plsql_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... +* [TooManyFields](pmd_rules_plsql_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... * [TooManyMethods](pmd_rules_plsql_codesize.html#toomanymethods): A package or type with too many methods is probably a good suspect for refactoring, in order to r... ## PLSQL DATETIME -* [TO_DATEWithoutDateFormat](pmd_rules_plsql_dates.html#to_datewithoutdateformat): TO_DATE without date format- use TO_DATE(expression, date-format) * [TO_DATE_TO_CHAR](pmd_rules_plsql_dates.html#to_date_to_char): TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) +* [TO_DATEWithoutDateFormat](pmd_rules_plsql_dates.html#to_datewithoutdateformat): TO_DATE without date format- use TO_DATE(expression, date-format) * [TO_TIMESTAMPWithoutDateFormat](pmd_rules_plsql_dates.html#to_timestampwithoutdateformat): TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) ## Strict Syntax diff --git a/docs/pages/pmd/rules/vf.md b/docs/pages/pmd/rules/vf.md index e0ef040ab..95b6f0915 100644 --- a/docs/pages/pmd/rules/vf.md +++ b/docs/pages/pmd/rules/vf.md @@ -8,6 +8,6 @@ List of rulesets and rules contained in each ruleset. * [Basic VF](pmd_rules_vf_security.html): Rules concerning basic VF guidelines. ## Basic VF -* [VfUnescapeEl](pmd_rules_vf_security.html#vfunescapeel): Avoid unescaped user controlled content in EL as it results in XSS. * [VfCsrf](pmd_rules_vf_security.html#vfcsrf): Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. +* [VfUnescapeEl](pmd_rules_vf_security.html#vfunescapeel): Avoid unescaped user controlled content in EL as it results in XSS. diff --git a/docs/pages/pmd/rules/vm.md b/docs/pages/pmd/rules/vm.md index e74f8c20c..88f95f9be 100644 --- a/docs/pages/pmd/rules/vm.md +++ b/docs/pages/pmd/rules/vm.md @@ -9,12 +9,12 @@ List of rulesets and rules contained in each ruleset. ## Basic Velocity * [AvoidDeeplyNestedIfStmts](pmd_rules_vm_basic.html#avoiddeeplynestedifstmts): Avoid creating deeply nested if-then statements since they are harder to read and error-prone to ... -* [CollapsibleIfStatements](pmd_rules_vm_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... -* [ExcessiveTemplateLength](pmd_rules_vm_basic.html#excessivetemplatelength): The template is too long. It should be broken up into smaller pieces. * [AvoidReassigningParameters](pmd_rules_vm_basic.html#avoidreassigningparameters): Reassigning values to incoming parameters is not recommended. Use temporary local variables inst... -* [EmptyIfStmt](pmd_rules_vm_basic.html#emptyifstmt): Empty if statements should be deleted. +* [CollapsibleIfStatements](pmd_rules_vm_basic.html#collapsibleifstatements): Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with... * [EmptyForeachStmt](pmd_rules_vm_basic.html#emptyforeachstmt): Empty foreach statements should be deleted. -* [UnusedMacroParameter](pmd_rules_vm_basic.html#unusedmacroparameter): Avoid unused macro parameters. They should be deleted. +* [EmptyIfStmt](pmd_rules_vm_basic.html#emptyifstmt): Empty if statements should be deleted. +* [ExcessiveTemplateLength](pmd_rules_vm_basic.html#excessivetemplatelength): The template is too long. It should be broken up into smaller pieces. * [NoInlineJavaScript](pmd_rules_vm_basic.html#noinlinejavascript): Avoid inline JavaScript. Import .js files instead. * [NoInlineStyles](pmd_rules_vm_basic.html#noinlinestyles): Avoid inline styles. Use css classes instead. +* [UnusedMacroParameter](pmd_rules_vm_basic.html#unusedmacroparameter): Avoid unused macro parameters. They should be deleted. diff --git a/docs/pages/pmd/rules/xml.md b/docs/pages/pmd/rules/xml.md index 9d58e4b61..c5318a408 100644 --- a/docs/pages/pmd/rules/xml.md +++ b/docs/pages/pmd/rules/xml.md @@ -9,8 +9,8 @@ List of rulesets and rules contained in each ruleset. * [Basic XML](pmd_rules_xml_basic.html): The Basic XML Ruleset contains a collection of good practices which everyone should follow. ## Basic POM -* [ProjectVersionAsDependencyVersion](pmd_rules_xml_basic.html#projectversionasdependencyversion): Using that expression in dependency declarations seems like a shortcut, but it can go wrong. By f... * [InvalidDependencyTypes](pmd_rules_xml_basic.html#invaliddependencytypes): While Maven will not failed if you use an invalid type for a dependency in the dependency managem... +* [ProjectVersionAsDependencyVersion](pmd_rules_xml_basic.html#projectversionasdependencyversion): Using that expression in dependency declarations seems like a shortcut, but it can go wrong. By f... ## Basic XML * [MistypedCDATASection](pmd_rules_xml_basic.html#mistypedcdatasection): An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and ends with a ]]> mar... diff --git a/docs/pages/pmd/rules/xsl.md b/docs/pages/pmd/rules/xsl.md index 55a023262..136139ca4 100644 --- a/docs/pages/pmd/rules/xsl.md +++ b/docs/pages/pmd/rules/xsl.md @@ -8,6 +8,6 @@ List of rulesets and rules contained in each ruleset. * [XPath in XSL](pmd_rules_xsl_xpath.html): This ruleset regroups a collection of good practices regarding XPath querying and functions inside an XSL. ## XPath in XSL -* [UseConcatOnce](pmd_rules_xsl_xpath.html#useconcatonce): The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b'... * [AvoidAxisNavigation](pmd_rules_xsl_xpath.html#avoidaxisnavigation): Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100%... +* [UseConcatOnce](pmd_rules_xsl_xpath.html#useconcatonce): The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b'... From 8bdb0a5d22d4d7d39c0b2da78049b3fb6293529d Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Thu, 10 Aug 2017 19:00:10 +0200 Subject: [PATCH 10/24] [doc] add pmd-doc submodule --- pmd-doc/pom.xml | 31 +++++++++++++++++++++++++++++++ pom.xml | 3 ++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 pmd-doc/pom.xml diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml new file mode 100644 index 000000000..fbd856c71 --- /dev/null +++ b/pmd-doc/pom.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>pmd-doc</artifactId> + <name>PMD Documentation Generator</name> + <packaging>jar</packaging> + + <parent> + <groupId>net.sourceforge.pmd</groupId> + <artifactId>pmd</artifactId> + <version>6.0.0-SNAPSHOT</version> + </parent> + + <properties> + <java.version>1.8</java.version> + </properties> + + <dependencies> + <dependency> + <groupId>net.sourceforge.pmd</groupId> + <artifactId>pmd-dist</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/pom.xml b/pom.xml index 9f3c42896..9c6b65098 100644 --- a/pom.xml +++ b/pom.xml @@ -471,7 +471,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code <artifactId>nexus-staging-maven-plugin</artifactId> <version>1.6.8</version> </plugin> - <!--This plugin's configuration is used to store Eclipse + <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself. --> <plugin> <groupId>org.eclipse.m2e</groupId> @@ -945,6 +945,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code <module>pmd-apex</module> <module>pmd-java8</module> <module>pmd-ui</module> + <module>pmd-doc</module> </modules> </profile> From d537b2acbe35de0168d854819b53146060b7029d Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Thu, 10 Aug 2017 19:18:35 +0200 Subject: [PATCH 11/24] [doc] move RuleDocGenerator into pmd-doc It'll be executed during package phase. --- pmd-doc/pom.xml | 24 +++++++++++++++++++ .../pmd/docs/GenerateRuleDocsCmd.java | 11 +++++---- .../pmd/docs/RuleDocGenerator.java | 4 +--- 3 files changed, 31 insertions(+), 8 deletions(-) rename pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java => pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java (54%) rename {pmd-dist/src/test => pmd-doc/src/main}/java/net/sourceforge/pmd/docs/RuleDocGenerator.java (98%) diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index fbd856c71..bbf0aa0ac 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -15,6 +15,30 @@ <java.version>1.8</java.version> </properties> + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.6.0</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + <configuration> + <mainClass>net.sourceforge.pmd.docs.GenerateRuleDocsCmd</mainClass> + <arguments> + <argument>${project.basedir}</argument> + </arguments> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> <dependency> <groupId>net.sourceforge.pmd</groupId> diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java similarity index 54% rename from pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java rename to pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java index 11546defa..e4357bbc1 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/GenerateRuleDocsTest.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java @@ -5,15 +5,16 @@ package net.sourceforge.pmd.docs; import java.nio.file.FileSystems; +import java.nio.file.Path; -import org.junit.Test; +public class GenerateRuleDocsCmd { -public class GenerateRuleDocsTest { - @Test - public void generateDocs() { + public static void main(String[] args) { long start = System.currentTimeMillis(); RuleDocGenerator generator = new RuleDocGenerator(); - generator.generate(FileSystems.getDefault().getPath("..").toAbsolutePath().normalize()); + Path output = FileSystems.getDefault().getPath(args[0]).resolve("..").toAbsolutePath().normalize(); + System.out.println("Generating docs into " + output); + generator.generate(output); System.out.println("Generated docs in " + (System.currentTimeMillis() - start) + " ms"); } } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java similarity index 98% rename from pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java rename to pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 562d2e43d..d999dd5d1 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; @@ -287,8 +286,7 @@ public int compare(Rule o1, Rule o2) { * @return * @throws IOException */ - private static String getRuleSetSourceFilepath(RuleSet ruleset) throws IOException { - Path root = FileSystems.getDefault().getPath("..").toAbsolutePath().normalize(); + private String getRuleSetSourceFilepath(RuleSet ruleset) throws IOException { final String rulesetFilename = FilenameUtils.normalize(StringUtils.chomp(ruleset.getFileName())); final List<Path> foundPathResult = new LinkedList<>(); From 5113af65681c715d853ee125db108f9ab04457b7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Thu, 10 Aug 2017 19:27:33 +0200 Subject: [PATCH 12/24] Fix build --- pmd-doc/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index bbf0aa0ac..23c78952a 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -13,6 +13,7 @@ <properties> <java.version>1.8</java.version> + <config.basedir>${basedir}/../pmd-core</config.basedir> </properties> <build> From 0b9b7e2a5dd94a053b28cbf9bfb2d149cf56f062 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Thu, 10 Aug 2017 19:41:00 +0200 Subject: [PATCH 13/24] Fix checkstyle --- .../java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java index e4357bbc1..5a34b910a 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java @@ -8,6 +8,9 @@ import java.nio.file.Path; public class GenerateRuleDocsCmd { + private GenerateRuleDocsCmd() { + // Utility class + } public static void main(String[] args) { long start = System.currentTimeMillis(); From d6c23fd17f2546ce775a00743353ef6aa41276f9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 11:32:05 +0200 Subject: [PATCH 14/24] [doc] Add unit test for rule doc generator Therefore the file writer has been mocked. The rulesets to be documented are now given, rather than determined by the generator. --- .../pmd/docs/DefaultFileWriter.java | 19 +++++ .../net/sourceforge/pmd/docs/FileWriter.java | 14 +++ .../pmd/docs/GenerateRuleDocsCmd.java | 15 +++- .../pmd/docs/RuleDocGenerator.java | 46 +++++----- .../pmd/docs/MockedFileWriter.java | 46 ++++++++++ .../pmd/docs/RuleDocGeneratorTest.java | 64 ++++++++++++++ pmd-doc/src/test/resources/expected/java.md | 12 +++ pmd-doc/src/test/resources/expected/sample.md | 62 ++++++++++++++ .../resources/rulesets/ruledoctest/sample.xml | 85 +++++++++++++++++++ 9 files changed, 337 insertions(+), 26 deletions(-) create mode 100644 pmd-doc/src/main/java/net/sourceforge/pmd/docs/DefaultFileWriter.java create mode 100644 pmd-doc/src/main/java/net/sourceforge/pmd/docs/FileWriter.java create mode 100644 pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java create mode 100644 pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java create mode 100644 pmd-doc/src/test/resources/expected/java.md create mode 100644 pmd-doc/src/test/resources/expected/sample.md create mode 100644 pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DefaultFileWriter.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DefaultFileWriter.java new file mode 100644 index 000000000..5c7e84ad2 --- /dev/null +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/DefaultFileWriter.java @@ -0,0 +1,19 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +public class DefaultFileWriter implements FileWriter { + @Override + public void write(Path path, List<String> lines) throws IOException { + Files.createDirectories(path.getParent()); + Files.write(path, lines, StandardCharsets.UTF_8); + } +} diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/FileWriter.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/FileWriter.java new file mode 100644 index 000000000..d47452754 --- /dev/null +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/FileWriter.java @@ -0,0 +1,14 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +public interface FileWriter { + + void write(Path path, List<String> lines) throws IOException; +} diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java index 5a34b910a..64f04bc96 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/GenerateRuleDocsCmd.java @@ -6,18 +6,27 @@ import java.nio.file.FileSystems; import java.nio.file.Path; +import java.util.Iterator; + +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; public class GenerateRuleDocsCmd { private GenerateRuleDocsCmd() { // Utility class } - public static void main(String[] args) { + public static void main(String[] args) throws RuleSetNotFoundException { long start = System.currentTimeMillis(); - RuleDocGenerator generator = new RuleDocGenerator(); Path output = FileSystems.getDefault().getPath(args[0]).resolve("..").toAbsolutePath().normalize(); System.out.println("Generating docs into " + output); - generator.generate(output); + RuleDocGenerator generator = new RuleDocGenerator(new DefaultFileWriter(), output); + + RuleSetFactory ruleSetFactory = new RuleSetFactory(); + Iterator<RuleSet> registeredRuleSets = ruleSetFactory.getRegisteredRuleSets(); + + generator.generate(registeredRuleSets); System.out.println("Generated docs in " + (System.currentTimeMillis() - start) + " ms"); } } diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index d999dd5d1..ade2c239a 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.docs; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; @@ -29,7 +28,6 @@ import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.rule.XPathRule; @@ -40,21 +38,25 @@ public class RuleDocGenerator { private static final String RULESET_INDEX_FILENAME_PATTERN = "docs/pages/pmd/rules/${language.tersename}/${ruleset.name}.md"; private static final String RULESET_INDEX_PERMALINK_PATTERN = "pmd_rules_${language.tersename}_${ruleset.name}.html"; - private Path root; + private final Path root; + private final FileWriter writer; - public void generate(Path root) { + public RuleDocGenerator(FileWriter writer, Path root) { this.root = Objects.requireNonNull(root, "Root directory must be provided"); + this.writer = Objects.requireNonNull(writer, "A file writer must be provided"); Path docsDir = root.resolve("docs"); if (!Files.exists(docsDir) || !Files.isDirectory(docsDir)) { throw new IllegalArgumentException("Couldn't find \"docs\" subdirectory"); } + } - Map<Language, List<RuleSet>> rulesets; + public void generate(Iterator<RuleSet> rulesets) { + Map<Language, List<RuleSet>> sortedRulesets; try { - rulesets = loadAndSortRulesets(); - generateLanguageIndex(rulesets); - generateRuleSetIndex(rulesets); + sortedRulesets = sortRulesets(rulesets); + generateLanguageIndex(sortedRulesets); + generateRuleSetIndex(sortedRulesets); } catch (RuleSetNotFoundException | IOException e) { throw new RuntimeException(e); @@ -65,23 +67,20 @@ private Path getAbsoluteOutputPath(String filename) { return root.resolve(FilenameUtils.normalize(filename)); } - private Map<Language, List<RuleSet>> loadAndSortRulesets() throws RuleSetNotFoundException { - RuleSetFactory ruleSetFactory = new RuleSetFactory(); - Iterator<RuleSet> registeredRuleSets = ruleSetFactory.getRegisteredRuleSets(); - - Map<Language, List<RuleSet>> rulesets = new HashMap<>(); + private Map<Language, List<RuleSet>> sortRulesets(Iterator<RuleSet> rulesets) throws RuleSetNotFoundException { + Map<Language, List<RuleSet>> rulesetsByLanguage = new HashMap<>(); - while (registeredRuleSets.hasNext()) { - RuleSet ruleset = registeredRuleSets.next(); + while (rulesets.hasNext()) { + RuleSet ruleset = rulesets.next(); Language language = getRuleSetLanguage(ruleset); - if (!rulesets.containsKey(language)) { - rulesets.put(language, new ArrayList<RuleSet>()); + if (!rulesetsByLanguage.containsKey(language)) { + rulesetsByLanguage.put(language, new ArrayList<RuleSet>()); } - rulesets.get(language).add(ruleset); + rulesetsByLanguage.get(language).add(ruleset); } - for (List<RuleSet> rulesetsOfOneLanguage : rulesets.values()) { + for (List<RuleSet> rulesetsOfOneLanguage : rulesetsByLanguage.values()) { Collections.sort(rulesetsOfOneLanguage, new Comparator<RuleSet>() { @Override public int compare(RuleSet o1, RuleSet o2) { @@ -89,7 +88,7 @@ public int compare(RuleSet o1, RuleSet o2) { } }); } - return rulesets; + return rulesetsByLanguage; } /** @@ -152,7 +151,7 @@ private void generateLanguageIndex(Map<Language, List<RuleSet>> rulesets) throws } System.out.println("Generated " + path); - Files.write(path, lines, StandardCharsets.UTF_8); + writer.write(path, lines); } } @@ -219,6 +218,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws for (Rule rule : getSortedRules(ruleset)) { lines.add("## " + rule.getName()); + lines.add(""); if (rule.getSince() != null) { lines.add("**Since:** " + rule.getSince()); lines.add(""); @@ -230,6 +230,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add(""); if (!rule.getExamples().isEmpty()) { lines.add("**Example(s):**"); + lines.add(""); for (String example : rule.getExamples()) { lines.add("```"); lines.add(StringUtils.stripToEmpty(example)); @@ -260,8 +261,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws } } - Files.createDirectories(path.getParent()); - Files.write(path, lines, StandardCharsets.UTF_8); + writer.write(path, lines); System.out.println("Generated " + path); } } diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java new file mode 100644 index 000000000..a533e136f --- /dev/null +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/MockedFileWriter.java @@ -0,0 +1,46 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +public class MockedFileWriter implements FileWriter { + + public static class FileEntry { + private String filename; + private String content; + + public String getFilename() { + return filename; + } + + public String getContent() { + return content; + } + } + + private List<FileEntry> data = new ArrayList<>(); + + @Override + public void write(Path path, List<String> lines) throws IOException { + FileEntry entry = new FileEntry(); + entry.filename = path.toString(); + entry.content = StringUtils.join(lines, System.getProperty("line.separator")); + data.add(entry); + } + + public List<FileEntry> getData() { + return data; + } + + public void reset() { + data.clear(); + } +} diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java new file mode 100644 index 000000000..43e64bb1d --- /dev/null +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java @@ -0,0 +1,64 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.docs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + +import org.apache.commons.io.IOUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; +import net.sourceforge.pmd.docs.MockedFileWriter.FileEntry; + +public class RuleDocGeneratorTest { + + private MockedFileWriter writer = new MockedFileWriter(); + private Path root; + + @Before + public void setup() throws IOException { + writer.reset(); + + root = Files.createTempDirectory("pmd-ruledocgenerator-test"); + Files.createDirectory(root.resolve("docs")); + } + + @After + public void cleanup() throws IOException { + Files.delete(root.resolve("docs")); + Files.delete(root); + } + + @Test + public void testSingleRuleset() throws RuleSetNotFoundException, IOException { + RuleDocGenerator generator = new RuleDocGenerator(writer, root); + + RuleSetFactory rsf = new RuleSetFactory(); + RuleSet ruleset = rsf.createRuleSet("rulesets/ruledoctest/sample.xml"); + + generator.generate(Arrays.asList(ruleset).iterator()); + + assertEquals(2, writer.getData().size()); + FileEntry languageIndex = writer.getData().get(0); + assertTrue(languageIndex.getFilename().endsWith("docs/pages/pmd/rules/java.md")); + assertEquals(IOUtils.toString(RuleDocGeneratorTest.class.getResourceAsStream("/expected/java.md")), + languageIndex.getContent()); + + FileEntry ruleSetIndex = writer.getData().get(1); + assertTrue(ruleSetIndex.getFilename().endsWith("docs/pages/pmd/rules/java/sample.md")); + assertEquals(IOUtils.toString(RuleDocGeneratorTest.class.getResourceAsStream("/expected/sample.md")), + ruleSetIndex.getContent()); + } +} diff --git a/pmd-doc/src/test/resources/expected/java.md b/pmd-doc/src/test/resources/expected/java.md new file mode 100644 index 000000000..97278fac9 --- /dev/null +++ b/pmd-doc/src/test/resources/expected/java.md @@ -0,0 +1,12 @@ +--- +title: Java Rules +permalink: pmd_rules_java.html +folder: pmd/rules +--- +List of rulesets and rules contained in each ruleset. + +* [Sample](pmd_rules_java_sample.html): Sample ruleset to test rule doc generation. + +## Sample +* [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +* [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md new file mode 100644 index 000000000..356d5197d --- /dev/null +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -0,0 +1,62 @@ +--- +title: Sample +summary: Sample ruleset to test rule doc generation. +permalink: pmd_rules_java_sample.html +folder: pmd/rules/java +sidebaractiveurl: /pmd_rules_java.html +editmepath: ../rulesets/ruledoctest/sample.xml +--- +## JumbledIncrementer + +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**Example(s):** + +``` +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} +``` + +## OverrideBothEqualsAndHashcode + +**Since:** 0.4 + +**Priority:** Medium (3) + +Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. + +**Example(s):** + +``` +public class Bar { // poor, missing a hashcode() method + public boolean equals(Object o) { + // do some comparison + } +} + +public class Baz { // poor, missing an equals() method + public int hashCode() { + // return some hash value + } +} + +public class Foo { // perfect, both methods provided + public boolean equals(Object other) { + // do some comparison + } + public int hashCode() { + // return some hash value + } +} +``` diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml new file mode 100644 index 000000000..e5d35152e --- /dev/null +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -0,0 +1,85 @@ +<?xml version="1.0"?> + +<ruleset name="Sample" + xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> + <description> +Sample ruleset to test rule doc generation. + </description> + + <rule name="OverrideBothEqualsAndHashcode" + language="java" + since="0.4" + message="Ensure you override both equals() and hashCode()" + class="net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule" + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#overridebothequalsandhashcode"> + <description> +Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. + </description> + <priority>3</priority> + <example> + <![CDATA[ +public class Bar { // poor, missing a hashcode() method + public boolean equals(Object o) { + // do some comparison + } +} + +public class Baz { // poor, missing an equals() method + public int hashCode() { + // return some hash value + } +} + +public class Foo { // perfect, both methods provided + public boolean equals(Object other) { + // do some comparison + } + public int hashCode() { + // return some hash value + } +} + ]]> + </example> + </rule> + + <rule name="JumbledIncrementer" + language="java" + since="1.0" + message="Avoid modifying an outer loop incrementer in an inner loop for update expression" + class="net.sourceforge.pmd.lang.rule.XPathRule" + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#jumbledincrementer"> + <description> +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + </description> + <priority>3</priority> + <properties> + <property name="xpath"> + <value> + <![CDATA[ +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] + ]]> + </value> + </property> + </properties> + <example> + <![CDATA[ +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} + ]]> + </example> + </rule> +</ruleset> From 2816988454040ab05015653b5b281478bb260a43 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 11:41:15 +0200 Subject: [PATCH 15/24] [doc] update generated documentation Note: only new lines have been added --- docs/pages/pmd/rules/apex/apexunit.md | 4 + docs/pages/pmd/rules/apex/braces.md | 8 ++ docs/pages/pmd/rules/apex/complexity.md | 18 +++ docs/pages/pmd/rules/apex/performance.md | 4 + docs/pages/pmd/rules/apex/security.md | 22 ++++ docs/pages/pmd/rules/apex/style.md | 12 ++ docs/pages/pmd/rules/ecmascript/basic.md | 18 +++ docs/pages/pmd/rules/ecmascript/braces.md | 8 ++ .../pages/pmd/rules/ecmascript/unnecessary.md | 6 + docs/pages/pmd/rules/java/android.md | 6 + docs/pages/pmd/rules/java/basic.md | 48 ++++++++ docs/pages/pmd/rules/java/braces.md | 8 ++ docs/pages/pmd/rules/java/clone.md | 10 ++ docs/pages/pmd/rules/java/codesize.md | 25 ++++ docs/pages/pmd/rules/java/comments.md | 8 ++ docs/pages/pmd/rules/java/controversial.md | 43 +++++++ docs/pages/pmd/rules/java/coupling.md | 10 ++ docs/pages/pmd/rules/java/design.md | 113 ++++++++++++++++++ docs/pages/pmd/rules/java/empty.md | 22 ++++ docs/pages/pmd/rules/java/finalizers.md | 12 ++ docs/pages/pmd/rules/java/imports.md | 12 ++ docs/pages/pmd/rules/java/j2ee.md | 18 +++ docs/pages/pmd/rules/java/javabeans.md | 4 + docs/pages/pmd/rules/java/junit.md | 24 ++++ .../pmd/rules/java/logging-jakarta-commons.md | 8 ++ docs/pages/pmd/rules/java/logging-java.md | 12 ++ docs/pages/pmd/rules/java/migrating.md | 28 +++++ docs/pages/pmd/rules/java/naming.md | 40 +++++++ docs/pages/pmd/rules/java/optimizations.md | 24 ++++ docs/pages/pmd/rules/java/strictexception.md | 24 ++++ docs/pages/pmd/rules/java/strings.md | 32 +++++ docs/pages/pmd/rules/java/sunsecure.md | 4 + docs/pages/pmd/rules/java/unnecessary.md | 18 +++ docs/pages/pmd/rules/java/unusedcode.md | 8 ++ docs/pages/pmd/rules/jsp/basic-jsf.md | 2 + docs/pages/pmd/rules/jsp/basic.md | 22 ++++ docs/pages/pmd/rules/plsql/TomKytesDespair.md | 2 + docs/pages/pmd/rules/plsql/codesize.md | 23 ++++ docs/pages/pmd/rules/plsql/dates.md | 6 + docs/pages/pmd/rules/plsql/strictsyntax.md | 2 + docs/pages/pmd/rules/vf/security.md | 4 + docs/pages/pmd/rules/vm/basic.md | 9 ++ docs/pages/pmd/rules/xml/basic.md | 2 + docs/pages/pmd/rules/xsl/xpath.md | 4 + 44 files changed, 737 insertions(+) diff --git a/docs/pages/pmd/rules/apex/apexunit.md b/docs/pages/pmd/rules/apex/apexunit.md index 7ce403575..a4826becf 100644 --- a/docs/pages/pmd/rules/apex/apexunit.md +++ b/docs/pages/pmd/rules/apex/apexunit.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/apexunit.xml --- ## ApexUnitTestClassShouldHaveAsserts + **Since:** 5.5.1 **Priority:** Medium (3) @@ -15,6 +16,7 @@ Apex unit tests should include at least one assertion. This makes the tests mor with messages provide the developer a clearer idea of what the test does. **Example(s):** + ``` @isTest public class Foo { @@ -36,6 +38,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexUnitTestShouldNotUseSeeAllDataTrue + **Since:** 5.5.1 **Priority:** Medium (3) @@ -43,6 +46,7 @@ public class Foo { Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests. **Example(s):** + ``` @isTest(seeAllData = true) public class Foo { diff --git a/docs/pages/pmd/rules/apex/braces.md b/docs/pages/pmd/rules/apex/braces.md index 1473297b8..4018e5747 100644 --- a/docs/pages/pmd/rules/apex/braces.md +++ b/docs/pages/pmd/rules/apex/braces.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/braces.xml --- ## ForLoopsMustUseBraces + **Since:** 5.6.0 **Priority:** Medium (3) @@ -16,6 +17,7 @@ indentation is lost then it becomes difficult to separate the code being control from the rest. **Example(s):** + ``` for (int i = 0; i < 42; i++) // not recommended foo(); @@ -34,6 +36,7 @@ for (int i = 0; i < 42; i++) { // preferred approach |cc_block_highlighting|false|Code Climate Block Highlighting| ## IfElseStmtsMustUseBraces + **Since:** 5.6.0 **Priority:** Medium (3) @@ -43,6 +46,7 @@ or indentation is lost then it becomes difficult to separate the code being cont from the rest. **Example(s):** + ``` // this is OK if (foo) x++; @@ -63,6 +67,7 @@ if (foo) |cc_block_highlighting|false|Code Climate Block Highlighting| ## IfStmtsMustUseBraces + **Since:** 5.6.0 **Priority:** Medium (3) @@ -72,6 +77,7 @@ formatting or indentation is lost then it becomes difficult to separate the code controlled from the rest. **Example(s):** + ``` if (foo) // not recommended x++; @@ -90,6 +96,7 @@ if (foo) { // preferred approach |cc_block_highlighting|false|Code Climate Block Highlighting| ## WhileLoopsMustUseBraces + **Since:** 5.6.0 **Priority:** Medium (3) @@ -99,6 +106,7 @@ formatting or indentation is lost then it becomes difficult to separate the code controlled from the rest. **Example(s):** + ``` while (true) // not recommended x++; diff --git a/docs/pages/pmd/rules/apex/complexity.md b/docs/pages/pmd/rules/apex/complexity.md index 8bf1d704e..11df749c4 100644 --- a/docs/pages/pmd/rules/apex/complexity.md +++ b/docs/pages/pmd/rules/apex/complexity.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/complexity.xml --- ## AvoidDeeplyNestedIfStmts + **Since:** 5.5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/complexity.xml Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. **Example(s):** + ``` public class Foo { public void bar(Integer x, Integer y, Integer z) { @@ -38,6 +40,7 @@ public class Foo { |problemDepth|3|The if statement depth reporting threshold| ## ExcessiveClassLength + **Since:** 5.5.0 **Priority:** Medium (3) @@ -47,6 +50,7 @@ responsibilities that could be provided by external classes or functions. In bre apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` public class Foo { public void bar1() { @@ -76,6 +80,7 @@ public class Foo { |sigma||Sigma value| ## ExcessiveParameterList + **Since:** 5.5.0 **Priority:** Medium (3) @@ -84,6 +89,7 @@ Methods with numerous parameters are a challenge to maintain, especially if most same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. **Example(s):** + ``` // too many arguments liable to be mixed up public void addPerson(int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { @@ -107,6 +113,7 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { |sigma||Sigma value| ## ExcessivePublicCount + **Since:** 5.5.0 **Priority:** Medium (3) @@ -117,6 +124,7 @@ smaller ones not only increases testability and reliability but also allows new developed easily. **Example(s):** + ``` public class Foo { public String value; @@ -143,6 +151,7 @@ public class Foo { |sigma||Sigma value| ## NcssConstructorCount + **Since:** 5.5.0 **Priority:** Medium (3) @@ -152,6 +161,7 @@ of code for a given constructor. NCSS ignores comments, and counts actual statem lines of code that are split are counted as one. **Example(s):** + ``` public class Foo extends Bar { //this constructor only has 1 NCSS lines @@ -178,6 +188,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## NcssMethodCount + **Since:** 5.5.0 **Priority:** Medium (3) @@ -187,6 +198,7 @@ of code for a given method. NCSS ignores comments, and counts actual statements. lines of code that are split are counted as one. **Example(s):** + ``` public class Foo extends Bar { //this method only has 1 NCSS lines @@ -212,6 +224,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## NcssTypeCount + **Since:** 5.5.0 **Priority:** Medium (3) @@ -221,6 +234,7 @@ of code for a given type. NCSS ignores comments, and counts actual statements. U lines of code that are split are counted as one. **Example(s):** + ``` //this class only has 6 NCSS lines public class Foo extends Bar { @@ -248,6 +262,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## StdCyclomaticComplexity + **Since:** 5.5.0 **Priority:** Medium (3) @@ -258,6 +273,7 @@ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate c high complexity, and 11+ is very high complexity. **Example(s):** + ``` // This has a Cyclomatic Complexity = 12 public class Foo { @@ -310,6 +326,7 @@ high complexity, and 11+ is very high complexity. |reportLevel|10|Cyclomatic Complexity reporting threshold| ## TooManyFields + **Since:** 5.5.0 **Priority:** Medium (3) @@ -319,6 +336,7 @@ possibly through grouping related fields in new objects. For example, a class w city/state/zip fields could park them within a single Address field. **Example(s):** + ``` public class Person { // too many separate fields diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md index f24acd4b2..80ea8bb85 100644 --- a/docs/pages/pmd/rules/apex/performance.md +++ b/docs/pages/pmd/rules/apex/performance.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/performance.xml --- ## AvoidDmlStatementsInLoops + **Since:** 5.5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/performance.xml Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. **Example(s):** + ``` public class Something { public void foo() { @@ -35,6 +37,7 @@ public class Something { |cc_block_highlighting|false|Code Climate Block Highlighting| ## AvoidSoqlInLoops + **Since:** 5.5.0 **Priority:** Medium (3) @@ -42,6 +45,7 @@ public class Something { New objects created within loops should be checked to see if they can created outside them and reused. **Example(s):** + ``` public class Something { public static void main( String as[] ) { diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md index 39cf3f158..49186a95e 100644 --- a/docs/pages/pmd/rules/apex/security.md +++ b/docs/pages/pmd/rules/apex/security.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/security.xml --- ## ApexBadCrypto + **Since:** 5.5.3 **Priority:** Medium (3) @@ -15,6 +16,7 @@ The rule makes sure you are using randomly generated IVs and keys for `Crypto` c Hard-wiring these values greatly compromises the security of encrypted data. **Example(s):** + ``` public without sharing class Foo { Blob hardCodedIV = Blob.valueOf('Hardcoded IV 123'); @@ -33,6 +35,7 @@ public without sharing class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexCRUDViolation + **Since:** 5.5.3 **Priority:** Medium (3) @@ -42,6 +45,7 @@ Since Apex runs in system mode not having proper permissions checks results in e privilege and may produce runtime errors. This check forces you to handle such scenarios. **Example(s):** + ``` public class Foo { public Contact foo(String status, String ID) { @@ -68,6 +72,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexCSRF + **Since:** 5.5.3 **Priority:** Medium (3) @@ -76,6 +81,7 @@ Check to avoid making DML operations in Apex class constructor/init method. This modification of the database just by accessing a page. **Example(s):** + ``` public class Foo { public init() { @@ -97,6 +103,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexDangerousMethods + **Since:** 5.5.3 **Priority:** Medium (3) @@ -111,6 +118,7 @@ opens the door to several attacks and requires manual validation, which is unrel of private data. **Example(s):** + ``` public class Foo { public Foo() { @@ -128,6 +136,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexInsecureEndpoint + **Since:** 5.5.3 **Priority:** Medium (3) @@ -136,6 +145,7 @@ Checks against accessing endpoints under plain **http**. You should always use **https** for security. **Example(s):** + ``` public without sharing class Foo { void foo() { @@ -154,6 +164,7 @@ public without sharing class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexOpenRedirect + **Since:** 5.5.3 **Priority:** Medium (3) @@ -162,6 +173,7 @@ Checks against redirects to user-controlled locations. This prevents attackers f redirecting users to phishing sites. **Example(s):** + ``` public without sharing class Foo { String unsafeLocation = ApexPage.getCurrentPage().getParameters.get('url_param'); @@ -180,6 +192,7 @@ public without sharing class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexSharingViolations + **Since:** 5.5.3 **Priority:** Medium (3) @@ -188,6 +201,7 @@ Detect classes declared without explicit sharing mode if DML methods are used. T forces the developer to take access restrictions into account before modifying objects. **Example(s):** + ``` public without sharing class Foo { // DML operation here @@ -203,6 +217,7 @@ public without sharing class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexSOQLInjection + **Since:** 5.5.3 **Priority:** Medium (3) @@ -210,6 +225,7 @@ public without sharing class Foo { Detects the usage of untrusted / unescaped variables in DML queries. **Example(s):** + ``` public class Foo { public void test1(String t1) { @@ -227,6 +243,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexSuggestUsingNamedCred + **Since:** 5.5.3 **Priority:** Medium (3) @@ -246,6 +263,7 @@ Instead, you should use *Named Credentials* and a callout endpoint. For more information, you can check [this](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials.htm) **Example(s):** + ``` public class Foo { public void foo(String username, String password) { @@ -265,6 +283,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexXSSFromEscapeFalse + **Since:** 5.5.3 **Priority:** Medium (3) @@ -274,6 +293,7 @@ will be displayed directly to the user in the UI, making it prime ground for XSS attacks if unescaped. **Example(s):** + ``` public without sharing class Foo { Trigger.new[0].addError(vulnerableHTMLGoesHere, false); @@ -289,6 +309,7 @@ public without sharing class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## ApexXSSFromURLParam + **Since:** 5.5.3 **Priority:** Medium (3) @@ -297,6 +318,7 @@ Makes sure that all values obtained from URL parameters are properly escaped / s to avoid XSS attacks. **Example(s):** + ``` public without sharing class Foo { String unescapedstring = ApexPage.getCurrentPage().getParameters.get('url_param'); diff --git a/docs/pages/pmd/rules/apex/style.md b/docs/pages/pmd/rules/apex/style.md index 465f5756c..0885a4dca 100644 --- a/docs/pages/pmd/rules/apex/style.md +++ b/docs/pages/pmd/rules/apex/style.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/rulesets/apex/style.xml --- ## AvoidGlobalModifier + **Since:** 5.5.0 **Priority:** Medium (3) @@ -15,6 +16,7 @@ Global classes should be avoided (especially in managed packages) as they can ne Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in. **Example(s):** + ``` global class Unchangeable { global UndeletableType unchangable(UndeletableType param) { @@ -32,6 +34,7 @@ global class Unchangeable { |cc_block_highlighting|false|Code Climate Block Highlighting| ## AvoidLogicInTrigger + **Since:** 5.5.0 **Priority:** Medium (3) @@ -42,6 +45,7 @@ Therefore delegate the triggers work to a regular class (often called Trigger ha See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices **Example(s):** + ``` trigger Accounts on Account (before insert, before update, before delete, after insert, after update, after delete, after undelete) { for(Account acc : Trigger.new) { @@ -67,6 +71,7 @@ trigger Accounts on Account (before insert, before update, before delete, after |cc_block_highlighting|false|Code Climate Block Highlighting| ## ClassNamingConventions + **Since:** 5.5.0 **Priority:** High (1) @@ -74,6 +79,7 @@ trigger Accounts on Account (before insert, before update, before delete, after Class names should always begin with an upper case character. **Example(s):** + ``` public class Foo {} ``` @@ -87,6 +93,7 @@ public class Foo {} |cc_block_highlighting|false|Code Climate Block Highlighting| ## MethodNamingConventions + **Since:** 5.5.0 **Priority:** High (1) @@ -94,6 +101,7 @@ public class Foo {} Method names should always begin with a lower case character, and should not contain underscores. **Example(s):** + ``` public class Foo { public void fooStuff() { @@ -110,6 +118,7 @@ public class Foo { |cc_block_highlighting|false|Code Climate Block Highlighting| ## MethodWithSameNameAsEnclosingClass + **Since:** 5.5.0 **Priority:** Medium (3) @@ -117,6 +126,7 @@ public class Foo { Non-constructor methods should not have the same name as the enclosing class. **Example(s):** + ``` public class MyClass { // this is OK because it is a constructor @@ -135,6 +145,7 @@ public class MyClass { |cc_block_highlighting|false|Code Climate Block Highlighting| ## VariableNamingConventions + **Since:** 5.5.0 **Priority:** High (1) @@ -144,6 +155,7 @@ checks for final variables that should be fully capitalized and non-final variab that should not include underscores. **Example(s):** + ``` public class Foo { public static final Integer MY_NUM = 0; diff --git a/docs/pages/pmd/rules/ecmascript/basic.md b/docs/pages/pmd/rules/ecmascript/basic.md index e9a192bb8..31967073d 100644 --- a/docs/pages/pmd/rules/ecmascript/basic.md +++ b/docs/pages/pmd/rules/ecmascript/basic.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_ecmascript.html editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/basic.xml --- ## AssignmentInOperand + **Since:** 5.0 **Priority:** Medium High (2) @@ -15,6 +16,7 @@ Avoid assignments in operands; this can make code more complicated and harder to indicative of the bug where the assignment operator '=' was used instead of the equality operator '=='. **Example(s):** + ``` var x = 2; // Bad @@ -39,6 +41,7 @@ function getX() { |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement| ## AvoidTrailingComma + **Since:** 5.1 **Priority:** High (1) @@ -46,6 +49,7 @@ function getX() { This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. **Example(s):** + ``` function(arg) { var obj1 = { a : 1 }; // Ok @@ -64,6 +68,7 @@ function(arg) { |allowArrayLiteral|false|Allow a trailing comma within an array literal| ## ConsistentReturn + **Since:** 5.0 **Priority:** Medium High (2) @@ -73,6 +78,7 @@ However, when a function does use returns they should all have a value, or all w usage is likely a bug, or at best poor style. **Example(s):** + ``` // Ok function foo() { @@ -100,6 +106,7 @@ function bar() { |recordingComments|true|Specifies that comments are produced in the AST.| ## EqualComparison + **Since:** 5.0 **Priority:** Medium (3) @@ -108,6 +115,7 @@ Using == in condition may lead to unexpected results, as the variables are autom same type. The === operator avoids the casting. **Example(s):** + ``` // Ok if (someVar === true) { @@ -128,6 +136,7 @@ if (someVar != 3) { ``` ## GlobalVariable + **Since:** 5.0 **Priority:** High (1) @@ -136,6 +145,7 @@ This rule helps to avoid using accidently global variables by simply missing the Global variables can lead to side-effects that are hard to debug. **Example(s):** + ``` function(arg) { notDeclaredVariable = 1; // this will create a global variable and trigger the rule @@ -147,6 +157,7 @@ function(arg) { ``` ## InnaccurateNumericLiteral + **Since:** 5.0 **Priority:** Medium High (2) @@ -155,6 +166,7 @@ The numeric literal will have at different value at runtime, which can happen if precision in a floating point number. This may result in numeric calculations being in error. **Example(s):** + ``` var a = 9; // Ok var b = 999999999999999; // Ok @@ -166,6 +178,7 @@ var z = 1.12345678901234567; // Not good ``` ## ScopeForInVariable + **Since:** 5.0 **Priority:** High (1) @@ -178,6 +191,7 @@ the for-in loop will be gone. Since the for-in variable name is most likely int is better to explicitly scope the variable name to the nearest enclosing scope with 'var'. **Example(s):** + ``` // Ok function foo() { @@ -208,6 +222,7 @@ function bar() { ``` ## UnreachableCode + **Since:** 5.0 **Priority:** High (1) @@ -216,6 +231,7 @@ A 'return', 'break', 'continue', or 'throw' statement should be the last in a bl will never execute. This is a bug, or extremely poor style. **Example(s):** + ``` // Ok function foo() { @@ -230,6 +246,7 @@ function bar() { ``` ## UseBaseWithParseInt + **Since:** 5.0.1 **Priority:** High (1) @@ -237,6 +254,7 @@ function bar() { TODO **Example(s):** + ``` parseInt("10",base); ``` diff --git a/docs/pages/pmd/rules/ecmascript/braces.md b/docs/pages/pmd/rules/ecmascript/braces.md index 6574ed850..42a080587 100644 --- a/docs/pages/pmd/rules/ecmascript/braces.md +++ b/docs/pages/pmd/rules/ecmascript/braces.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_ecmascript.html editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/braces.xml --- ## ForLoopsMustUseBraces + **Since:** 5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/braces.xml Avoid using 'for' statements without using curly braces. **Example(s):** + ``` // Ok for (var i = 0; i < 42; i++) { @@ -26,6 +28,7 @@ for (var i = 0; i < 42; i++) ``` ## IfElseStmtsMustUseBraces + **Since:** 5.0 **Priority:** Medium (3) @@ -33,6 +36,7 @@ for (var i = 0; i < 42; i++) Avoid using if..else statements without using curly braces. **Example(s):** + ``` // Ok if (foo) { @@ -49,6 +53,7 @@ else ``` ## IfStmtsMustUseBraces + **Since:** 5.0 **Priority:** Medium (3) @@ -56,6 +61,7 @@ else Avoid using if statements without using curly braces. **Example(s):** + ``` // Ok if (foo) { @@ -68,6 +74,7 @@ if (foo) ``` ## WhileLoopsMustUseBraces + **Since:** 5.0 **Priority:** Medium (3) @@ -75,6 +82,7 @@ if (foo) Avoid using 'while' statements without using curly braces. **Example(s):** + ``` // Ok while (true) { diff --git a/docs/pages/pmd/rules/ecmascript/unnecessary.md b/docs/pages/pmd/rules/ecmascript/unnecessary.md index 02e1211c7..34b353857 100644 --- a/docs/pages/pmd/rules/ecmascript/unnecessary.md +++ b/docs/pages/pmd/rules/ecmascript/unnecessary.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_ecmascript.html editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/unnecessary.xml --- ## NoElseReturn + **Since:** 5.5.0 **Priority:** Medium (3) @@ -17,6 +18,7 @@ The else block in a if-else-construct is unnecessary if the `if` block contains See also: http://eslint.org/docs/rules/no-else-return **Example(s):** + ``` // Bad: if (x) { @@ -33,6 +35,7 @@ return z; ``` ## UnnecessaryBlock + **Since:** 5.0 **Priority:** Medium (3) @@ -42,6 +45,7 @@ An unnecessary Block is present. Such Blocks are often used in other languages be misleading. Considering removing this unnecessary Block. **Example(s):** + ``` if (foo) { // Ok @@ -54,6 +58,7 @@ if (bar) { ``` ## UnnecessaryParentheses + **Since:** 5.0 **Priority:** Medium Low (4) @@ -61,6 +66,7 @@ if (bar) { Unnecessary parentheses should be removed. **Example(s):** + ``` var x = 1; // Ok var y = (1 + 1); // Ok diff --git a/docs/pages/pmd/rules/java/android.md b/docs/pages/pmd/rules/java/android.md index c9ff23e6a..703492904 100644 --- a/docs/pages/pmd/rules/java/android.md +++ b/docs/pages/pmd/rules/java/android.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/android.xml --- ## CallSuperFirst + **Since:** 4.2.5 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/android.xml Super should be called at the start of the method **Example(s):** + ``` public class DummyActivity extends Activity { public void onCreate(Bundle bundle) { @@ -24,6 +26,7 @@ public class DummyActivity extends Activity { ``` ## CallSuperLast + **Since:** 4.2.5 **Priority:** Medium (3) @@ -31,6 +34,7 @@ public class DummyActivity extends Activity { Super should be called at the end of the method **Example(s):** + ``` public class DummyActivity extends Activity { public void onPause() { @@ -41,6 +45,7 @@ public class DummyActivity extends Activity { ``` ## DoNotHardCodeSDCard + **Since:** 4.2.6 **Priority:** Medium (3) @@ -48,6 +53,7 @@ public class DummyActivity extends Activity { Use Environment.getExternalStorageDirectory() instead of "/sdcard" **Example(s):** + ``` public class MyActivity extends Activity { protected void foo() { diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md index 78eb82222..50f170b6f 100644 --- a/docs/pages/pmd/rules/java/basic.md +++ b/docs/pages/pmd/rules/java/basic.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/basic.xml --- ## AvoidBranchingStatementAsLastInLoop + **Since:** 5.0 **Priority:** Medium High (2) @@ -15,6 +16,7 @@ Using a branching statement as the last part of a loop may be a bug, and/or is c Ensure that the usage is not a bug, or consider using another approach. **Example(s):** + ``` // unusual use of branching statement in a loop for (int i = 0; i < 10; i++) { @@ -41,6 +43,7 @@ for (int i = 0; i < 10; i++) { |checkBreakLoopTypes|[for, do, while]|Check for break statements in loop types| ## AvoidDecimalLiteralsInBigDecimalConstructor + **Since:** 3.4 **Priority:** Medium (3) @@ -56,6 +59,7 @@ exactly equal to 0.1, as one would expect. Therefore, it is generally recommend (String) constructor be used in preference to this one. **Example(s):** + ``` BigDecimal bd = new BigDecimal(1.123); // loss of precision, this would trigger the rule @@ -65,6 +69,7 @@ BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer v ``` ## AvoidMultipleUnaryOperators + **Since:** 4.2 **Priority:** Medium High (2) @@ -73,6 +78,7 @@ The use of multiple unary operators may be problematic, and/or confusing. Ensure that the intended usage is not a bug, or consider simplifying the expression. **Example(s):** + ``` // These are typo bugs, or at best needlessly complex and confusing: int i = - -1; @@ -94,6 +100,7 @@ int j = -~7; ``` ## AvoidThreadGroup + **Since:** 3.6 **Priority:** Medium (3) @@ -102,6 +109,7 @@ Avoid using java.lang.ThreadGroup; although it is intended to be used in a threa it contains methods that are not thread-safe. **Example(s):** + ``` public class Bar { void buz() { @@ -114,6 +122,7 @@ public class Bar { ``` ## AvoidUsingHardCodedIP + **Since:** 4.1 **Priority:** Medium (3) @@ -122,6 +131,7 @@ Application with hard-coded IP addresses can become impossible to deploy in some Externalizing IP adresses is preferable. **Example(s):** + ``` public class Foo { private String ip = "127.0.0.1"; // not recommended @@ -136,6 +146,7 @@ public class Foo { |pattern|^"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"$|Regular Expression| ## AvoidUsingOctalValues + **Since:** 3.9 **Priority:** Medium (3) @@ -144,6 +155,7 @@ Integer literals should not start with zero since this denotes that the rest of interpreted as an octal value. **Example(s):** + ``` int i = 012; // set i with 10 not 12 int j = 010; // set j with 8 not 10 @@ -157,6 +169,7 @@ k = i * j; // set k with 80 not 120 |strict|false|Detect violations between 00 and 07| ## BigIntegerInstantiation + **Since:** 3.9 **Priority:** Medium (3) @@ -165,6 +178,7 @@ Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteg for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN) **Example(s):** + ``` BigInteger bi = new BigInteger(1); // reference BigInteger.ONE instead BigInteger bi2 = new BigInteger("0"); // reference BigInteger.ZERO instead @@ -174,6 +188,7 @@ bi4 = new BigInteger(0); // reference BigInteger.ZERO instead ``` ## BooleanInstantiation + **Since:** 1.2 **Priority:** Medium High (2) @@ -181,12 +196,14 @@ bi4 = new BigInteger(0); // reference BigInteger.ZERO instead Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. **Example(s):** + ``` Boolean bar = new Boolean("true"); // unnecessary creation, just reference Boolean.TRUE; Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; ``` ## BrokenNullCheck + **Since:** 3.8 **Priority:** Medium High (2) @@ -195,6 +212,7 @@ The null check is broken since it will throw a NullPointerException itself. It is likely that you used || instead of && or vice versa. **Example(s):** + ``` public String bar(String string) { // should be && @@ -207,6 +225,7 @@ public String bar(String string) { ``` ## CheckResultSet + **Since:** 4.1 **Priority:** Medium (3) @@ -215,6 +234,7 @@ Always check the return values of navigation methods (next, previous, first, las If the value return is 'false', it should be handled properly. **Example(s):** + ``` Statement stat = conn.createStatement(); ResultSet rst = stat.executeQuery("SELECT name FROM person"); @@ -231,6 +251,7 @@ if (rst.next()) { // result is properly examined and used ``` ## CheckSkipResult + **Since:** 5.0 **Priority:** Medium (3) @@ -238,6 +259,7 @@ if (rst.next()) { // result is properly examined and used The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not. **Example(s):** + ``` public class Foo { @@ -258,6 +280,7 @@ public class Foo { ``` ## ClassCastExceptionWithToArray + **Since:** 3.4 **Priority:** Medium (3) @@ -267,6 +290,7 @@ the same class as the parameter of the toArray() method. Doing otherwise you wil in a ClassCastException. **Example(s):** + ``` Collection c = new ArrayList(); Integer obj = new Integer(1); @@ -280,6 +304,7 @@ Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); ``` ## CollapsibleIfStatements + **Since:** 3.1 **Priority:** Medium (3) @@ -287,6 +312,7 @@ Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. **Example(s):** + ``` void bar() { if (x) { // original implementation @@ -304,6 +330,7 @@ void bar() { ``` ## DontCallThreadRun + **Since:** 4.3 **Priority:** Medium Low (4) @@ -311,6 +338,7 @@ void bar() { Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior. **Example(s):** + ``` Thread t = new Thread(); t.run(); // use t.start() instead @@ -318,6 +346,7 @@ new Thread().run(); // same violation ``` ## DontUseFloatTypeForLoopIndices + **Since:** 4.3 **Priority:** Medium (3) @@ -327,6 +356,7 @@ unless you're certain that float provides enough precision and you have a compel performance need (space or time). **Example(s):** + ``` public class Count { public static void main(String[] args) { @@ -342,6 +372,7 @@ public class Count { ``` ## DoubleCheckedLocking + **Since:** 1.04 **Priority:** High (1) @@ -356,6 +387,7 @@ For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209 or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html **Example(s):** + ``` public class Foo { /*volatile */ Object baz = null; // fix for Java5 and later: volatile @@ -373,6 +405,7 @@ public class Foo { ``` ## ExtendsObject + **Since:** 5.0 **Priority:** Medium Low (4) @@ -380,12 +413,14 @@ public class Foo { No need to explicitly extend Object. **Example(s):** + ``` public class Foo extends Object { // not required } ``` ## ForLoopShouldBeWhileLoop + **Since:** 1.02 **Priority:** Medium (3) @@ -393,6 +428,7 @@ public class Foo extends Object { // not required Some for loops can be simplified to while loops, this makes them more concise. **Example(s):** + ``` public class Foo { void bar() { @@ -402,6 +438,7 @@ public class Foo { ``` ## JumbledIncrementer + **Since:** 1.0 **Priority:** Medium (3) @@ -409,6 +446,7 @@ public class Foo { Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. **Example(s):** + ``` public class JumbledIncrementerRule1 { public void foo() { @@ -422,6 +460,7 @@ public class JumbledIncrementerRule1 { ``` ## MisplacedNullCheck + **Since:** 3.5 **Priority:** Medium (3) @@ -430,6 +469,7 @@ The null check here is misplaced. If the variable is null a NullPointerException Either the check is useless (the variable will never be "null") or it is incorrect. **Example(s):** + ``` public class Foo { void bar() { @@ -447,6 +487,7 @@ public class Foo { ``` ## OverrideBothEqualsAndHashcode + **Since:** 0.4 **Priority:** Medium (3) @@ -454,6 +495,7 @@ public class Foo { Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. **Example(s):** + ``` public class Bar { // poor, missing a hashcode() method public boolean equals(Object o) { @@ -478,6 +520,7 @@ public class Foo { // perfect, both methods provided ``` ## ReturnFromFinallyBlock + **Since:** 1.05 **Priority:** Medium (3) @@ -485,6 +528,7 @@ public class Foo { // perfect, both methods provided Avoid returning from a finally block, this can discard exceptions. **Example(s):** + ``` public class Bar { public String foo() { @@ -500,6 +544,7 @@ public class Bar { ``` ## SimplifiedTernary + **Since:** 5.4.0 **Priority:** Medium (3) @@ -515,6 +560,7 @@ or `condition && foo` when the literalBoolean is false **Example(s):** + ``` public class Foo { public boolean test() { @@ -536,6 +582,7 @@ public class Foo { ``` ## UnconditionalIfStatement + **Since:** 1.5 **Priority:** Medium (3) @@ -543,6 +590,7 @@ public class Foo { Do not use "if" statements whose conditionals are always true or always false. **Example(s):** + ``` public class Foo { public void close() { diff --git a/docs/pages/pmd/rules/java/braces.md b/docs/pages/pmd/rules/java/braces.md index 3b520a068..9fac8304e 100644 --- a/docs/pages/pmd/rules/java/braces.md +++ b/docs/pages/pmd/rules/java/braces.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/braces.xml --- ## ForLoopsMustUseBraces + **Since:** 0.7 **Priority:** Medium (3) @@ -16,12 +17,14 @@ indentation is lost then it becomes difficult to separate the code being control from the rest. **Example(s):** + ``` for (int i = 0; i < 42; i++) foo(); ``` ## IfElseStmtsMustUseBraces + **Since:** 0.2 **Priority:** Medium (3) @@ -31,6 +34,7 @@ or indentation is lost then it becomes difficult to separate the code being cont from the rest. **Example(s):** + ``` // this is OK if (foo) x++; @@ -43,6 +47,7 @@ if (foo) ``` ## IfStmtsMustUseBraces + **Since:** 1.0 **Priority:** Medium (3) @@ -52,6 +57,7 @@ formatting or indentation is lost then it becomes difficult to separate the code controlled from the rest. **Example(s):** + ``` if (foo) // not recommended x++; @@ -62,6 +68,7 @@ if (foo) { // preferred approach ``` ## WhileLoopsMustUseBraces + **Since:** 0.7 **Priority:** Medium (3) @@ -71,6 +78,7 @@ formatting or indentation is lost then it becomes difficult to separate the code controlled from the rest. **Example(s):** + ``` while (true) // not recommended x++; diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md index 62a91a3ab..5b48edda4 100644 --- a/docs/pages/pmd/rules/java/clone.md +++ b/docs/pages/pmd/rules/java/clone.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/clone.xml --- ## CloneMethodMustBePublic + **Since:** 5.4.0 **Priority:** Medium (3) @@ -15,6 +16,7 @@ The java Manual says "By convention, classes that implement this interface shoul Object.clone (which is protected) with a public method." **Example(s):** + ``` public class Foo implements Cloneable { @Override @@ -35,6 +37,7 @@ public class Foo implements Cloneable { ``` ## CloneMethodMustImplementCloneable + **Since:** 1.9 **Priority:** Medium (3) @@ -42,6 +45,7 @@ public class Foo implements Cloneable { The method clone() should only be implemented if the class implements the Cloneable interface with the exception of a final method that only throws CloneNotSupportedException. **Example(s):** + ``` public class MyClass { public Object clone() throws CloneNotSupportedException { @@ -51,6 +55,7 @@ public class MyClass { ``` ## CloneMethodReturnTypeMustMatchClassName + **Since:** 5.4.0 **Priority:** Medium (3) @@ -61,6 +66,7 @@ of the clone method doesn't need to cast the returned clone to the correct type. Note: This is only possible with Java 1.5 or higher. **Example(s):** + ``` public class Foo implements Cloneable { @Override @@ -76,6 +82,7 @@ public class Foo implements Cloneable { ``` ## CloneThrowsCloneNotSupportedException + **Since:** 1.9 **Priority:** Medium (3) @@ -83,6 +90,7 @@ public class Foo implements Cloneable { The method clone() should throw a CloneNotSupportedException. **Example(s):** + ``` public class MyClass implements Cloneable{ public Object clone() { // will cause an error @@ -93,6 +101,7 @@ public class MyClass implements Cloneable{ ``` ## ProperCloneImplementation + **Since:** 1.4 **Priority:** Medium High (2) @@ -100,6 +109,7 @@ public class MyClass implements Cloneable{ Object clone() should be implemented with super.clone(). **Example(s):** + ``` class Foo{ public Object clone(){ diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md index 17cc32541..774419302 100644 --- a/docs/pages/pmd/rules/java/codesize.md +++ b/docs/pages/pmd/rules/java/codesize.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/codesize.xml --- ## CyclomaticComplexity + **Since:** 1.03 **Priority:** Medium (3) @@ -17,6 +18,7 @@ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate c high complexity, and 11+ is very high complexity. **Example(s):** + ``` public class Foo { // This has a Cyclomatic Complexity = 12 1 public void example() { @@ -65,6 +67,7 @@ public class Foo { // This has a Cyclomatic Complexity = 12 |reportLevel|10|Cyclomatic Complexity reporting threshold| ## ExcessiveClassLength + **Since:** 0.6 **Priority:** Medium (3) @@ -74,6 +77,7 @@ responsibilities that could be provided by external classes or functions. In bre apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` public class Foo { public void bar1() { @@ -102,6 +106,7 @@ public class Foo { |sigma||Sigma value| ## ExcessiveMethodLength + **Since:** 0.6 **Priority:** Medium (3) @@ -112,6 +117,7 @@ scrolling causes readers to lose focus. Try to reduce the method length by creating helper methods and removing any copy/pasted code. **Example(s):** + ``` public void doSomething() { System.out.println("Hello world!"); @@ -129,6 +135,7 @@ public void doSomething() { |sigma||Sigma value| ## ExcessiveParameterList + **Since:** 0.9 **Priority:** Medium (3) @@ -137,6 +144,7 @@ Methods with numerous parameters are a challenge to maintain, especially if most same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. **Example(s):** + ``` public void addPerson( // too many arguments liable to be mixed up int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { @@ -160,6 +168,7 @@ public void addPerson( // preferred approach |sigma||Sigma value| ## ExcessivePublicCount + **Since:** 1.04 **Priority:** Medium (3) @@ -170,6 +179,7 @@ smaller ones not only increases testability and reliability but also allows new developed easily. **Example(s):** + ``` public class Foo { public String value; @@ -193,6 +203,7 @@ public class Foo { |sigma||Sigma value| ## ModifiedCyclomaticComplexity + **Since:** 5.1.2 **Priority:** Medium (3) @@ -204,6 +215,7 @@ high complexity, and 11+ is very high complexity. Modified complexity treats swi decision point. **Example(s):** + ``` public class Foo { // This has a Cyclomatic Complexity = 9 1 public void example() { @@ -252,6 +264,7 @@ public class Foo { // This has a Cyclomatic Complexity = 9 |reportLevel|10|Cyclomatic Complexity reporting threshold| ## NcssConstructorCount + **Since:** 3.9 **Priority:** Medium (3) @@ -261,6 +274,7 @@ of code for a given constructor. NCSS ignores comments, and counts actual statem lines of code that are split are counted as one. **Example(s):** + ``` public class Foo extends Bar { public Foo() { @@ -285,6 +299,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## NcssMethodCount + **Since:** 3.9 **Priority:** Medium (3) @@ -294,6 +309,7 @@ of code for a given method. NCSS ignores comments, and counts actual statements. lines of code that are split are counted as one. **Example(s):** + ``` public class Foo extends Bar { public int methd() { @@ -318,6 +334,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## NcssTypeCount + **Since:** 3.9 **Priority:** Medium (3) @@ -327,6 +344,7 @@ of code for a given type. NCSS ignores comments, and counts actual statements. U lines of code that are split are counted as one. **Example(s):** + ``` public class Foo extends Bar { public Foo() { @@ -351,6 +369,7 @@ public class Foo extends Bar { |sigma||Sigma value| ## NPathComplexity + **Since:** 3.9 **Priority:** Medium (3) @@ -360,6 +379,7 @@ A threshold of 200 is generally considered the point where measures should be ta complexity and increase readability. **Example(s):** + ``` void bar() { // this is something more complex than it needs to be, if (y) { // it should be broken down into smaller methods or functions @@ -400,6 +420,7 @@ void bar() { // this is something more complex than it needs to be, |sigma||Sigma value| ## StdCyclomaticComplexity + **Since:** 5.1.2 **Priority:** Medium (3) @@ -410,6 +431,7 @@ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate c high complexity, and 11+ is very high complexity. **Example(s):** + ``` public class Foo { // This has a Cyclomatic Complexity = 12 1 public void example() { @@ -458,6 +480,7 @@ public class Foo { // This has a Cyclomatic Complexity = 12 |reportLevel|10|Cyclomatic Complexity reporting threshold| ## TooManyFields + **Since:** 3.0 **Priority:** Medium (3) @@ -467,6 +490,7 @@ possibly through grouping related fields in new objects. For example, a class w city/state/zip fields could park them within a single Address field. **Example(s):** + ``` public class Person { // too many separate fields int birthYear; @@ -489,6 +513,7 @@ public class Person { // this is more manageable |maxfields|15|Max allowable fields| ## TooManyMethods + **Since:** 4.2 **Priority:** Medium (3) diff --git a/docs/pages/pmd/rules/java/comments.md b/docs/pages/pmd/rules/java/comments.md index 4a98e3a09..96007472d 100644 --- a/docs/pages/pmd/rules/java/comments.md +++ b/docs/pages/pmd/rules/java/comments.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/comments.xml --- ## CommentContent + **Since:** 5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/comments.xml A rule for the politically correct... we don't want to offend anyone. **Example(s):** + ``` // OMG, this is horrible, Bob is an idiot !!! ``` @@ -27,6 +29,7 @@ A rule for the politically correct... we don't want to offend anyone. |wordsAreRegex|false|Use regular expressions| ## CommentDefaultAccessModifier + **Since:** 5.4.0 **Priority:** Medium (3) @@ -36,6 +39,7 @@ To avoid mistakes if we want that a Method, Field or Nested class have a default By default the comment must be /* default */, if you want another, you have to provide a regex. **Example(s):** + ``` public class Foo { final String stringValue = "some string"; @@ -66,6 +70,7 @@ public class Foo { |regex||Regular expression| ## CommentRequired + **Since:** 5.1 **Priority:** Medium (3) @@ -73,6 +78,7 @@ public class Foo { Denotes whether comments are required (or unwanted) for specific language elements. **Example(s):** + ``` /** * @@ -93,6 +99,7 @@ Denotes whether comments are required (or unwanted) for specific language elemen |headerCommentRequirement|Required|Header comments. Possible values: [Required, Ignored, Unwanted]| ## CommentSize + **Since:** 5.0 **Priority:** Medium (3) @@ -100,6 +107,7 @@ Denotes whether comments are required (or unwanted) for specific language elemen Determines whether the dimensions of non-header comments found are within the specified limits. **Example(s):** + ``` /** * diff --git a/docs/pages/pmd/rules/java/controversial.md b/docs/pages/pmd/rules/java/controversial.md index 32d90d960..9ca7454da 100644 --- a/docs/pages/pmd/rules/java/controversial.md +++ b/docs/pages/pmd/rules/java/controversial.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/controversial.xml --- ## AssignmentInOperand + **Since:** 1.03 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/controversial.xml Avoid assignments in operands; this can make code more complicated and harder to read. **Example(s):** + ``` public void bar() { int x = 2; @@ -33,6 +35,7 @@ public void bar() { |allowIf|false|Allow assignment within the conditional expression of an if statement| ## AtLeastOneConstructor + **Since:** 1.04 **Priority:** Medium (3) @@ -40,6 +43,7 @@ public void bar() { Each class should declare at least one constructor. **Example(s):** + ``` public class Foo { // missing constructor @@ -49,6 +53,7 @@ public class Foo { ``` ## AvoidAccessibilityAlteration + **Since:** 4.1 **Priority:** Medium (3) @@ -58,6 +63,7 @@ as the interface PrivilegedAction, allows for the runtime alteration of variable method visibility, even if they are private. This violates the principle of encapsulation. **Example(s):** + ``` import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; @@ -89,6 +95,7 @@ public class Violation { ``` ## AvoidFinalLocalVariable + **Since:** 4.1 **Priority:** Medium (3) @@ -96,6 +103,7 @@ public class Violation { Avoid using final local variables, turn them into fields. **Example(s):** + ``` public class MyClass { public void foo() { @@ -105,6 +113,7 @@ public class MyClass { ``` ## AvoidLiteralsInIfCondition + **Since:** 4.2.6 **Priority:** Medium (3) @@ -114,6 +123,7 @@ or private members with descriptive names maintainability is enhanced. By defaul More exceptions can be defined with the property "ignoreMagicNumbers". **Example(s):** + ``` private static final int MAX_NUMBER_OF_REQUESTS = 10; @@ -142,6 +152,7 @@ public void checkRequests() { |ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored| ## AvoidPrefixingMethodParameters + **Since:** 5.0 **Priority:** Medium Low (4) @@ -151,6 +162,7 @@ To indicate whether or not a parameter will be modify in a method, its better to behavior with Javadoc. **Example(s):** + ``` // Not really clear public class Foo { @@ -179,6 +191,7 @@ public class Foo { ``` ## AvoidUsingNativeCode + **Since:** 4.1 **Priority:** Medium High (2) @@ -187,6 +200,7 @@ Unnecessary reliance on Java Native Interface (JNI) calls directly reduces appli and increases the maintenance burden. **Example(s):** + ``` public class SomeJNIClass { @@ -205,6 +219,7 @@ public class SomeJNIClass { ``` ## AvoidUsingShortType + **Since:** 4.1 **Priority:** High (1) @@ -215,6 +230,7 @@ and convert the int back to a short. Thus any storage gains found through use of adverse impacts on performance. **Example(s):** + ``` public class UsingShort { private short doNotUseShort = 0; @@ -227,6 +243,7 @@ public class UsingShort { ``` ## AvoidUsingVolatile + **Since:** 4.1 **Priority:** Medium High (2) @@ -236,6 +253,7 @@ a good expertise of the Java Memory Model. Moreover, its range of action is some the volatile keyword should not be used for maintenance purpose and portability. **Example(s):** + ``` public class ThrDeux { private volatile String var1; // not suggested @@ -244,6 +262,7 @@ public class ThrDeux { ``` ## CallSuperInConstructor + **Since:** 3.0 **Priority:** Medium (3) @@ -252,6 +271,7 @@ It is a good practice to call super() in a constructor. If super() is not called another constructor (such as an overloaded constructor) is called, this rule will not report it. **Example(s):** + ``` public class Foo extends Bar{ public Foo() { @@ -267,6 +287,7 @@ public class Foo extends Bar{ ``` ## DataflowAnomalyAnalysis + **Since:** 3.9 **Priority:** Low (5) @@ -279,6 +300,7 @@ From those informations there can be found various problems. 3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug. **Example(s):** + ``` public void foo() { int buz = 5; @@ -296,6 +318,7 @@ public void foo() { |maxPaths|1000|Maximum number of checked paths per method. A lower value will increase the performance of the rule but may decrease anomalies found.| ## DefaultPackage + **Since:** 3.4 **Priority:** Medium (3) @@ -304,6 +327,7 @@ Use explicit scoping instead of accidental usage of default package private leve The rule allows methods and fields annotated with Guava's @VisibleForTesting. ## DoNotCallGarbageCollectionExplicitly + **Since:** 4.2 **Priority:** Medium High (2) @@ -314,6 +338,7 @@ Moreover, "modern" jvms do a very good job handling garbage collections. If memo leaks develop within an application, it should be dealt with JVM options rather than within the code itself. **Example(s):** + ``` public class GCCall { public GCCall() { @@ -339,6 +364,7 @@ public class GCCall { ``` ## DontImportSun + **Since:** 1.5 **Priority:** Medium Low (4) @@ -346,12 +372,14 @@ public class GCCall { Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. **Example(s):** + ``` import sun.misc.foo; public class Foo {} ``` ## NullAssignment + **Since:** 1.02 **Priority:** Medium (3) @@ -362,6 +390,7 @@ of assignment is an indication that the programmer doesn't completely understand NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. **Example(s):** + ``` public void bar() { Object x = null; // this is OK @@ -373,6 +402,7 @@ public void bar() { ``` ## OneDeclarationPerLine + **Since:** 5.0 **Priority:** Medium Low (4) @@ -381,6 +411,7 @@ Java allows the use of several variables declaration of the same type on one lin can lead to quite messy code. This rule looks for several declarations on the same line. **Example(s):** + ``` String name; // separate declarations String lastname; @@ -399,6 +430,7 @@ String name, |strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.| ## OnlyOneReturn + **Since:** 1.0 **Priority:** Medium (3) @@ -406,6 +438,7 @@ String name, A method should have only one exit point, and that should be the last statement in the method. **Example(s):** + ``` public class OneReturnOnly1 { public void foo(int x) { @@ -418,6 +451,7 @@ public class OneReturnOnly1 { ``` ## SuspiciousOctalEscape + **Since:** 1.5 **Priority:** Medium (3) @@ -434,6 +468,7 @@ e.g. "\038" is interpreted as the octal escape sequence "\03" followed by the literal character "8". **Example(s):** + ``` public void foo() { // interpreted as octal 12, followed by character '8' @@ -442,6 +477,7 @@ public void foo() { ``` ## UnnecessaryConstructor + **Since:** 1.0 **Priority:** Medium (3) @@ -450,6 +486,7 @@ This rule detects when a constructor is not necessary; i.e., when there is only its public, has an empty body, and takes no arguments. **Example(s):** + ``` public class Foo { public Foo() {} @@ -457,6 +494,7 @@ public class Foo { ``` ## UnnecessaryParentheses + **Since:** 3.1 **Priority:** Medium (3) @@ -464,6 +502,7 @@ public class Foo { Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. **Example(s):** + ``` public class Foo { boolean bar() { @@ -473,6 +512,7 @@ public class Foo { ``` ## UseConcurrentHashMap + **Since:** 4.2.6 **Priority:** Medium (3) @@ -481,6 +521,7 @@ Since Java5 brought a new implementation of the Map designed for multi-threaded perform efficient map reads without blocking other threads. **Example(s):** + ``` public class ConcurrentApp { public void getMyInstance() { @@ -494,6 +535,7 @@ public class ConcurrentApp { ``` ## UseObjectForClearerAPI + **Since:** 4.2.6 **Priority:** Medium (3) @@ -506,6 +548,7 @@ point to pass extra data, you'll be able to do so by simply modifying or extendi your API. **Example(s):** + ``` public class MyClass { public void connect(String username, diff --git a/docs/pages/pmd/rules/java/coupling.md b/docs/pages/pmd/rules/java/coupling.md index ac7168297..30f6880a9 100644 --- a/docs/pages/pmd/rules/java/coupling.md +++ b/docs/pages/pmd/rules/java/coupling.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/coupling.xml --- ## CouplingBetweenObjects + **Since:** 1.04 **Priority:** Medium (3) @@ -15,6 +16,7 @@ This rule counts the number of unique attributes, local variables, and return ty A number higher than the specified threshold can indicate a high degree of coupling. **Example(s):** + ``` import com.Blah; import org.Bar; @@ -41,6 +43,7 @@ public class Foo { |threshold|20|Unique type reporting threshold| ## ExcessiveImports + **Since:** 1.04 **Priority:** Medium (3) @@ -50,6 +53,7 @@ counts the number of unique imports and reports a violation if the count is abov user-specified threshold. **Example(s):** + ``` import blah.blah.Baz; import blah.blah.Bif; @@ -68,6 +72,7 @@ public class Foo { |sigma||Sigma value| ## LawOfDemeter + **Since:** 5.0 **Priority:** Medium (3) @@ -80,6 +85,7 @@ http://www.ccs.neu.edu/home/lieber/LoD.html; http://en.wikipedia.org/wiki/Law_of_Demeter **Example(s):** + ``` public class Foo { /** @@ -105,6 +111,7 @@ public class Foo { ``` ## LooseCoupling + **Since:** 0.7 **Priority:** Medium (3) @@ -114,6 +121,7 @@ implementations in the future as requirements change. Whenever available, refere by their interface types provides much more flexibility. **Example(s):** + ``` // sub-optimal approach private ArrayList list = new ArrayList(); @@ -131,6 +139,7 @@ public Set getFoo() { ``` ## LoosePackageCoupling + **Since:** 5.0 **Priority:** Medium (3) @@ -139,6 +148,7 @@ Avoid using classes from the configured package hierarchy outside of the package except when using one of the configured allowed classes. **Example(s):** + ``` package some.package; diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index 2a919a596..b0960aa3a 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/design.xml --- ## AbstractClassWithoutAbstractMethod + **Since:** 3.0 **Priority:** Medium (3) @@ -17,6 +18,7 @@ abstract methods. If the class is intended to be used as a base class only (not directly) a protected constructor can be provided prevent direct instantiation. **Example(s):** + ``` public abstract class Foo { void int method1() { ... } @@ -27,6 +29,7 @@ public abstract class Foo { ``` ## AbstractClassWithoutAnyMethod + **Since:** 4.2 **Priority:** High (1) @@ -36,6 +39,7 @@ that is not meant to be instantiated. In this case, it is probably better to use protected constructor in order to prevent instantiation than make the class misleadingly abstract. **Example(s):** + ``` public class abstract Example { String field; @@ -44,6 +48,7 @@ public class abstract Example { ``` ## AccessorClassGeneration + **Since:** 1.04 **Priority:** Medium (3) @@ -55,6 +60,7 @@ to invoke a new hidden package scope constructor that takes the interface as a s This turns a private constructor effectively into one with package scope, and is challenging to discern. **Example(s):** + ``` public class Outer { void method(){ @@ -67,6 +73,7 @@ public class Outer { ``` ## AccessorMethodGeneration + **Since:** 5.5.4 **Priority:** Medium (3) @@ -76,6 +83,7 @@ with package-private visibility. This adds overhead, and to the dex method count be avoided by changing the visibility of the field / method from private to package-private. **Example(s):** + ``` public class OuterClass { private int counter; @@ -94,6 +102,7 @@ public class OuterClass { ``` ## AssignmentToNonFinalStatic + **Since:** 2.2 **Priority:** Medium (3) @@ -101,6 +110,7 @@ public class OuterClass { Identifies a possible unsafe usage of a static field. **Example(s):** + ``` public class StaticField { static int x; @@ -111,6 +121,7 @@ public class StaticField { ``` ## AvoidDeeplyNestedIfStmts + **Since:** 1.0 **Priority:** Medium (3) @@ -118,6 +129,7 @@ public class StaticField { Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. **Example(s):** + ``` public class Foo { public void bar(int x, int y, int z) { @@ -139,6 +151,7 @@ public class Foo { |problemDepth|3|The if statement depth reporting threshold| ## AvoidInstanceofChecksInCatchClause + **Since:** 3.0 **Priority:** Medium (3) @@ -146,6 +159,7 @@ public class Foo { Each caught exception type should be handled in its own catch clause. **Example(s):** + ``` try { // Avoid this // do something @@ -162,6 +176,7 @@ try { // Prefer this: ``` ## AvoidProtectedFieldInFinalClass + **Since:** 2.1 **Priority:** Medium (3) @@ -170,6 +185,7 @@ Do not use protected fields in final classes since they cannot be subclassed. Clarify your intent by using private or package access modifiers instead. **Example(s):** + ``` public final class Bar { private int x; @@ -179,6 +195,7 @@ public final class Bar { ``` ## AvoidProtectedMethodInFinalClassNotExtending + **Since:** 5.1 **Priority:** Medium (3) @@ -188,6 +205,7 @@ only be allowed in final classes that extend other classes with protected method visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead. **Example(s):** + ``` public final class Foo { private int bar() {} @@ -196,6 +214,7 @@ public final class Foo { ``` ## AvoidReassigningParameters + **Since:** 1.0 **Priority:** Medium High (2) @@ -203,6 +222,7 @@ public final class Foo { Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. **Example(s):** + ``` public class Foo { private void foo(String bar) { @@ -212,6 +232,7 @@ public class Foo { ``` ## AvoidSynchronizedAtMethodLevel + **Since:** 3.0 **Priority:** Medium (3) @@ -221,6 +242,7 @@ Block-level synchronization helps to ensure that only the code that needs synchr gets it. **Example(s):** + ``` public class Foo { // Try to avoid this: @@ -245,6 +267,7 @@ public class Foo { ``` ## BadComparison + **Since:** 1.8 **Priority:** Medium (3) @@ -253,11 +276,13 @@ Avoid equality comparisons with Double.NaN. Due to the implicit lack of represen precision when comparing floating point numbers these are likely to cause logic errors. **Example(s):** + ``` boolean x = (y == Double.NaN); ``` ## ClassWithOnlyPrivateConstructorsShouldBeFinal + **Since:** 4.1 **Priority:** High (1) @@ -266,6 +291,7 @@ A class with only private constructors should be final, unless the private const is invoked by a inner class. **Example(s):** + ``` public class Foo { //Should be final private Foo() { } @@ -273,6 +299,7 @@ public class Foo { //Should be final ``` ## CloseResource + **Since:** 1.2.2 **Priority:** Medium (3) @@ -280,6 +307,7 @@ public class Foo { //Should be final Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use. **Example(s):** + ``` public class Bar { public void foo() { @@ -305,6 +333,7 @@ public class Bar { |closeTargets|[]|Methods which may close this resource| ## CompareObjectsWithEquals + **Since:** 3.2 **Priority:** Medium (3) @@ -312,6 +341,7 @@ public class Bar { Use equals() to compare object references; avoid comparing them with ==. **Example(s):** + ``` class Foo { boolean bar(String a, String b) { @@ -321,6 +351,7 @@ class Foo { ``` ## ConfusingTernary + **Since:** 1.9 **Priority:** Medium (3) @@ -336,6 +367,7 @@ rule makes the code easier to read. Also, this resolves trivial ordering proble as "does the error case go first?" or "does the common case go first?". **Example(s):** + ``` boolean bar(int x, int y) { return (x != y) ? diff : same; @@ -349,6 +381,7 @@ boolean bar(int x, int y) { |ignoreElseIf|false|Ignore conditions with an else-if case| ## ConstantsInInterface + **Since:** 5.5 **Priority:** Medium (3) @@ -357,6 +390,7 @@ Avoid constants in interfaces. Interfaces should define types, constants are imp better placed in classes or enums. See Effective Java, item 19. **Example(s):** + ``` public interface ConstantInterface { public static final int CONST1 = 1; // violation, no fields allowed in interface! @@ -387,6 +421,7 @@ public interface YetAnotherConstantInterface { |ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods| ## ConstructorCallsOverridableMethod + **Since:** 1.04 **Priority:** High (1) @@ -400,6 +435,7 @@ this includes method calls throughout the control flow graph - i.e., if a constr private method bar() that calls a public method buz(), this denotes a problem. **Example(s):** + ``` public class SeniorClass { public SeniorClass(){ @@ -422,6 +458,7 @@ public class JuniorClass extends SeniorClass { ``` ## DefaultLabelNotLastInSwitchStmt + **Since:** 1.5 **Priority:** Medium (3) @@ -429,6 +466,7 @@ public class JuniorClass extends SeniorClass { By convention, the default label should be the last label in a switch statement. **Example(s):** + ``` public class Foo { void bar(int a) { @@ -445,6 +483,7 @@ public class Foo { ``` ## EmptyMethodInAbstractClassShouldBeAbstract + **Since:** 4.1 **Priority:** High (1) @@ -453,6 +492,7 @@ Empty or auto-generated methods in an abstract class should be tagged as abstrac usage by developers who should be implementing their own versions in the concrete subclasses. **Example(s):** + ``` public abstract class ShouldBeAbstract { public Object couldBeAbstract() { @@ -466,6 +506,7 @@ public abstract class ShouldBeAbstract { ``` ## EqualsNull + **Since:** 1.9 **Priority:** High (1) @@ -473,6 +514,7 @@ public abstract class ShouldBeAbstract { Tests for null should not use the equals() method. The '==' operator should be used instead. **Example(s):** + ``` String x = "foo"; @@ -486,6 +528,7 @@ if (x == null) { // preferred ``` ## FieldDeclarationsShouldBeAtStartOfClass + **Since:** 5.0 **Priority:** Medium (3) @@ -493,6 +536,7 @@ if (x == null) { // preferred Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. **Example(s):** + ``` public class HelloWorldBean { @@ -517,6 +561,7 @@ public class HelloWorldBean { |ignoreEnumDeclarations|true|Ignore Enum Declarations that precede fields.| ## FinalFieldCouldBeStatic + **Since:** 1.1 **Priority:** Medium (3) @@ -525,6 +570,7 @@ If a final field is assigned to a compile-time constant, it could be made static in each object at runtime. **Example(s):** + ``` public class Foo { public final int BAR = 42; // this could be static and save some space @@ -532,6 +578,7 @@ public class Foo { ``` ## GodClass + **Since:** 5.0 **Priority:** Medium (3) @@ -545,6 +592,7 @@ Using Software Metrics to Characterize, Evaluate, and Improve the Design of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. ## IdempotentOperations + **Since:** 2.0 **Priority:** Medium (3) @@ -552,6 +600,7 @@ of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. Avoid idempotent operations - they have no effect. **Example(s):** + ``` public class Foo { public void bar() { @@ -562,6 +611,7 @@ public class Foo { ``` ## ImmutableField + **Since:** 2.0 **Priority:** Medium (3) @@ -570,6 +620,7 @@ Identifies private fields whose values never change once they are initialized ei of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. **Example(s):** + ``` public class Foo { private int x; // could be final @@ -583,6 +634,7 @@ public class Foo { ``` ## InstantiationToGetClass + **Since:** 2.0 **Priority:** Medium Low (4) @@ -590,6 +642,7 @@ public class Foo { Avoid instantiating an object just to call getClass() on it; use the .class public member instead. **Example(s):** + ``` // replace this Class c = new String().getClass(); @@ -599,6 +652,7 @@ Class c = String.class; ``` ## LogicInversion + **Since:** 5.0 **Priority:** Medium (3) @@ -606,6 +660,7 @@ Class c = String.class; Use opposite operator instead of negating the whole expression with a logic complement operator. **Example(s):** + ``` public boolean bar(int a, int b) { @@ -622,6 +677,7 @@ public boolean bar(int a, int b) { ``` ## MissingBreakInSwitch + **Since:** 3.0 **Priority:** Medium (3) @@ -630,6 +686,7 @@ Switch statements without break or return statements for each case option may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. **Example(s):** + ``` public void bar(int status) { switch(status) { @@ -651,6 +708,7 @@ public void bar(int status) { ``` ## MissingStaticMethodInNonInstantiatableClass + **Since:** 3.0 **Priority:** Medium (3) @@ -658,6 +716,7 @@ public void bar(int status) { A class that has private constructors and does not have any static methods or fields cannot be used. **Example(s):** + ``` // This class is unusable, since it cannot be // instantiated (private constructor), @@ -670,6 +729,7 @@ public class Foo { ``` ## NonCaseLabelInSwitchStatement + **Since:** 1.5 **Priority:** Medium (3) @@ -678,6 +738,7 @@ A non-case label (e.g. a named break/continue label) was present in a switch sta This legal, but confusing. It is easy to mix up the case labels and the non-case labels. **Example(s):** + ``` public class Foo { void bar(int a) { @@ -695,6 +756,7 @@ public class Foo { ``` ## NonStaticInitializer + **Since:** 1.5 **Priority:** Medium (3) @@ -704,6 +766,7 @@ invoking the constructor). While this is a valid language construct, it is rare confusing. **Example(s):** + ``` public class MyClass { // this block gets run before any call to a constructor @@ -714,6 +777,7 @@ public class MyClass { ``` ## NonThreadSafeSingleton + **Since:** 3.4 **Priority:** Medium (3) @@ -731,6 +795,7 @@ performance penalty. [Reference](http://www.cs.umd.edu/~pugh/java/memoryModel/Do See Effective Java, item 48. **Example(s):** + ``` private static Foo foo = null; @@ -751,6 +816,7 @@ public static Foo getFoo() { |checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.| ## OptimizableToArrayCall + **Since:** 1.8 **Priority:** Medium (3) @@ -760,6 +826,7 @@ collection. Initial arrays that are too small are discarded in favour of new one that are the proper size. **Example(s):** + ``` List foos = getFoos(); @@ -772,6 +839,7 @@ Foo[] fooArray = foos.toArray(new Foo[foos.size()]); ``` ## PositionLiteralsFirstInCaseInsensitiveComparisons + **Since:** 5.1 **Priority:** Medium (3) @@ -780,6 +848,7 @@ Position literals first in comparisons, if the second argument is null then Null can be avoided, they will just return false. **Example(s):** + ``` class Foo { boolean bar(String x) { @@ -789,6 +858,7 @@ class Foo { ``` ## PositionLiteralsFirstInComparisons + **Since:** 3.3 **Priority:** Medium (3) @@ -797,6 +867,7 @@ Position literals first in comparisons, if the second argument is null then Null can be avoided, they will just return false. **Example(s):** + ``` class Foo { boolean bar(String x) { @@ -806,6 +877,7 @@ class Foo { ``` ## PreserveStackTrace + **Since:** 3.7 **Priority:** Medium (3) @@ -815,6 +887,7 @@ new exception will cause the original stack trace to be lost making it difficult effectively. **Example(s):** + ``` public class Foo { void good() { @@ -840,6 +913,7 @@ public class Foo { ``` ## ReturnEmptyArrayRatherThanNull + **Since:** 4.2 **Priority:** High (1) @@ -849,6 +923,7 @@ null reference. This removes the need for null checking all results and avoids i NullPointerExceptions. **Example(s):** + ``` public class Example { // Not a good idea... @@ -866,6 +941,7 @@ public class Example { ``` ## SimpleDateFormatNeedsLocale + **Since:** 2.0 **Priority:** Medium (3) @@ -874,6 +950,7 @@ Be sure to specify a Locale when creating SimpleDateFormat instances to ensure t formatting is used. **Example(s):** + ``` public class Foo { // Should specify Locale.US (or whatever) @@ -882,6 +959,7 @@ public class Foo { ``` ## SimplifyBooleanExpressions + **Since:** 1.05 **Priority:** Medium (3) @@ -889,6 +967,7 @@ public class Foo { Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. **Example(s):** + ``` public class Bar { // can be simplified to @@ -900,6 +979,7 @@ public class Bar { ``` ## SimplifyBooleanReturns + **Since:** 0.9 **Priority:** Medium (3) @@ -908,6 +988,7 @@ Avoid unnecessary if-then-else statements when returning a boolean. The result o the conditional test can be returned instead. **Example(s):** + ``` public boolean isBarEqualTo(int x) { @@ -925,6 +1006,7 @@ public boolean isBarEqualTo(int x) { ``` ## SimplifyConditional + **Since:** 3.1 **Priority:** Medium (3) @@ -932,6 +1014,7 @@ public boolean isBarEqualTo(int x) { No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. **Example(s):** + ``` class Foo { void bar(Object x) { @@ -943,6 +1026,7 @@ class Foo { ``` ## SingleMethodSingleton + **Since:** 5.4 **Priority:** Medium High (2) @@ -952,6 +1036,7 @@ is that the instance created using the overloaded method is not cached and so, for each call and new objects will be created for every invocation. **Example(s):** + ``` public class Singleton { @@ -970,6 +1055,7 @@ public static Singleton getInstance(Object obj){ ``` ## SingletonClassReturningNewInstance + **Since:** 5.4 **Priority:** Medium High (2) @@ -979,6 +1065,7 @@ is that the instance created using the overloaded method is not cached and so, for each call and new objects will be created for every invocation. **Example(s):** + ``` class Singleton { private static Singleton instance = null; @@ -991,6 +1078,7 @@ class Singleton { ``` ## SingularField + **Since:** 3.1 **Priority:** Medium (3) @@ -1000,6 +1088,7 @@ object to provide them to other methods. They may be better implemented as local within those methods. **Example(s):** + ``` public class Foo { private int x; // no reason to exist at the Foo instance level @@ -1018,6 +1107,7 @@ public class Foo { |checkInnerClasses|false|Check inner classes| ## SwitchDensity + **Since:** 1.02 **Priority:** Medium (3) @@ -1027,6 +1117,7 @@ is overloaded. Consider moving the statements into new methods or creating subc on the switch variable. **Example(s):** + ``` public class Foo { public void bar(int x) { @@ -1052,6 +1143,7 @@ public class Foo { |sigma||Sigma value| ## SwitchStmtsShouldHaveDefault + **Since:** 1.0 **Priority:** Medium (3) @@ -1059,6 +1151,7 @@ public class Foo { All switch statements should include a default option to catch any unspecified values. **Example(s):** + ``` public void bar() { int x = 2; @@ -1071,6 +1164,7 @@ public void bar() { ``` ## TooFewBranchesForASwitchStatement + **Since:** 4.2 **Priority:** Medium (3) @@ -1080,6 +1174,7 @@ cases is ill-advised, since switches are not as easy to understand as if-then st if-then statement to increase code readability. **Example(s):** + ``` // With a minimumNumberCaseForASwitch of 3 public class Foo { @@ -1102,6 +1197,7 @@ public class Foo { |minimumNumberCaseForASwitch|3|Minimum number of branches for a switch| ## UncommentedEmptyConstructor + **Since:** 3.4 **Priority:** Medium (3) @@ -1112,6 +1208,7 @@ constructors it is easier to distinguish between intentional (commented) and unintentional empty constructors. **Example(s):** + ``` public Foo() { // This constructor is intentionally empty. Nothing special is needed here. @@ -1125,6 +1222,7 @@ public Foo() { |ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not| ## UncommentedEmptyMethodBody + **Since:** 3.4 **Priority:** Medium (3) @@ -1135,12 +1233,14 @@ it is easier to distinguish between intentional (commented) and unintentional empty methods. **Example(s):** + ``` public void doSomething() { } ``` ## UnnecessaryLocalBeforeReturn + **Since:** 3.3 **Priority:** Medium (3) @@ -1148,6 +1248,7 @@ public void doSomething() { Avoid the creation of unnecessary local variables **Example(s):** + ``` public class Foo { public int foo() { @@ -1164,6 +1265,7 @@ public class Foo { |statementOrderMatters|true|If set to false this rule no longer requires the variable declaration and return statement to be on consecutive lines. Any variable that is used solely in a return statement will be reported.| ## UnsynchronizedStaticDateFormatter + **Since:** 3.6 **Priority:** Medium (3) @@ -1173,6 +1275,7 @@ for each thread. If multiple threads must access a static formatter, the formatt synchronized either on method or block level. **Example(s):** + ``` public class Foo { private static final SimpleDateFormat sdf = new SimpleDateFormat(); @@ -1186,6 +1289,7 @@ public class Foo { ``` ## UseCollectionIsEmpty + **Since:** 3.9 **Priority:** Medium (3) @@ -1194,6 +1298,7 @@ The isEmpty() method on java.util.Collection is provided to determine if a colle Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. **Example(s):** + ``` public class Foo { void good() { @@ -1213,6 +1318,7 @@ public class Foo { ``` ## UseLocaleWithCaseConversions + **Since:** 2.0 **Priority:** Medium (3) @@ -1221,6 +1327,7 @@ When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids have unusual conventions, i.e. Turkish. **Example(s):** + ``` class Foo { // BAD @@ -1238,6 +1345,7 @@ class Foo { ``` ## UseNotifyAllInsteadOfNotify + **Since:** 3.0 **Priority:** Medium (3) @@ -1246,6 +1354,7 @@ Thread.notify() awakens a thread monitoring the object. If more than one thread one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. **Example(s):** + ``` void bar() { x.notify(); @@ -1256,6 +1365,7 @@ void bar() { ``` ## UseUtilityClass + **Since:** 0.3 **Priority:** Medium (3) @@ -1267,6 +1377,7 @@ remember to add a private constructor to prevent instantiation. (Note, that this use was known before PMD 5.1.0 as UseSingleton). **Example(s):** + ``` public class MaybeAUtility { public static void foo() {} @@ -1275,6 +1386,7 @@ public class MaybeAUtility { ``` ## UseVarargs + **Since:** 5.0 **Priority:** Medium Low (4) @@ -1284,6 +1396,7 @@ sugar provides flexibility for users of these methods and constructors, allowing having to deal with the creation of an array. **Example(s):** + ``` public class Foo { public void foo(String s, Object[] args) { diff --git a/docs/pages/pmd/rules/java/empty.md b/docs/pages/pmd/rules/java/empty.md index 55767f44d..e02a136a6 100644 --- a/docs/pages/pmd/rules/java/empty.md +++ b/docs/pages/pmd/rules/java/empty.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/empty.xml --- ## EmptyCatchBlock + **Since:** 0.1 **Priority:** Medium (3) @@ -16,6 +17,7 @@ In most circumstances, this swallows an exception which should either be acted o or reported. **Example(s):** + ``` public void doSomething() { try { @@ -34,6 +36,7 @@ public void doSomething() { |allowExceptionNameRegex|^$|Empty blocks catching exceptions with names matching this regular expression will be skipped| ## EmptyFinallyBlock + **Since:** 0.4 **Priority:** Medium (3) @@ -41,6 +44,7 @@ public void doSomething() { Empty finally blocks serve no purpose and should be removed. **Example(s):** + ``` public class Foo { public void bar() { @@ -54,6 +58,7 @@ public class Foo { ``` ## EmptyIfStmt + **Since:** 0.1 **Priority:** Medium (3) @@ -61,6 +66,7 @@ public class Foo { Empty If Statement finds instances where a condition is checked but nothing is done about it. **Example(s):** + ``` public class Foo { void bar(int x) { @@ -72,6 +78,7 @@ public class Foo { ``` ## EmptyInitializer + **Since:** 5.0 **Priority:** Medium (3) @@ -79,6 +86,7 @@ public class Foo { Empty initializers serve no purpose and should be removed. **Example(s):** + ``` public class Foo { @@ -90,6 +98,7 @@ public class Foo { ``` ## EmptyStatementBlock + **Since:** 5.0 **Priority:** Medium (3) @@ -97,6 +106,7 @@ public class Foo { Empty block statements serve no purpose and should be removed. **Example(s):** + ``` public class Foo { @@ -111,6 +121,7 @@ public class Foo { ``` ## EmptyStatementNotInLoop + **Since:** 1.5 **Priority:** Medium (3) @@ -120,6 +131,7 @@ or 'while' loop is probably a bug. It could also be a double semicolon, which h and should be removed. **Example(s):** + ``` public void doit() { // this is probably not what you meant to do @@ -130,6 +142,7 @@ public void doit() { ``` ## EmptyStaticInitializer + **Since:** 1.5 **Priority:** Medium (3) @@ -137,6 +150,7 @@ public void doit() { An empty static initializer serve no purpose and should be removed. **Example(s):** + ``` public class Foo { static { @@ -146,6 +160,7 @@ public class Foo { ``` ## EmptySwitchStatements + **Since:** 1.0 **Priority:** Medium (3) @@ -153,6 +168,7 @@ public class Foo { Empty switch statements serve no purpose and should be removed. **Example(s):** + ``` public void bar() { int x = 2; @@ -164,6 +180,7 @@ public void bar() { ``` ## EmptySynchronizedBlock + **Since:** 1.3 **Priority:** Medium (3) @@ -171,6 +188,7 @@ public void bar() { Empty synchronized blocks serve no purpose and should be removed. **Example(s):** + ``` public class Foo { public void bar() { @@ -182,6 +200,7 @@ public class Foo { ``` ## EmptyTryBlock + **Since:** 0.4 **Priority:** Medium (3) @@ -189,6 +208,7 @@ public class Foo { Avoid empty try blocks - what's the point? **Example(s):** + ``` public class Foo { public void bar() { @@ -201,6 +221,7 @@ public class Foo { ``` ## EmptyWhileStmt + **Since:** 0.2 **Priority:** Medium (3) @@ -210,6 +231,7 @@ If it is a timing loop, then you should use Thread.sleep() for it; if it is a while loop that does a lot in the exit expression, rewrite it to make it clearer. **Example(s):** + ``` void bar(int a, int b) { while (a == b) { diff --git a/docs/pages/pmd/rules/java/finalizers.md b/docs/pages/pmd/rules/java/finalizers.md index 903ece8be..9b3101b03 100644 --- a/docs/pages/pmd/rules/java/finalizers.md +++ b/docs/pages/pmd/rules/java/finalizers.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/finalizers.xml --- ## AvoidCallingFinalize + **Since:** 3.0 **Priority:** Medium (3) @@ -15,6 +16,7 @@ The method Object.finalize() is called by the garbage collector on an object whe that there are no more references to the object. It should not be invoked by application logic. **Example(s):** + ``` void foo() { Bar b = new Bar(); @@ -23,6 +25,7 @@ void foo() { ``` ## EmptyFinalizer + **Since:** 1.5 **Priority:** Medium (3) @@ -30,6 +33,7 @@ void foo() { Empty finalize methods serve no purpose and should be removed. **Example(s):** + ``` public class Foo { protected void finalize() {} @@ -37,6 +41,7 @@ public class Foo { ``` ## FinalizeDoesNotCallSuperFinalize + **Since:** 1.5 **Priority:** Medium (3) @@ -44,6 +49,7 @@ public class Foo { If the finalize() is implemented, its last action should be to call super.finalize. **Example(s):** + ``` protected void finalize() { something(); @@ -52,6 +58,7 @@ protected void finalize() { ``` ## FinalizeOnlyCallsSuperFinalize + **Since:** 1.5 **Priority:** Medium (3) @@ -59,6 +66,7 @@ protected void finalize() { If the finalize() is implemented, it should do something besides just calling super.finalize(). **Example(s):** + ``` protected void finalize() { super.finalize(); @@ -66,6 +74,7 @@ protected void finalize() { ``` ## FinalizeOverloaded + **Since:** 1.5 **Priority:** Medium (3) @@ -74,6 +83,7 @@ Methods named finalize() should not have parameters. It is confusing and most l overload Object.finalize(). It will not be called by the VM. **Example(s):** + ``` public class Foo { // this is confusing and probably a bug @@ -83,6 +93,7 @@ public class Foo { ``` ## FinalizeShouldBeProtected + **Since:** 1.1 **Priority:** Medium (3) @@ -91,6 +102,7 @@ When overriding the finalize(), the new method should be set as protected. If m other classes may invoke it at inappropriate times. **Example(s):** + ``` public void finalize() { // do something diff --git a/docs/pages/pmd/rules/java/imports.md b/docs/pages/pmd/rules/java/imports.md index 7403ab773..2938c323c 100644 --- a/docs/pages/pmd/rules/java/imports.md +++ b/docs/pages/pmd/rules/java/imports.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/imports.xml --- ## DontImportJavaLang + **Since:** 0.5 **Priority:** Medium Low (4) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/imports.xml Avoid importing anything from the package 'java.lang'. These classes are automatically imported (JLS 7.5.3). **Example(s):** + ``` import java.lang.String; // this is unnecessary @@ -27,6 +29,7 @@ public class Foo {} ``` ## DuplicateImports + **Since:** 0.5 **Priority:** Medium Low (4) @@ -34,6 +37,7 @@ public class Foo {} Duplicate or overlapping import statements should be avoided. **Example(s):** + ``` import java.lang.String; import java.lang.*; @@ -41,6 +45,7 @@ public class Foo {} ``` ## ImportFromSamePackage + **Since:** 1.02 **Priority:** Medium (3) @@ -48,6 +53,7 @@ public class Foo {} There is no need to import a type that lives in the same package. **Example(s):** + ``` package foo; @@ -58,6 +64,7 @@ package foo; ``` ## TooManyStaticImports + **Since:** 4.1 **Priority:** Medium (3) @@ -68,6 +75,7 @@ Readers of your code (including you, a few months after you wrote it) will not k which class a static member comes from (Sun 1.5 Language Guide). **Example(s):** + ``` import static Lennon; import static Ringo; @@ -83,6 +91,7 @@ import static Yoko; // Too much ! |maximumStaticImports|4|All static imports can be disallowed by setting this to 0| ## UnnecessaryFullyQualifiedName + **Since:** 5.0 **Priority:** Medium Low (4) @@ -91,6 +100,7 @@ Import statements allow the use of non-fully qualified names. The use of a full which is covered by an import statement is redundant. Consider using the non-fully qualified name. **Example(s):** + ``` import java.util.List; @@ -101,6 +111,7 @@ public class Foo { ``` ## UnusedImports + **Since:** 1.0 **Priority:** Medium Low (4) @@ -108,6 +119,7 @@ public class Foo { Avoid the use of unused import statements to prevent unwanted dependencies. **Example(s):** + ``` // this is bad import java.io.File; diff --git a/docs/pages/pmd/rules/java/j2ee.md b/docs/pages/pmd/rules/java/j2ee.md index 5b1714cec..013793cd9 100644 --- a/docs/pages/pmd/rules/java/j2ee.md +++ b/docs/pages/pmd/rules/java/j2ee.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/j2ee.xml --- ## DoNotCallSystemExit + **Since:** 4.1 **Priority:** Medium (3) @@ -15,6 +16,7 @@ Web applications should not call System.exit(), since only the web container or application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). **Example(s):** + ``` public void bar() { System.exit(0); // never call this when running in an application server! @@ -25,6 +27,7 @@ public void foo() { ``` ## DoNotUseThreads + **Since:** 4.1 **Priority:** Medium (3) @@ -32,6 +35,7 @@ public void foo() { The J2EE specification explicitly forbids the use of threads. **Example(s):** + ``` // This is not allowed public class UsingThread extends Thread { @@ -47,6 +51,7 @@ public class OtherThread implements Runnable { ``` ## LocalHomeNamingConvention + **Since:** 4.0 **Priority:** Medium Low (4) @@ -54,6 +59,7 @@ public class OtherThread implements Runnable { The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. **Example(s):** + ``` public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper name @@ -61,6 +67,7 @@ public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper ``` ## LocalInterfaceSessionNamingConvention + **Since:** 4.0 **Priority:** Medium Low (4) @@ -68,6 +75,7 @@ public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper The Local Interface of a Session EJB should be suffixed by 'Local'. **Example(s):** + ``` public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name @@ -75,6 +83,7 @@ public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name ``` ## MDBAndSessionBeanNamingConvention + **Since:** 4.0 **Priority:** Medium Low (4) @@ -82,6 +91,7 @@ public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. **Example(s):** + ``` public class SomeBean implements SessionBean{} // proper name @@ -89,6 +99,7 @@ public class MissingTheProperSuffix implements SessionBean {} // non-standard ``` ## RemoteInterfaceNamingConvention + **Since:** 4.0 **Priority:** Medium Low (4) @@ -96,6 +107,7 @@ public class MissingTheProperSuffix implements SessionBean {} // non-standard Remote Interface of a Session EJB should not have a suffix. **Example(s):** + ``` /* Poor Session suffix */ public interface BadSuffixSession extends javax.ejb.EJBObject {} @@ -108,6 +120,7 @@ Remote Interface of a Session EJB should not have a suffix. ``` ## RemoteSessionInterfaceNamingConvention + **Since:** 4.0 **Priority:** Medium Low (4) @@ -115,6 +128,7 @@ Remote Interface of a Session EJB should not have a suffix. A Remote Home interface type of a Session EJB should be suffixed by 'Home'. **Example(s):** + ``` public interface MyBeautifulHome extends javax.ejb.EJBHome {} // proper name @@ -122,6 +136,7 @@ public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standar ``` ## StaticEJBFieldShouldBeFinal + **Since:** 4.1 **Priority:** Medium (3) @@ -131,6 +146,7 @@ with write access. However, static read-only fields are allowed. This ensures pr behavior especially when instances are distributed by the container on several JREs. **Example(s):** + ``` public class SomeEJB extends EJBObject implements EJBLocalHome { @@ -141,6 +157,7 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { ``` ## UseProperClassLoader + **Since:** 3.7 **Priority:** Medium (3) @@ -149,6 +166,7 @@ In J2EE, the getClassLoader() method might not work as expected. Use Thread.currentThread().getContextClassLoader() instead. **Example(s):** + ``` public class Foo { ClassLoader cl = Bar.class.getClassLoader(); diff --git a/docs/pages/pmd/rules/java/javabeans.md b/docs/pages/pmd/rules/java/javabeans.md index 5a2edfc82..7c00cee20 100644 --- a/docs/pages/pmd/rules/java/javabeans.md +++ b/docs/pages/pmd/rules/java/javabeans.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/javabeans.xml --- ## BeanMembersShouldSerialize + **Since:** 1.1 **Priority:** Medium (3) @@ -17,6 +18,7 @@ variables as transient is the safest and easiest modification. Accessor methods naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided. **Example(s):** + ``` private transient int someFoo; // good, it's transient private static int otherFoo; // also OK @@ -39,6 +41,7 @@ private int getMoreFoo(){ |prefix||A variable prefix to skip, i.e., m_| ## MissingSerialVersionUID + **Since:** 3.0 **Priority:** Medium (3) @@ -46,6 +49,7 @@ private int getMoreFoo(){ Serializable classes should provide a serialVersionUID field. **Example(s):** + ``` public class Foo implements java.io.Serializable { String name; diff --git a/docs/pages/pmd/rules/java/junit.md b/docs/pages/pmd/rules/java/junit.md index 7e0f3c143..5823e297d 100644 --- a/docs/pages/pmd/rules/java/junit.md +++ b/docs/pages/pmd/rules/java/junit.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/junit.xml --- ## JUnitAssertionsShouldIncludeMessage + **Since:** 1.04 **Priority:** Medium (3) @@ -15,6 +16,7 @@ JUnit assertions should include an informative message - i.e., use the three-arg assertEquals(), not the two-argument version. **Example(s):** + ``` public class Foo extends TestCase { public void testSomething() { @@ -27,6 +29,7 @@ public class Foo extends TestCase { ``` ## JUnitSpelling + **Since:** 1.0 **Priority:** Medium (3) @@ -34,6 +37,7 @@ public class Foo extends TestCase { Some JUnit framework methods are easy to misspell. **Example(s):** + ``` import junit.framework.*; @@ -44,6 +48,7 @@ public class Foo extends TestCase { ``` ## JUnitStaticSuite + **Since:** 1.0 **Priority:** Medium (3) @@ -51,6 +56,7 @@ public class Foo extends TestCase { The suite() method in a JUnit test needs to be both public and static. **Example(s):** + ``` import junit.framework.*; @@ -61,6 +67,7 @@ public class Foo extends TestCase { ``` ## JUnitTestContainsTooManyAsserts + **Since:** 5.0 **Priority:** Medium (3) @@ -70,6 +77,7 @@ it is harder to verify correctness. Consider breaking the test scenario into mu Customize the maximum number of assertions used by this Rule to suit your needs. **Example(s):** + ``` public class MyTestCase extends TestCase { // Ok @@ -94,6 +102,7 @@ public class MyTestCase extends TestCase { |maximumAsserts|1|Maximum number of Asserts in a test method| ## JUnitTestsShouldIncludeAssert + **Since:** 2.0 **Priority:** Medium (3) @@ -102,6 +111,7 @@ JUnit tests should include at least one assertion. This makes the tests more ro with messages provide the developer a clearer idea of what the test does. **Example(s):** + ``` public class Foo extends TestCase { public void testSomething() { @@ -114,6 +124,7 @@ public class Foo extends TestCase { ``` ## SimplifyBooleanAssertion + **Since:** 3.6 **Priority:** Medium (3) @@ -129,6 +140,7 @@ as: assertFalse(expr); **Example(s):** + ``` public class SimpleTest extends TestCase { public void testX() { @@ -139,6 +151,7 @@ public class SimpleTest extends TestCase { ``` ## TestClassWithoutTestCases + **Since:** 3.0 **Priority:** Medium (3) @@ -147,6 +160,7 @@ Test classes end with the suffix Test. Having a non-test class with that name is since most people will assume it is a test case. Test classes have test methods named testXXX. **Example(s):** + ``` //Consider changing the name of the class if it is not a test //Consider adding test methods if it is a test @@ -159,6 +173,7 @@ public class CarTest { ``` ## UnnecessaryBooleanAssertion + **Since:** 3.0 **Priority:** Medium (3) @@ -169,6 +184,7 @@ statements like assertTrue(true) and assertFalse(false). If you just want a tes an error, use the fail() method and provide an indication message of why it did. **Example(s):** + ``` public class SimpleTest extends TestCase { public void testX() { @@ -178,6 +194,7 @@ public class SimpleTest extends TestCase { ``` ## UseAssertEqualsInsteadOfAssertTrue + **Since:** 3.1 **Priority:** Medium (3) @@ -185,6 +202,7 @@ public class SimpleTest extends TestCase { This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals. **Example(s):** + ``` public class FooTest extends TestCase { void testCode() { @@ -196,6 +214,7 @@ public class FooTest extends TestCase { ``` ## UseAssertNullInsteadOfAssertTrue + **Since:** 3.5 **Priority:** Medium (3) @@ -204,6 +223,7 @@ This rule detects JUnit assertions in object references equality. These assertio more specific methods, like assertNull, assertNotNull. **Example(s):** + ``` public class FooTest extends TestCase { void testCode() { @@ -217,6 +237,7 @@ public class FooTest extends TestCase { ``` ## UseAssertSameInsteadOfAssertTrue + **Since:** 3.1 **Priority:** Medium (3) @@ -225,6 +246,7 @@ This rule detects JUnit assertions in object references equality. These assertio by more specific methods, like assertSame, assertNotSame. **Example(s):** + ``` public class FooTest extends TestCase { void testCode() { @@ -236,6 +258,7 @@ public class FooTest extends TestCase { ``` ## UseAssertTrueInsteadOfAssertEquals + **Since:** 5.0 **Priority:** Medium (3) @@ -243,6 +266,7 @@ public class FooTest extends TestCase { When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, instead of assertEquals. **Example(s):** + ``` public class MyTestCase extends TestCase { public void testMyCase() { diff --git a/docs/pages/pmd/rules/java/logging-jakarta-commons.md b/docs/pages/pmd/rules/java/logging-jakarta-commons.md index f826983d6..886641e22 100644 --- a/docs/pages/pmd/rules/java/logging-jakarta-commons.md +++ b/docs/pages/pmd/rules/java/logging-jakarta-commons.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-jakarta-commons.xml --- ## GuardDebugLogging + **Since:** 4.3 **Priority:** Medium (3) @@ -15,6 +16,7 @@ When log messages are composed by concatenating strings, the whole section shoul by a isDebugEnabled() check to avoid performance and memory issues. **Example(s):** + ``` public class Test { private static final Log __log = LogFactory.getLog(Test.class); @@ -47,6 +49,7 @@ public class Test { |logLevels|[]|LogLevels to guard| ## GuardLogStatement + **Since:** 5.1.0 **Priority:** Medium High (2) @@ -55,6 +58,7 @@ Whenever using a log level, one should check if the loglevel is actually enabled otherwise skip the associate String creation and manipulation. **Example(s):** + ``` // Add this for performance if (log.isDebugEnabled() { ... @@ -69,6 +73,7 @@ otherwise skip the associate String creation and manipulation. |logLevels|[]|LogLevels to guard| ## ProperLogger + **Since:** 3.3 **Priority:** Medium (3) @@ -78,6 +83,7 @@ Private final Log log; is also allowed for rare cases where loggers need to be p with the restriction that the logger needs to be passed into the constructor. **Example(s):** + ``` public class Foo { @@ -94,6 +100,7 @@ public class Foo { |staticLoggerName|LOG|Name of the static Logger variable| ## UseCorrectExceptionLogging + **Since:** 3.2 **Priority:** Medium (3) @@ -101,6 +108,7 @@ public class Foo { To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. **Example(s):** + ``` public class Main { private static final Log _LOG = LogFactory.getLog( Main.class ); diff --git a/docs/pages/pmd/rules/java/logging-java.md b/docs/pages/pmd/rules/java/logging-java.md index 7095fad41..34a4a85eb 100644 --- a/docs/pages/pmd/rules/java/logging-java.md +++ b/docs/pages/pmd/rules/java/logging-java.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-java.xml --- ## AvoidPrintStackTrace + **Since:** 3.2 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-java.xml Avoid printStackTrace(); use a logger call instead. **Example(s):** + ``` class Foo { void bar() { @@ -27,6 +29,7 @@ class Foo { ``` ## GuardLogStatementJavaUtil + **Since:** 5.1.0 **Priority:** Medium High (2) @@ -35,6 +38,7 @@ Whenever using a log level, one should check if the loglevel is actually enabled otherwise skip the associate String creation and manipulation. **Example(s):** + ``` // Add this for performance if (log.isLoggable(Level.FINE)) { ... @@ -49,6 +53,7 @@ otherwise skip the associate String creation and manipulation. |logLevels|[]|LogLevels to guard| ## InvalidSlf4jMessageFormat + **Since:** 5.5.0 **Priority:** Low (5) @@ -56,6 +61,7 @@ otherwise skip the associate String creation and manipulation. Check for messages in slf4j loggers with non matching number of arguments and placeholders. **Example(s):** + ``` LOGGER.error("forget the arg {}"); LOGGER.error("too many args {}", "arg1", "arg2"); @@ -63,6 +69,7 @@ LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The except ``` ## LoggerIsNotStaticFinal + **Since:** 2.0 **Priority:** Medium High (2) @@ -70,6 +77,7 @@ LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The except In most cases, the Logger reference can be declared as static and final. **Example(s):** + ``` public class Foo{ Logger log = Logger.getLogger(Foo.class.getName()); // not recommended @@ -79,6 +87,7 @@ public class Foo{ ``` ## MoreThanOneLogger + **Since:** 2.0 **Priority:** Medium High (2) @@ -86,6 +95,7 @@ public class Foo{ Normally only one logger is used in each class. **Example(s):** + ``` public class Foo { Logger log = Logger.getLogger(Foo.class.getName()); @@ -96,6 +106,7 @@ public class Foo { ``` ## SystemPrintln + **Since:** 2.1 **Priority:** Medium High (2) @@ -105,6 +116,7 @@ the codebase even in production code. By using a logger one can enable/disable t will (and by priority) and avoid clogging the Standard out log. **Example(s):** + ``` class Foo{ Logger log = Logger.getLogger(Foo.class.getName()); diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md index 90a2a37d0..ab95e3aa1 100644 --- a/docs/pages/pmd/rules/java/migrating.md +++ b/docs/pages/pmd/rules/java/migrating.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml --- ## AvoidAssertAsIdentifier + **Since:** 3.4 **Priority:** Medium High (2) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. **Example(s):** + ``` public class A { public class foo { @@ -23,6 +25,7 @@ public class A { ``` ## AvoidEnumAsIdentifier + **Since:** 3.4 **Priority:** Medium High (2) @@ -30,6 +33,7 @@ public class A { Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. **Example(s):** + ``` public class A { public class foo { @@ -39,6 +43,7 @@ public class A { ``` ## ByteInstantiation + **Since:** 4.0 **Priority:** Medium High (2) @@ -47,6 +52,7 @@ Calling new Byte() causes memory allocation that can be avoided by the static By It makes use of an internal cache that recycles earlier instances making it more memory efficient. **Example(s):** + ``` public class Foo { private Byte i = new Byte(0); // change to Byte i = Byte.valueOf(0); @@ -54,6 +60,7 @@ public class Foo { ``` ## IntegerInstantiation + **Since:** 3.5 **Priority:** Medium High (2) @@ -62,6 +69,7 @@ Calling new Integer() causes memory allocation that can be avoided by the static It makes use of an internal cache that recycles earlier instances making it more memory efficient. **Example(s):** + ``` public class Foo { private Integer i = new Integer(0); // change to Integer i = Integer.valueOf(0); @@ -69,6 +77,7 @@ public class Foo { ``` ## JUnit4SuitesShouldUseSuiteAnnotation + **Since:** 4.0 **Priority:** Medium (3) @@ -77,6 +86,7 @@ In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites through the @RunWith(Suite.class) annotation. **Example(s):** + ``` public class BadExample extends TestCase{ @@ -92,6 +102,7 @@ public class GoodTest { ``` ## JUnit4TestShouldUseAfterAnnotation + **Since:** 4.0 **Priority:** Medium (3) @@ -100,6 +111,7 @@ In JUnit 3, the tearDown method was used to clean up all data entities required JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test **Example(s):** + ``` public class MyTest { public void tearDown() { @@ -114,6 +126,7 @@ public class MyTest2 { ``` ## JUnit4TestShouldUseBeforeAnnotation + **Since:** 4.0 **Priority:** Medium (3) @@ -122,6 +135,7 @@ In JUnit 3, the setUp method was used to set up all data entities required in ru JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests **Example(s):** + ``` public class MyTest { public void setUp() { @@ -136,6 +150,7 @@ public class MyTest2 { ``` ## JUnit4TestShouldUseTestAnnotation + **Since:** 4.0 **Priority:** Medium (3) @@ -144,6 +159,7 @@ In JUnit 3, the framework executed all methods which started with the word test In JUnit 4, only methods annotated with the @Test annotation are executed. **Example(s):** + ``` public class MyTest { public void testBad() { @@ -158,6 +174,7 @@ public class MyTest { ``` ## JUnitUseExpected + **Since:** 4.0 **Priority:** Medium (3) @@ -165,6 +182,7 @@ public class MyTest { In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. **Example(s):** + ``` public class MyTest { @Test @@ -184,6 +202,7 @@ public class MyTest { ``` ## LongInstantiation + **Since:** 4.0 **Priority:** Medium High (2) @@ -192,6 +211,7 @@ Calling new Long() causes memory allocation that can be avoided by the static Lo It makes use of an internal cache that recycles earlier instances making it more memory efficient. **Example(s):** + ``` public class Foo { private Long i = new Long(0); // change to Long i = Long.valueOf(0); @@ -199,6 +219,7 @@ public class Foo { ``` ## ReplaceEnumerationWithIterator + **Since:** 3.4 **Priority:** Medium (3) @@ -206,6 +227,7 @@ public class Foo { Consider replacing Enumeration usages with the newer java.util.Iterator **Example(s):** + ``` public class Foo implements Enumeration { private int x = 42; @@ -219,6 +241,7 @@ public class Foo implements Enumeration { ``` ## ReplaceHashtableWithMap + **Since:** 3.4 **Priority:** Medium (3) @@ -226,6 +249,7 @@ public class Foo implements Enumeration { Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. **Example(s):** + ``` public class Foo { void bar() { @@ -235,6 +259,7 @@ public class Foo { ``` ## ReplaceVectorWithList + **Since:** 3.4 **Priority:** Medium (3) @@ -242,6 +267,7 @@ public class Foo { Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. **Example(s):** + ``` public class Foo { void bar() { @@ -251,6 +277,7 @@ public class Foo { ``` ## ShortInstantiation + **Since:** 4.0 **Priority:** Medium High (2) @@ -259,6 +286,7 @@ Calling new Short() causes memory allocation that can be avoided by the static S It makes use of an internal cache that recycles earlier instances making it more memory efficient. **Example(s):** + ``` public class Foo { private Short i = new Short(0); // change to Short i = Short.valueOf(0); diff --git a/docs/pages/pmd/rules/java/naming.md b/docs/pages/pmd/rules/java/naming.md index 9164a66e9..f4f942ebf 100644 --- a/docs/pages/pmd/rules/java/naming.md +++ b/docs/pages/pmd/rules/java/naming.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/naming.xml --- ## AbstractNaming + **Since:** 1.4 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/naming.xml Abstract classes should be named 'AbstractXXX'. **Example(s):** + ``` public abstract class Foo { // should be AbstractFoo } @@ -26,6 +28,7 @@ public abstract class Foo { // should be AbstractFoo |strict|true|Also flag classes, that are named Abstract, but are not abstract.| ## AvoidDollarSigns + **Since:** 1.5 **Priority:** Medium (3) @@ -33,12 +36,14 @@ public abstract class Foo { // should be AbstractFoo Avoid using dollar signs in variable/method/class/interface names. **Example(s):** + ``` public class Fo$o { // not a recommended name } ``` ## AvoidFieldNameMatchingMethodName + **Since:** 3.0 **Priority:** Medium (3) @@ -48,6 +53,7 @@ having information (field) and actions (method) is not clear naming. Developers Smalltalk often prefer this approach as the methods denote accessor methods. **Example(s):** + ``` public class Foo { Object bar; @@ -58,6 +64,7 @@ public class Foo { ``` ## AvoidFieldNameMatchingTypeName + **Since:** 3.0 **Priority:** Medium (3) @@ -66,6 +73,7 @@ It is somewhat confusing to have a field name matching the declaring class name. This probably means that type and/or field names should be chosen more carefully. **Example(s):** + ``` public class Foo extends Bar { int foo; // There is probably a better name that can be used @@ -73,6 +81,7 @@ public class Foo extends Bar { ``` ## BooleanGetMethodName + **Since:** 4.0 **Priority:** Medium Low (4) @@ -82,6 +91,7 @@ I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the u prefix for these methods. **Example(s):** + ``` public boolean getFoo(); // bad public boolean isFoo(); // ok @@ -95,6 +105,7 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true |checkParameterizedMethods|false|Check parameterized methods| ## ClassNamingConventions + **Since:** 1.2 **Priority:** High (1) @@ -102,11 +113,13 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true Class names should always begin with an upper case character. **Example(s):** + ``` public class Foo {} ``` ## GenericsNaming + **Since:** 4.2.6 **Priority:** Medium Low (4) @@ -114,6 +127,7 @@ public class Foo {} Names for references to generic values should be limited to a single uppercase letter. **Example(s):** + ``` public interface GenericDao<E extends BaseModel, K extends Serializable> extends BaseDao { // This is ok... @@ -133,6 +147,7 @@ public interface GenericDao<EF extends BaseModel, K extends Serializable> { ``` ## LongVariable + **Since:** 0.3 **Priority:** Medium (3) @@ -140,6 +155,7 @@ public interface GenericDao<EF extends BaseModel, K extends Serializable> { Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. **Example(s):** + ``` public class Something { int reallyLongIntName = -3; // VIOLATION - Field @@ -159,6 +175,7 @@ public class Something { |minimum|17|The variable length reporting threshold| ## MethodNamingConventions + **Since:** 1.2 **Priority:** High (1) @@ -166,6 +183,7 @@ public class Something { Method names should always begin with a lower case character, and should not contain underscores. **Example(s):** + ``` public class Foo { public void fooStuff() { @@ -180,6 +198,7 @@ public class Foo { |checkNativeMethods|true|Check native methods| ## MethodWithSameNameAsEnclosingClass + **Since:** 1.5 **Priority:** Medium (3) @@ -187,6 +206,7 @@ public class Foo { Non-constructor methods should not have the same name as the enclosing class. **Example(s):** + ``` public class MyClass { @@ -197,6 +217,7 @@ public class MyClass { ``` ## MisleadingVariableName + **Since:** 3.4 **Priority:** Medium (3) @@ -204,6 +225,7 @@ public class MyClass { Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing. **Example(s):** + ``` public class Foo { private int m_foo; // OK @@ -214,6 +236,7 @@ public class Foo { ``` ## NoPackage + **Since:** 3.3 **Priority:** Medium (3) @@ -221,6 +244,7 @@ public class Foo { Detects when a class or interface does not have a package definition. **Example(s):** + ``` // no package declaration public class ClassInDefaultPackage { @@ -228,6 +252,7 @@ public class ClassInDefaultPackage { ``` ## PackageCase + **Since:** 3.3 **Priority:** Medium (3) @@ -235,6 +260,7 @@ public class ClassInDefaultPackage { Detects when a package definition contains uppercase characters. **Example(s):** + ``` package com.MyCompany; // should be lowercase name @@ -243,6 +269,7 @@ public class SomeClass { ``` ## ShortClassName + **Since:** 5.0 **Priority:** Medium Low (4) @@ -250,6 +277,7 @@ public class SomeClass { Short Classnames with fewer than e.g. five characters are not recommended. **Example(s):** + ``` public class Foo { } @@ -262,6 +290,7 @@ public class Foo { |minimum|5|Number of characters that are required as a minimum for a class name.| ## ShortMethodName + **Since:** 0.3 **Priority:** Medium (3) @@ -269,6 +298,7 @@ public class Foo { Method names that are very short are not helpful to the reader. **Example(s):** + ``` public class ShortMethod { public void a( int i ) { // Violation @@ -283,6 +313,7 @@ public class ShortMethod { |minimum|3|Number of characters that are required as a minimum for a method name.| ## ShortVariable + **Since:** 0.3 **Priority:** Medium (3) @@ -290,6 +321,7 @@ public class ShortMethod { Fields, local variables, or parameter names that are very short are not helpful to the reader. **Example(s):** + ``` public class Something { private int q = 15; // field - too short @@ -312,6 +344,7 @@ public class Something { |minimum|3|Number of characters that are required as a minimum for a variable name.| ## SuspiciousConstantFieldName + **Since:** 2.0 **Priority:** Medium (3) @@ -320,6 +353,7 @@ Field names using all uppercase characters - Sun's Java naming conventions indic be declared as final. **Example(s):** + ``` public class Foo { // this is bad, since someone could accidentally @@ -330,6 +364,7 @@ public class Foo { ``` ## SuspiciousEqualsMethodName + **Since:** 2.0 **Priority:** Medium High (2) @@ -338,6 +373,7 @@ The method name and parameter number are suspiciously close to equals(Object), w intention to override the equals(Object) method. **Example(s):** + ``` public class Foo { public int equals(Object o) { @@ -353,6 +389,7 @@ public class Foo { ``` ## SuspiciousHashcodeMethodName + **Since:** 1.5 **Priority:** Medium (3) @@ -361,6 +398,7 @@ The method name and return type are suspiciously close to hashCode(), which may to override the hashCode() method. **Example(s):** + ``` public class Foo { public int hashcode() { // oops, this probably was supposed to be 'hashCode' @@ -370,6 +408,7 @@ public class Foo { ``` ## VariableNamingConventions + **Since:** 1.2 **Priority:** High (1) @@ -379,6 +418,7 @@ checks for final variables that should be fully capitalized and non-final variab that should not include underscores. **Example(s):** + ``` public class Foo { public static final int MY_NUM = 0; diff --git a/docs/pages/pmd/rules/java/optimizations.md b/docs/pages/pmd/rules/java/optimizations.md index b2632fe38..efdf79976 100644 --- a/docs/pages/pmd/rules/java/optimizations.md +++ b/docs/pages/pmd/rules/java/optimizations.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/optimizations.xml --- ## AddEmptyString + **Since:** 4.0 **Priority:** Medium (3) @@ -15,12 +16,14 @@ The conversion of literals to strings by concatenating them with empty strings i It is much better to use one of the type-specific toString() methods instead. **Example(s):** + ``` String s = "" + 123; // inefficient String t = Integer.toString(456); // preferred approach ``` ## AvoidArrayLoops + **Since:** 3.5 **Priority:** Medium (3) @@ -28,6 +31,7 @@ String t = Integer.toString(456); // preferred approach Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead. **Example(s):** + ``` public class Test { public void bar() { @@ -48,6 +52,7 @@ public class Test { ``` ## AvoidInstantiatingObjectsInLoops + **Since:** 2.2 **Priority:** Medium (3) @@ -55,6 +60,7 @@ public class Test { New objects created within loops should be checked to see if they can created outside them and reused. **Example(s):** + ``` public class Something { public static void main( String as[] ) { @@ -66,6 +72,7 @@ public class Something { ``` ## LocalVariableCouldBeFinal + **Since:** 2.2 **Priority:** Medium (3) @@ -73,6 +80,7 @@ public class Something { A local variable assigned only once can be declared final. **Example(s):** + ``` public class Bar { public void foo () { @@ -83,6 +91,7 @@ public class Bar { ``` ## MethodArgumentCouldBeFinal + **Since:** 2.2 **Priority:** Medium (3) @@ -90,6 +99,7 @@ public class Bar { A method argument that is never re-assigned within the method can be declared final. **Example(s):** + ``` public void foo1 (String param) { // do stuff with param never assigning it @@ -101,6 +111,7 @@ public void foo2 (final String param) { // better, do stuff with param never ass ``` ## PrematureDeclaration + **Since:** 5.0 **Priority:** Medium (3) @@ -108,6 +119,7 @@ public void foo2 (final String param) { // better, do stuff with param never ass Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception. **Example(s):** + ``` public int getLength(String[] strings) { @@ -124,6 +136,7 @@ public int getLength(String[] strings) { ``` ## RedundantFieldInitializer + **Since:** 5.0 **Priority:** Medium (3) @@ -132,6 +145,7 @@ Java will initialize fields with known default values so any explicit initializa is redundant and results in a larger class file (approximately three additional bytecode instructions per field). **Example(s):** + ``` public class C { boolean b = false; // examples of redundant initializers @@ -155,6 +169,7 @@ public class C { ``` ## SimplifyStartsWith + **Since:** 3.1 **Priority:** Medium (3) @@ -163,6 +178,7 @@ Since it passes in a literal of length 1, calls to (string).startsWith can be re at the expense of some readability. **Example(s):** + ``` public class Foo { @@ -177,6 +193,7 @@ public class Foo { ``` ## UnnecessaryWrapperObjectCreation + **Since:** 3.8 **Priority:** Medium (3) @@ -186,6 +203,7 @@ just to create the primitive forms. Using these avoids the cost of creating obje garbage-collected later. **Example(s):** + ``` public int convert(String s) { int i, i2; @@ -204,6 +222,7 @@ public int convert(String s) { ``` ## UseArrayListInsteadOfVector + **Since:** 3.0 **Priority:** Medium (3) @@ -211,6 +230,7 @@ public int convert(String s) { ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. **Example(s):** + ``` public class SimpleTest extends TestCase { public void testX() { @@ -221,6 +241,7 @@ public class SimpleTest extends TestCase { ``` ## UseArraysAsList + **Since:** 3.5 **Priority:** Medium (3) @@ -229,6 +250,7 @@ The java.util.Arrays class has a "asList" method that should be used when you wa an array of objects. It is faster than executing a loop to copy all the elements of the array one by one. **Example(s):** + ``` public class Test { public void foo(Integer[] ints) { @@ -245,6 +267,7 @@ public class Test { ``` ## UseStringBufferForStringAppends + **Since:** 3.1 **Priority:** Medium (3) @@ -254,6 +277,7 @@ If a non-trivial number of these concatenations are being used then the explicit threadsafe StringBuffer is recommended to avoid this. **Example(s):** + ``` public class Foo { void bar() { diff --git a/docs/pages/pmd/rules/java/strictexception.md b/docs/pages/pmd/rules/java/strictexception.md index 83a3bc630..116668861 100644 --- a/docs/pages/pmd/rules/java/strictexception.md +++ b/docs/pages/pmd/rules/java/strictexception.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/strictexception.xml --- ## AvoidCatchingGenericException + **Since:** 4.2.6 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/strictexception.xml Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block **Example(s):** + ``` package com.igate.primitive; @@ -34,6 +36,7 @@ public class PrimitiveType { ``` ## AvoidCatchingNPE + **Since:** 1.8 **Priority:** Medium (3) @@ -42,6 +45,7 @@ Code should never throw NullPointerExceptions under normal circumstances. A cat original error, causing other, more subtle problems later on. **Example(s):** + ``` public class Foo { void bar() { @@ -54,6 +58,7 @@ public class Foo { ``` ## AvoidCatchingThrowable + **Since:** 1.2 **Priority:** Medium (3) @@ -62,6 +67,7 @@ Catching Throwable errors is not recommended since its scope is very broad. It i OutOfMemoryError that should be exposed and managed separately. **Example(s):** + ``` public void bar() { try { @@ -73,6 +79,7 @@ public void bar() { ``` ## AvoidLosingExceptionInformation + **Since:** 4.2.6 **Priority:** Medium High (2) @@ -81,6 +88,7 @@ Statements in a catch block that invoke accessors on the exception without using only add to code size. Either remove the invocation, or use the return result. **Example(s):** + ``` public void bar() { try { @@ -92,6 +100,7 @@ public void bar() { ``` ## AvoidRethrowingException + **Since:** 3.8 **Priority:** Medium (3) @@ -99,6 +108,7 @@ public void bar() { Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. **Example(s):** + ``` public void bar() { try { @@ -110,6 +120,7 @@ public void bar() { ``` ## AvoidThrowingNewInstanceOfSameException + **Since:** 4.2.5 **Priority:** Medium (3) @@ -118,6 +129,7 @@ Catch blocks that merely rethrow a caught exception wrapped inside a new instanc code size and runtime complexity. **Example(s):** + ``` public void bar() { try { @@ -130,6 +142,7 @@ public void bar() { ``` ## AvoidThrowingNullPointerException + **Since:** 1.8 **Priority:** High (1) @@ -139,6 +152,7 @@ virtual machine threw it. Consider using an IllegalArgumentException instead; th clearly seen as a programmer-initiated exception. **Example(s):** + ``` public class Foo { void bar() { @@ -148,6 +162,7 @@ public class Foo { ``` ## AvoidThrowingRawExceptionTypes + **Since:** 1.8 **Priority:** High (1) @@ -156,6 +171,7 @@ Avoid throwing certain exception types. Rather than throw a raw RuntimeException Exception, or Error, use a subclassed exception or error instead. **Example(s):** + ``` public class Foo { public void bar() throws Exception { @@ -165,6 +181,7 @@ public class Foo { ``` ## DoNotExtendJavaLangError + **Since:** 4.0 **Priority:** Medium (3) @@ -172,11 +189,13 @@ public class Foo { Errors are system exceptions. Do not extend them. **Example(s):** + ``` public class Foo extends Error { } ``` ## DoNotThrowExceptionInFinally + **Since:** 4.2 **Priority:** Medium Low (4) @@ -186,6 +205,7 @@ or code defects. Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block" **Example(s):** + ``` public class Foo { public void bar() { @@ -202,6 +222,7 @@ public class Foo { ``` ## ExceptionAsFlowControl + **Since:** 1.8 **Priority:** Medium (3) @@ -210,6 +231,7 @@ Using Exceptions as form of flow control is not recommended as they obscure true Either add the necessary validation or use an alternate control structure. **Example(s):** + ``` public void bar() { try { @@ -225,6 +247,7 @@ public void bar() { ``` ## SignatureDeclareThrowsException + **Since:** 1.2 **Priority:** Medium (3) @@ -233,6 +256,7 @@ Methods that declare the generic Exception as a possible throwable are not very failure modes are unclear. Use a class derived from RuntimeException or a more specific checked exception. **Example(s):** + ``` public void foo() throws Exception { } diff --git a/docs/pages/pmd/rules/java/strings.md b/docs/pages/pmd/rules/java/strings.md index f1ad1c9d2..d99550a71 100644 --- a/docs/pages/pmd/rules/java/strings.md +++ b/docs/pages/pmd/rules/java/strings.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/strings.xml --- ## AppendCharacterWithChar + **Since:** 3.5 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/strings.xml Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. **Example(s):** + ``` StringBuffer sb = new StringBuffer(); sb.append("a"); // avoid this @@ -23,6 +25,7 @@ sb.append('a'); // use this instead ``` ## AvoidDuplicateLiterals + **Since:** 1.0 **Priority:** Medium (3) @@ -30,6 +33,7 @@ sb.append('a'); // use this instead Code containing duplicate String literals can usually be improved by declaring the String as a constant field. **Example(s):** + ``` private void bar() { buz("Howdy"); @@ -52,6 +56,7 @@ private void bar() { |skipAnnotations|false|Skip literals within annotations| ## AvoidStringBufferField + **Since:** 4.2 **Priority:** Medium (3) @@ -60,6 +65,7 @@ StringBuffers/StringBuilders can grow considerably, and so may become a source o if held within objects with long lifetimes. **Example(s):** + ``` public class Foo { private StringBuffer buffer; // potential memory leak as an instance variable; @@ -67,6 +73,7 @@ public class Foo { ``` ## ConsecutiveAppendsShouldReuse + **Since:** 5.1 **Priority:** Medium (3) @@ -75,6 +82,7 @@ Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusi by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found [here](https://github.com/pmd/pmd/issues/202#issuecomment-274349067) **Example(s):** + ``` String foo = " "; @@ -88,6 +96,7 @@ buf.append("Hello").append(foo).append("World"); // good ``` ## ConsecutiveLiteralAppends + **Since:** 3.5 **Priority:** Medium (3) @@ -95,6 +104,7 @@ buf.append("Hello").append(foo).append("World"); // good Consecutively calling StringBuffer/StringBuilder.append with String literals **Example(s):** + ``` StringBuffer buf = new StringBuffer(); buf.append("Hello").append(" ").append("World"); // poor @@ -108,6 +118,7 @@ buf.append("Hello World"); // good |threshold|1|Max consecutive appends| ## InefficientEmptyStringCheck + **Since:** 3.6 **Priority:** Medium (3) @@ -119,6 +130,7 @@ false if a non-whitespace character is found. You can refer to Apache's StringUt or Spring's StringUtils#hasText (in the Springs framework) for existing implementations. **Example(s):** + ``` public void bar(String string) { if (string != null && string.trim().size() > 0) { @@ -128,6 +140,7 @@ public void bar(String string) { ``` ## InefficientStringBuffering + **Since:** 3.4 **Priority:** Medium (3) @@ -136,6 +149,7 @@ Avoid concatenating non-literals in a StringBuffer constructor or append() since need to be be created and destroyed by the JVM. **Example(s):** + ``` // Avoid this, two buffers are actually being created here StringBuffer sb = new StringBuffer("tmp = "+System.getProperty("java.io.tmpdir")); @@ -146,6 +160,7 @@ sb.append(System.getProperty("java.io.tmpdir")); ``` ## InsufficientStringBufferDeclaration + **Since:** 3.6 **Priority:** Medium (3) @@ -157,6 +172,7 @@ StringBuffer/StringBuilder constructor initializes the object to 16 characters. is assumed if the length of the constructor can not be determined. **Example(s):** + ``` StringBuffer bad = new StringBuffer(); bad.append("This is a long string that will exceed the default 16 characters"); @@ -166,6 +182,7 @@ good.append("This is a long string, which is pre-sized"); ``` ## StringBufferInstantiationWithChar + **Since:** 3.9 **Priority:** Medium Low (4) @@ -186,6 +203,7 @@ new StringBuilder('C') // chr(C) = 67 new StringBuilder("A") // 1 + 16 = 17 **Example(s):** + ``` // misleading instantiation, these buffers // are actually sized to 99 characters long @@ -198,6 +216,7 @@ StringBuilder sb4 = new StringBuilder("c"); ``` ## StringInstantiation + **Since:** 1.0 **Priority:** Medium High (2) @@ -205,11 +224,13 @@ StringBuilder sb4 = new StringBuilder("c"); Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared. **Example(s):** + ``` private String bar = new String("bar"); // just do a String bar = "bar"; ``` ## StringToString + **Since:** 1.0 **Priority:** Medium (3) @@ -217,6 +238,7 @@ private String bar = new String("bar"); // just do a String bar = "bar"; Avoid calling toString() on objects already known to be string instances; this is unnecessary. **Example(s):** + ``` private String baz() { String bar = "howdy"; @@ -225,6 +247,7 @@ private String baz() { ``` ## UnnecessaryCaseChange + **Since:** 3.3 **Priority:** Medium (3) @@ -232,6 +255,7 @@ private String baz() { Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() **Example(s):** + ``` boolean answer1 = buz.toUpperCase().equals("baz"); // should be buz.equalsIgnoreCase("baz") @@ -239,6 +263,7 @@ boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unneces ``` ## UseEqualsToCompareStrings + **Since:** 4.1 **Priority:** Medium (3) @@ -247,6 +272,7 @@ Using '==' or '!=' to compare strings only works if intern version is used on bo Use the equals() method instead. **Example(s):** + ``` public boolean test(String s) { if (s == "one") return true; // unreliable @@ -256,6 +282,7 @@ public boolean test(String s) { ``` ## UseIndexOfChar + **Since:** 3.5 **Priority:** Medium (3) @@ -263,6 +290,7 @@ public boolean test(String s) { Use String.indexOf(char) when checking for the index of a single character; it executes faster. **Example(s):** + ``` String s = "hello world"; // avoid this @@ -272,6 +300,7 @@ if (s.indexOf('d') {} ``` ## UselessStringValueOf + **Since:** 3.8 **Priority:** Medium (3) @@ -279,6 +308,7 @@ if (s.indexOf('d') {} No need to call String.valueOf to append to a string; just use the valueOf() argument directly. **Example(s):** + ``` public String convert(int i) { String s; @@ -289,6 +319,7 @@ public String convert(int i) { ``` ## UseStringBufferLength + **Since:** 3.4 **Priority:** Medium (3) @@ -297,6 +328,7 @@ Use StringBuffer.length() to determine StringBuffer length rather than using Str or StringBuffer.toString().length() == ... **Example(s):** + ``` StringBuffer sb = new StringBuffer(); diff --git a/docs/pages/pmd/rules/java/sunsecure.md b/docs/pages/pmd/rules/java/sunsecure.md index 8010bec6f..a34d44125 100644 --- a/docs/pages/pmd/rules/java/sunsecure.md +++ b/docs/pages/pmd/rules/java/sunsecure.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/sunsecure.xml --- ## ArrayIsStoredDirectly + **Since:** 2.2 **Priority:** Medium (3) @@ -15,6 +16,7 @@ Constructors and methods receiving arrays should clone objects and store the cop This prevents future changes from the user from affecting the original array. **Example(s):** + ``` public class Foo { private String [] x; @@ -26,6 +28,7 @@ public class Foo { ``` ## MethodReturnsInternalArray + **Since:** 2.2 **Priority:** Medium (3) @@ -34,6 +37,7 @@ Exposing internal arrays to the caller violates object encapsulation since eleme removed or replaced outside of the object that owns it. It is safer to return a copy of the array. **Example(s):** + ``` public class SecureSystem { UserData [] ud; diff --git a/docs/pages/pmd/rules/java/unnecessary.md b/docs/pages/pmd/rules/java/unnecessary.md index bd12faff7..c9601d5f4 100644 --- a/docs/pages/pmd/rules/java/unnecessary.md +++ b/docs/pages/pmd/rules/java/unnecessary.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/unnecessary.xml --- ## UnnecessaryConversionTemporary + **Since:** 0.1 **Priority:** Medium (3) @@ -15,6 +16,7 @@ Avoid the use temporary objects when converting primitives to Strings. Use the s on the wrapper classes instead. **Example(s):** + ``` public String convert(int x) { String foo = new Integer(x).toString(); // this wastes an object @@ -24,6 +26,7 @@ public String convert(int x) { ``` ## UnnecessaryFinalModifier + **Since:** 3.0 **Priority:** Medium (3) @@ -33,6 +36,7 @@ tagged as such. Similarly, methods that can't be overridden (private methods, me methods of enum instance) do not need to be tagged either. **Example(s):** + ``` public final class Foo { // This final modifier is not necessary, since the class is final @@ -43,6 +47,7 @@ public final class Foo { ``` ## UnnecessaryModifier + **Since:** 1.02 **Priority:** Medium (3) @@ -54,6 +59,7 @@ Nested enums are automatically `static`. For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous. **Example(s):** + ``` public @interface Annotation { public abstract void bar(); // both abstract and public are ignored by the compiler @@ -76,6 +82,7 @@ public class Bar { ``` ## UnnecessaryReturn + **Since:** 1.3 **Priority:** Medium (3) @@ -83,6 +90,7 @@ public class Bar { Avoid the use of unnecessary return statements. **Example(s):** + ``` public class Foo { public void bar() { @@ -93,6 +101,7 @@ public class Foo { ``` ## UnusedNullCheckInEquals + **Since:** 3.5 **Priority:** Medium (3) @@ -100,6 +109,7 @@ public class Foo { After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object's equals() method. **Example(s):** + ``` public class Test { @@ -139,6 +149,7 @@ public class Test { ``` ## UselessOperationOnImmutable + **Since:** 3.5 **Priority:** Medium (3) @@ -147,6 +158,7 @@ An operation on an Immutable object (String, BigDecimal or BigInteger) won't cha since the result of the operation is a new object. Therefore, ignoring the operation result is an error. **Example(s):** + ``` import java.math.*; @@ -163,6 +175,7 @@ class Test { ``` ## UselessOverridingMethod + **Since:** 3.3 **Priority:** Medium (3) @@ -170,6 +183,7 @@ class Test { The overriding method merely calls the same method defined in a superclass. **Example(s):** + ``` public void foo(String bar) { super.foo(bar); // why bother overriding? @@ -192,6 +206,7 @@ public Long getId() { |ignoreAnnotations|false|Ignore annotations| ## UselessParentheses + **Since:** 5.0 **Priority:** Medium Low (4) @@ -199,6 +214,7 @@ public Long getId() { Useless parentheses should be removed. **Example(s):** + ``` public class Foo { @@ -214,6 +230,7 @@ public class Foo { ``` ## UselessQualifiedThis + **Since:** 5.4.0 **Priority:** Medium (3) @@ -221,6 +238,7 @@ public class Foo { Look for qualified this usages in the same class. **Example(s):** + ``` public class Foo { final Foo otherFoo = Foo.this; // use "this" directly diff --git a/docs/pages/pmd/rules/java/unusedcode.md b/docs/pages/pmd/rules/java/unusedcode.md index c605268a5..4b956a988 100644 --- a/docs/pages/pmd/rules/java/unusedcode.md +++ b/docs/pages/pmd/rules/java/unusedcode.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_java.html editmepath: ../pmd-java/src/main/resources/rulesets/java/unusedcode.xml --- ## UnusedFormalParameter + **Since:** 0.8 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/unusedcode.xml Avoid passing parameters to methods or constructors without actually referencing them in the method body. **Example(s):** + ``` public class Foo { private void bar(String howdy) { @@ -29,6 +31,7 @@ public class Foo { |checkAll|false|Check all methods, including non-private ones| ## UnusedLocalVariable + **Since:** 0.1 **Priority:** Medium (3) @@ -36,6 +39,7 @@ public class Foo { Detects when a local variable is declared and/or assigned, but not used. **Example(s):** + ``` public class Foo { public void doSomething() { @@ -45,6 +49,7 @@ public class Foo { ``` ## UnusedPrivateField + **Since:** 0.1 **Priority:** Medium (3) @@ -52,6 +57,7 @@ public class Foo { Detects when a private field is declared and/or assigned a value, but not used. **Example(s):** + ``` public class Something { private static int FOO = 2; // Unused @@ -64,6 +70,7 @@ public class Something { ``` ## UnusedPrivateMethod + **Since:** 0.7 **Priority:** Medium (3) @@ -71,6 +78,7 @@ public class Something { Unused Private Method detects when a private method is declared but is unused. **Example(s):** + ``` public class Something { private void foo() {} // unused diff --git a/docs/pages/pmd/rules/jsp/basic-jsf.md b/docs/pages/pmd/rules/jsp/basic-jsf.md index c3f09b6d5..73ceb11d3 100644 --- a/docs/pages/pmd/rules/jsp/basic-jsf.md +++ b/docs/pages/pmd/rules/jsp/basic-jsf.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_jsp.html editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic-jsf.xml --- ## DontNestJsfInJstlIteration + **Since:** 3.6 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic-jsf.xml Do not nest JSF component custom actions inside a custom action that iterates over its body. **Example(s):** + ``` <html> <body> <ul> <c:forEach items='${books}' var='b'> diff --git a/docs/pages/pmd/rules/jsp/basic.md b/docs/pages/pmd/rules/jsp/basic.md index e3ddb2f59..2f3335af1 100644 --- a/docs/pages/pmd/rules/jsp/basic.md +++ b/docs/pages/pmd/rules/jsp/basic.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_jsp.html editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic.xml --- ## DuplicateJspImports + **Since:** 3.7 **Priority:** Medium (3) @@ -14,11 +15,13 @@ editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic.xml Avoid duplicate import statements inside JSP's. **Example(s):** + ``` <%@ page import=\"com.foo.MyClass,com.foo.MyClass\"%><html><body><b><img src=\"<%=Some.get()%>/foo\">xx</img>text</b></body></html> ``` ## IframeMissingSrcAttribute + **Since:** 3.6 **Priority:** Medium High (2) @@ -27,6 +30,7 @@ IFrames which are missing a src element can cause security information popups in through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 **Example(s):** + ``` <HTML><title>bad example><BODY> <iframe></iframe> @@ -38,6 +42,7 @@ through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 ``` ## JspEncoding + **Since:** 4.0 **Priority:** Medium (3) @@ -45,6 +50,7 @@ through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. **Example(s):** + ``` Most browsers should be able to interpret the following headers: @@ -54,6 +60,7 @@ Most browsers should be able to interpret the following headers: ``` ## NoClassAttribute + **Since:** 3.6 **Priority:** Medium High (2) @@ -61,6 +68,7 @@ Most browsers should be able to interpret the following headers: Do not use an attribute called 'class'. Use "styleclass" for CSS styles. **Example(s):** + ``` <HTML> <BODY> <P class="MajorHeading">Some text</P> @@ -68,6 +76,7 @@ Do not use an attribute called 'class'. Use "styleclass" for CSS styles. ``` ## NoHtmlComments + **Since:** 3.6 **Priority:** Medium High (2) @@ -77,6 +86,7 @@ In a production system, HTML comments increase the payload little other purpose. Consider switching to JSP comments. **Example(s):** + ``` <HTML><title>bad example><BODY> <!-- HTML comment --> @@ -88,6 +98,7 @@ In a production system, HTML comments increase the payload ``` ## NoInlineScript + **Since:** 4.0 **Priority:** Medium (3) @@ -96,6 +107,7 @@ Avoid inlining HTML script content. Consider externalizing the HTML script usin Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth. **Example(s):** + ``` Most browsers should be able to interpret the following headers: @@ -105,6 +117,7 @@ Most browsers should be able to interpret the following headers: ``` ## NoInlineStyleInformation + **Since:** 3.6 **Priority:** Medium (3) @@ -112,11 +125,13 @@ Most browsers should be able to interpret the following headers: Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FONT> tags, or attributes like "align='center'". **Example(s):** + ``` <html><body><p align='center'><b>text</b></p></body></html> ``` ## NoJspForward + **Since:** 3.6 **Priority:** Medium (3) @@ -124,11 +139,13 @@ Style information should be put in CSS files, not in JSPs. Therefore, don't use Do not do a forward from within a JSP file. **Example(s):** + ``` <jsp:forward page='UnderConstruction.jsp'/> ``` ## NoLongScripts + **Since:** 3.6 **Priority:** Medium High (2) @@ -136,6 +153,7 @@ Do not do a forward from within a JSP file. Scripts should be part of Tag Libraries, rather than part of JSP pages. **Example(s):** + ``` <HTML> <BODY> @@ -161,6 +179,7 @@ onload=calcDays; ``` ## NoScriptlets + **Since:** 3.6 **Priority:** Medium (3) @@ -168,6 +187,7 @@ onload=calcDays; Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. **Example(s):** + ``` <HTML> <HEAD> @@ -182,6 +202,7 @@ response.setHeader("Pragma", "No-cache"); ``` ## NoUnsanitizedJSPExpression + **Since:** 5.1.4 **Priority:** Medium (3) @@ -190,6 +211,7 @@ Avoid using expressions without escaping / sanitizing. This could lead to cross would be interpreted by the browser directly (e.g. "<script>alert('hello');</script>"). **Example(s):** + ``` <%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> diff --git a/docs/pages/pmd/rules/plsql/TomKytesDespair.md b/docs/pages/pmd/rules/plsql/TomKytesDespair.md index 62dd24c3c..92c9c160d 100644 --- a/docs/pages/pmd/rules/plsql/TomKytesDespair.md +++ b/docs/pages/pmd/rules/plsql/TomKytesDespair.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/TomKytesDespair.xml --- ## TomKytesDespair + **Since:** 5.1 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/TomKytesDespair.xml "WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY update_planned_hrs IS diff --git a/docs/pages/pmd/rules/plsql/codesize.md b/docs/pages/pmd/rules/plsql/codesize.md index 851ee09d8..b583a5a32 100644 --- a/docs/pages/pmd/rules/plsql/codesize.md +++ b/docs/pages/pmd/rules/plsql/codesize.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/codesize.xml --- ## CyclomaticComplexity + **Since:** 5.1 **Priority:** Medium (3) @@ -17,6 +18,7 @@ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate c high complexity, and 11+ is very high complexity. **Example(s):** + ``` -- Cyclomatic Complexity of 25 CREATE OR REPLACE PACKAGE BODY pkg_pmd_working_sequence AS @@ -143,6 +145,7 @@ END; |reportLevel|10|Cyclomatic Complexity reporting threshold| ## ExcessiveMethodLength + **Since:** 5.1 **Priority:** Medium (3) @@ -153,6 +156,7 @@ scrolling causes readers to lose focus. Try to reduce the method length by creating helper methods and removing any copy/pasted code. **Example(s):** + ``` CREATE OR REPLACE PROCEDURE doSomething BEGIN @@ -171,6 +175,7 @@ END; |sigma||Sigma value| ## ExcessiveObjectLength + **Since:** 5.1 **Priority:** Medium (3) @@ -180,6 +185,7 @@ responsibilities that could be provided by other objects. In breaking these meth apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY Foo AS @@ -209,6 +215,7 @@ END; |sigma||Sigma value| ## ExcessivePackageBodyLength + **Since:** 5.1 **Priority:** Medium (3) @@ -218,6 +225,7 @@ responsibilities that could be provided by external classes or functions. In bre apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY Foo AS @@ -247,6 +255,7 @@ END; |sigma||Sigma value| ## ExcessivePackageSpecificationLength + **Since:** 5.1 **Priority:** Medium (3) @@ -256,6 +265,7 @@ responsibilities that could be provided by external classes or functions. In bre apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` CREATE OR REPLACE PACKAGE Foo AS @@ -278,6 +288,7 @@ END; |sigma||Sigma value| ## ExcessiveParameterList + **Since:** 5.1 **Priority:** Medium (3) @@ -286,6 +297,7 @@ Methods with numerous parameters are a challenge to maintain, especially if most same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. **Example(s):** + ``` CREATE OR REPLACE PROCEDURE addPerson( -- too many arguments liable to be mixed up @@ -311,6 +323,7 @@ END; |sigma||Sigma value| ## ExcessiveTypeLength + **Since:** 5.1 **Priority:** Medium (3) @@ -320,6 +333,7 @@ responsibilities that could be provided by external classes or functions. In bre apart the code becomes more managable and ripe for reuse. **Example(s):** + ``` CREATE OR REPLACE TYPE BODY Foo AS @@ -349,6 +363,7 @@ END; |sigma||Sigma value| ## NcssMethodCount + **Since:** 5.1 **Priority:** Medium (3) @@ -358,6 +373,7 @@ of code for a given method. NCSS ignores comments, and counts actual statements. lines of code that are split are counted as one. **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY AS FUNCTION methd RETURN INTEGER IS @@ -376,6 +392,7 @@ END; |sigma||Sigma value| ## NcssObjectCount + **Since:** 5.1 **Priority:** Medium (3) @@ -385,6 +402,7 @@ of code for a given Oracle object. NCSS ignores comments, and counts actual stat lines of code that are split are counted as one. **Example(s):** + ``` CREATE OR REPLACE PACKAGE pkg_ PROCEDURE Foo IS @@ -405,6 +423,7 @@ CREATE OR REPLACE PACKAGE pkg_ |sigma||Sigma value| ## NPathComplexity + **Since:** 5.1 **Priority:** Medium (3) @@ -414,6 +433,7 @@ A threshold of 200 is generally considered the point where measures should be ta complexity and increase readability. **Example(s):** + ``` CREATE OR REPLACE PROCEDURE bar AS BEGIN -- this is something more complex than it needs to be, @@ -458,6 +478,7 @@ END; |sigma||Sigma value| ## TooManyFields + **Since:** 5.1 **Priority:** Medium (3) @@ -467,6 +488,7 @@ possibly through grouping related fields in new objects. For example, a class w city/state/zip fields could park them within a single Address field. **Example(s):** + ``` CREATE OR REPLACE PACKAGE pkg_too_many_fields AS C_CHAR_A CONSTANT CHAR(1 CHAR) := 'A'; @@ -483,6 +505,7 @@ END pkg_too_many_fields; |maxfields|15|Max allowable fields| ## TooManyMethods + **Since:** 5.1 **Priority:** Medium (3) diff --git a/docs/pages/pmd/rules/plsql/dates.md b/docs/pages/pmd/rules/plsql/dates.md index 98bd3424c..e92e6ce11 100644 --- a/docs/pages/pmd/rules/plsql/dates.md +++ b/docs/pages/pmd/rules/plsql/dates.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/dates.xml --- ## TO_DATE_TO_CHAR + **Since:** 5.1 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/dates.xml TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY date_utilities IS @@ -31,6 +33,7 @@ END date_utilities ; ``` ## TO_DATEWithoutDateFormat + **Since:** 5.1 **Priority:** Medium (3) @@ -38,6 +41,7 @@ END date_utilities ; TO_DATE without date format- use TO_DATE(expression, date-format) **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY date_utilities IS @@ -68,6 +72,7 @@ END date_utilities ; ``` ## TO_TIMESTAMPWithoutDateFormat + **Since:** 5.1 **Priority:** Medium (3) @@ -75,6 +80,7 @@ END date_utilities ; TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) **Example(s):** + ``` CREATE OR REPLACE PACKAGE BODY date_utilities IS diff --git a/docs/pages/pmd/rules/plsql/strictsyntax.md b/docs/pages/pmd/rules/plsql/strictsyntax.md index a2095dc21..46d222ba6 100644 --- a/docs/pages/pmd/rules/plsql/strictsyntax.md +++ b/docs/pages/pmd/rules/plsql/strictsyntax.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/strictsyntax.xml --- ## MisplacedPragma + **Since:** 5.5.2 **Priority:** Medium (3) @@ -16,6 +17,7 @@ but the code does not complain, when being compiled on the 11g DB. https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#BABIIHBJ **Example(s):** + ``` create or replace package inline_pragma_error is diff --git a/docs/pages/pmd/rules/vf/security.md b/docs/pages/pmd/rules/vf/security.md index 6839cd39c..7eae45756 100644 --- a/docs/pages/pmd/rules/vf/security.md +++ b/docs/pages/pmd/rules/vf/security.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_vf.html editmepath: ../pmd-visualforce/src/main/resources/rulesets/vf/security.xml --- ## VfCsrf + **Since:** 5.6.0 **Priority:** Medium (3) @@ -14,11 +15,13 @@ editmepath: ../pmd-visualforce/src/main/resources/rulesets/vf/security.xml Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. **Example(s):** + ``` <apex:page controller="AcRestActionsController" action="{!csrfInitMethod}" > ``` ## VfUnescapeEl + **Since:** 5.6.0 **Priority:** Medium (3) @@ -26,6 +29,7 @@ Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. Avoid unescaped user controlled content in EL as it results in XSS. **Example(s):** + ``` <apex:outputText value="Potential XSS is {! here }" escape="false" /> ``` diff --git a/docs/pages/pmd/rules/vm/basic.md b/docs/pages/pmd/rules/vm/basic.md index 6b51f70d2..0919b8e1d 100644 --- a/docs/pages/pmd/rules/vm/basic.md +++ b/docs/pages/pmd/rules/vm/basic.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_vm.html editmepath: ../pmd-vm/src/main/resources/rulesets/vm/basic.xml --- ## AvoidDeeplyNestedIfStmts + **Since:** 5.1 **Priority:** Medium (3) @@ -20,6 +21,7 @@ Avoid creating deeply nested if-then statements since they are harder to read an |problemDepth|3|The if statement depth reporting threshold| ## AvoidReassigningParameters + **Since:** 5.1 **Priority:** Medium High (2) @@ -27,6 +29,7 @@ Avoid creating deeply nested if-then statements since they are harder to read an Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. ## CollapsibleIfStatements + **Since:** 5.1 **Priority:** Medium (3) @@ -34,6 +37,7 @@ Reassigning values to incoming parameters is not recommended. Use temporary loc Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. ## EmptyForeachStmt + **Since:** 5.1 **Priority:** Medium High (2) @@ -41,6 +45,7 @@ Sometimes two consecutive 'if' statements can be consolidated by separating thei Empty foreach statements should be deleted. ## EmptyIfStmt + **Since:** 5.1 **Priority:** Medium High (2) @@ -48,6 +53,7 @@ Empty foreach statements should be deleted. Empty if statements should be deleted. ## ExcessiveTemplateLength + **Since:** 5.1 **Priority:** Medium (3) @@ -63,6 +69,7 @@ The template is too long. It should be broken up into smaller pieces. |sigma||Sigma value| ## NoInlineJavaScript + **Since:** 5.1 **Priority:** Medium High (2) @@ -70,6 +77,7 @@ The template is too long. It should be broken up into smaller pieces. Avoid inline JavaScript. Import .js files instead. ## NoInlineStyles + **Since:** 5.1 **Priority:** Medium High (2) @@ -77,6 +85,7 @@ Avoid inline JavaScript. Import .js files instead. Avoid inline styles. Use css classes instead. ## UnusedMacroParameter + **Since:** 5.1 **Priority:** Medium High (2) diff --git a/docs/pages/pmd/rules/xml/basic.md b/docs/pages/pmd/rules/xml/basic.md index 49b48ff1c..ea057818b 100644 --- a/docs/pages/pmd/rules/xml/basic.md +++ b/docs/pages/pmd/rules/xml/basic.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_xml.html editmepath: ../pmd-xml/src/main/resources/rulesets/xml/basic.xml --- ## MistypedCDATASection + **Since:** 5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-xml/src/main/resources/rulesets/xml/basic.xml An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and ends with a ]]> marker, which has only two ]. **Example(s):** + ``` An extra [ looks like <!CDATA[[]]>, and an extra ] looks like <!CDATA[]]]>. ``` diff --git a/docs/pages/pmd/rules/xsl/xpath.md b/docs/pages/pmd/rules/xsl/xpath.md index ddca5b7e9..7200af7ee 100644 --- a/docs/pages/pmd/rules/xsl/xpath.md +++ b/docs/pages/pmd/rules/xsl/xpath.md @@ -7,6 +7,7 @@ sidebaractiveurl: /pmd_rules_xsl.html editmepath: ../pmd-xml/src/main/resources/rulesets/xsl/xpath.xml --- ## AvoidAxisNavigation + **Since:** 5.0 **Priority:** Medium (3) @@ -14,6 +15,7 @@ editmepath: ../pmd-xml/src/main/resources/rulesets/xsl/xpath.xml Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document. **Example(s):** + ``` <xsl:variable name="var" select="//item/descendant::child"/> ``` @@ -25,6 +27,7 @@ Avoid using the 'following' or 'preceeding' axes whenever possible, as these can |checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.| ## UseConcatOnce + **Since:** 5.0 **Priority:** Medium (3) @@ -32,6 +35,7 @@ Avoid using the 'following' or 'preceeding' axes whenever possible, as these can The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)". **Example(s):** + ``` <xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/> <xsl:variable name="var" select="concat("Welcome","to you ",$name))"> From ba32ed572b8368bb300fa0d53c75542de3bc8a05 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 20:17:37 +0200 Subject: [PATCH 16/24] [core] Take deprecated flag into account when loading rulesets/rules --- .../src/main/java/net/sourceforge/pmd/RuleSetFactory.java | 4 ++++ .../src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java | 1 + 2 files changed, 5 insertions(+) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java index 79026d54a..599957bc3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RuleSetFactory.java @@ -567,6 +567,10 @@ private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetB rule.setRuleSetName(ruleSetBuilder.getName()); rule.setExternalInfoUrl(ruleElement.getAttribute(EXTERNAL_INFO_URL)); + if (hasAttributeSetTrue(ruleElement, "deprecated")) { + rule.setDeprecated(true); + } + if (hasAttributeSetTrue(ruleElement, "dfa")) { rule.setUsesDFA(); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index 3623e0137..4d2452a2f 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -431,6 +431,7 @@ public void testInvertedMinimumMaximumLanugageVersions() throws RuleSetNotFoundE public void testDirectDeprecatedRule() throws RuleSetNotFoundException { Rule r = loadFirstRule(DIRECT_DEPRECATED_RULE); assertNotNull("Direct Deprecated Rule", r); + assertTrue(r.isDeprecated()); } @Test From 171ebad44488e510b706127ba58d7aeb91228ff9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 20:28:06 +0200 Subject: [PATCH 17/24] [doc] Add deprecation label for deprecated rules --- .../pmd/docs/RuleDocGenerator.java | 11 ++++++++- pmd-doc/src/test/resources/expected/java.md | 1 + pmd-doc/src/test/resources/expected/sample.md | 10 ++++++++ .../resources/rulesets/ruledoctest/sample.xml | 23 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index ade2c239a..3a098183b 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -38,6 +38,9 @@ public class RuleDocGenerator { private static final String RULESET_INDEX_FILENAME_PATTERN = "docs/pages/pmd/rules/${language.tersename}/${ruleset.name}.md"; private static final String RULESET_INDEX_PERMALINK_PATTERN = "pmd_rules_${language.tersename}_${ruleset.name}.html"; + private static final String DEPRECATION_LABEL_SMALL = "<span style=\"border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;\">Deprecated</span> "; + private static final String DEPRECATION_LABEL = "<span style=\"border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;\">Deprecated</span> "; + private final Path root; private final FileWriter writer; @@ -145,7 +148,9 @@ private void generateLanguageIndex(Map<Language, List<RuleSet>> rulesets) throws .replace("${language.tersename}", languageTersename) .replace("${ruleset.name}", getRuleSetFilename(ruleset)); link += "#" + rule.getName().toLowerCase(Locale.ROOT); - lines.add("* [" + rule.getName() + "](" + link + "): " + getShortRuleDescription(rule)); + lines.add("* [" + rule.getName() + "](" + link + "): " + + (rule.isDeprecated() ? DEPRECATION_LABEL_SMALL : "") + + getShortRuleDescription(rule)); } lines.add(""); } @@ -219,6 +224,10 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws for (Rule rule : getSortedRules(ruleset)) { lines.add("## " + rule.getName()); lines.add(""); + if (rule.isDeprecated()) { + lines.add(DEPRECATION_LABEL); + lines.add(""); + } if (rule.getSince() != null) { lines.add("**Since:** " + rule.getSince()); lines.add(""); diff --git a/pmd-doc/src/test/resources/expected/java.md b/pmd-doc/src/test/resources/expected/java.md index 97278fac9..0b00b9081 100644 --- a/pmd-doc/src/test/resources/expected/java.md +++ b/pmd-doc/src/test/resources/expected/java.md @@ -8,5 +8,6 @@ List of rulesets and rules contained in each ruleset. * [Sample](pmd_rules_java_sample.html): Sample ruleset to test rule doc generation. ## Sample +* [DeprecatedSample](pmd_rules_java_sample.html#deprecatedsample): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Just some description of a deprecated rule. * [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. * [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index 356d5197d..34928add8 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -6,6 +6,16 @@ folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../rulesets/ruledoctest/sample.xml --- +## DeprecatedSample + +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + +**Since:** 1.0 + +**Priority:** Medium (3) + +Just some description of a deprecated rule. + ## JumbledIncrementer **Since:** 1.0 diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index e5d35152e..bf731140f 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -82,4 +82,27 @@ public class JumbledIncrementerRule1 { ]]> </example> </rule> + +<rule name="DeprecatedSample" + language="java" + since="1.0" + message="Sample rule, which is deprecated" + class="net.sourceforge.pmd.lang.rule.XPathRule" + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#deprecatedsample" + deprecated="true"> + <description> +Just some description of a deprecated rule. + </description> + <priority>3</priority> + <properties> + <property name="xpath"> + <value> +<![CDATA[ +//ForStatement +]]> + </value> + </property> + </properties> + </rule> + </ruleset> From 9111316c01c0a24868dd6909cbf80071989a57e5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 21:29:31 +0200 Subject: [PATCH 18/24] [doc] Support renamed/moved rules --- .../pmd/docs/RuleDocGenerator.java | 58 +++++++++++++++++-- pmd-doc/src/test/resources/expected/java.md | 2 + pmd-doc/src/test/resources/expected/sample.md | 52 +++++++++++++++++ .../resources/rulesets/ruledoctest/sample.xml | 4 ++ .../main/resources/rulesets/java/basic.xml | 14 ++--- 5 files changed, 118 insertions(+), 12 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 3a098183b..2925ce0dc 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -30,6 +30,7 @@ import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetNotFoundException; import net.sourceforge.pmd.lang.Language; +import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; public class RuleDocGenerator { @@ -147,10 +148,30 @@ private void generateLanguageIndex(Map<Language, List<RuleSet>> rulesets) throws String link = RULESET_INDEX_PERMALINK_PATTERN .replace("${language.tersename}", languageTersename) .replace("${ruleset.name}", getRuleSetFilename(ruleset)); - link += "#" + rule.getName().toLowerCase(Locale.ROOT); - lines.add("* [" + rule.getName() + "](" + link + "): " - + (rule.isDeprecated() ? DEPRECATION_LABEL_SMALL : "") - + getShortRuleDescription(rule)); + if (rule instanceof RuleReference) { + RuleReference ref = (RuleReference) rule; + if (ruleset.getFileName().equals(ref.getRuleSetReference().getRuleSetFileName())) { + // rule renamed within same ruleset + lines.add("* [" + rule.getName() + "](" + link + "#" + rule.getName().toLowerCase(Locale.ROOT) + "): " + + DEPRECATION_LABEL_SMALL + + "The rule has been renamed. Use instead " + + "[" + ref.getRule().getName() + "](" + link + "#" + ref.getRule().getName().toLowerCase(Locale.ROOT) + ")."); + } else { + // rule moved to another ruleset... + String otherLink = RULESET_INDEX_PERMALINK_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ref.getRuleSetReference().getRuleSetFileName())); + lines.add("* [" + rule.getName() + "](" + link + "#" + rule.getName().toLowerCase(Locale.ROOT) + "): " + + DEPRECATION_LABEL_SMALL + + "The rule has been moved to another ruleset. Use instead " + + "[" + ref.getRule().getName() + "](" + otherLink + "#" + ref.getRule().getName().toLowerCase(Locale.ROOT) + ")."); + } + } else { + link += "#" + rule.getName().toLowerCase(Locale.ROOT); + lines.add("* [" + rule.getName() + "](" + link + "): " + + (rule.isDeprecated() ? DEPRECATION_LABEL_SMALL : "") + + getShortRuleDescription(rule)); + } } lines.add(""); } @@ -181,7 +202,11 @@ private static String getShortRuleDescription(Rule rule) { * @return */ private static String getRuleSetFilename(RuleSet ruleset) { - return FilenameUtils.getBaseName(StringUtils.chomp(ruleset.getFileName())); + return getRuleSetFilename(ruleset.getFileName()); + } + + private static String getRuleSetFilename(String rulesetFileName) { + return FilenameUtils.getBaseName(StringUtils.chomp(rulesetFileName)); } private static String getRuleSetDescriptionSingleLine(RuleSet ruleset) { @@ -224,6 +249,29 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws for (Rule rule : getSortedRules(ruleset)) { lines.add("## " + rule.getName()); lines.add(""); + + if (rule instanceof RuleReference) { + RuleReference ref = (RuleReference) rule; + if (ruleset.getFileName().equals(ref.getRuleSetReference().getRuleSetFileName())) { + // rule renamed within same ruleset + lines.add(DEPRECATION_LABEL); + lines.add(""); + lines.add("This rule has been renamed. Use instead: [" + + ref.getRule().getName() + "](" + "#" + ref.getRule().getName().toLowerCase(Locale.ROOT) + ")"); + lines.add(""); + } else { + // rule moved to another ruleset + String otherLink = RULESET_INDEX_PERMALINK_PATTERN + .replace("${language.tersename}", languageTersename) + .replace("${ruleset.name}", getRuleSetFilename(ref.getRuleSetReference().getRuleSetFileName())); + lines.add(DEPRECATION_LABEL); + lines.add(""); + lines.add("The rule has been moved to another ruleset. Use instead: [" + + ref.getRule().getName() + "](" + otherLink + "#" + ref.getRule().getName().toLowerCase(Locale.ROOT) + ")"); + lines.add(""); + } + } + if (rule.isDeprecated()) { lines.add(DEPRECATION_LABEL); lines.add(""); diff --git a/pmd-doc/src/test/resources/expected/java.md b/pmd-doc/src/test/resources/expected/java.md index 0b00b9081..474ee48a6 100644 --- a/pmd-doc/src/test/resources/expected/java.md +++ b/pmd-doc/src/test/resources/expected/java.md @@ -10,4 +10,6 @@ List of rulesets and rules contained in each ruleset. ## Sample * [DeprecatedSample](pmd_rules_java_sample.html#deprecatedsample): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Just some description of a deprecated rule. * [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +* [MovedRule](pmd_rules_java_sample.html#movedrule): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> The rule has been moved to another ruleset. Use instead [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer). * [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... +* [RenamedRule](pmd_rules_java_sample.html#renamedrule): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index 34928add8..bc50e5667 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -38,6 +38,32 @@ public class JumbledIncrementerRule1 { } ``` +## MovedRule + +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + +The rule has been moved to another ruleset. Use instead: [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer) + +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**Example(s):** + +``` +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} +``` + ## OverrideBothEqualsAndHashcode **Since:** 0.4 @@ -70,3 +96,29 @@ public class Foo { // perfect, both methods provided } } ``` + +## RenamedRule + +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + +This rule has been renamed. Use instead: [JumbledIncrementer](#jumbledincrementer) + +**Since:** 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**Example(s):** + +``` +public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +} +``` diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index bf731140f..f6148216e 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -105,4 +105,8 @@ Just some description of a deprecated rule. </properties> </rule> +<rule name="RenamedRule" ref="JumbledIncrementer"/> + +<rule name="MovedRule" ref="rulesets/java/basic.xml/JumbledIncrementer"/> + </ruleset> diff --git a/pmd-java/src/main/resources/rulesets/java/basic.xml b/pmd-java/src/main/resources/rulesets/java/basic.xml index f7f06a0ad..df103cd67 100644 --- a/pmd-java/src/main/resources/rulesets/java/basic.xml +++ b/pmd-java/src/main/resources/rulesets/java/basic.xml @@ -35,13 +35,13 @@ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even i <example> <![CDATA[ public class JumbledIncrementerRule1 { - public void foo() { - for (int i = 0; i < 10; i++) { // only references 'i' - for (int k = 0; k < 20; i++) { // references both 'i' and 'k' - System.out.println("Hello"); - } - } - } + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } } ]]> </example> From 06e8e32d23068625d363ceac981a9196f95d6262 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Fri, 11 Aug 2017 21:52:18 +0200 Subject: [PATCH 19/24] [doc] update generated documentation --- docs/pages/pmd/rules/java.md | 6 +++--- docs/pages/pmd/rules/java/basic.md | 14 +++++++------- docs/pages/pmd/rules/java/codesize.md | 6 ++++++ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index aa6b07fb8..125a9ed55 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -76,17 +76,17 @@ List of rulesets and rules contained in each ruleset. * [ProperCloneImplementation](pmd_rules_java_clone.html#propercloneimplementation): Object clone() should be implemented with super.clone(). ## Code Size -* [CyclomaticComplexity](pmd_rules_java_codesize.html#cyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [CyclomaticComplexity](pmd_rules_java_codesize.html#cyclomaticcomplexity): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Complexity directly affects maintenance costs is determined by the number of decision points in a... * [ExcessiveClassLength](pmd_rules_java_codesize.html#excessiveclasslength): Excessive class file lengths are usually indications that the class may be burdened with excessiv... * [ExcessiveMethodLength](pmd_rules_java_codesize.html#excessivemethodlength): When methods are excessively long this usually indicates that the method is doing more than itsna... * [ExcessiveParameterList](pmd_rules_java_codesize.html#excessiveparameterlist): Methods with numerous parameters are a challenge to maintain, especially if most of them share th... * [ExcessivePublicCount](pmd_rules_java_codesize.html#excessivepubliccount): Classes with large numbers of public methods and attributes require disproportionate testing effo... -* [ModifiedCyclomaticComplexity](pmd_rules_java_codesize.html#modifiedcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [ModifiedCyclomaticComplexity](pmd_rules_java_codesize.html#modifiedcyclomaticcomplexity): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Complexity directly affects maintenance costs is determined by the number of decision points in a... * [NcssConstructorCount](pmd_rules_java_codesize.html#ncssconstructorcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssMethodCount](pmd_rules_java_codesize.html#ncssmethodcount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NcssTypeCount](pmd_rules_java_codesize.html#ncsstypecount): This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of l... * [NPathComplexity](pmd_rules_java_codesize.html#npathcomplexity): The NPath complexity of a method is the number of acyclic execution paths through that method.A t... -* [StdCyclomaticComplexity](pmd_rules_java_codesize.html#stdcyclomaticcomplexity): Complexity directly affects maintenance costs is determined by the number of decision points in a... +* [StdCyclomaticComplexity](pmd_rules_java_codesize.html#stdcyclomaticcomplexity): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Complexity directly affects maintenance costs is determined by the number of decision points in a... * [TooManyFields](pmd_rules_java_codesize.html#toomanyfields): Classes that have too many fields can become unwieldy and could be redesigned to have fewer field... * [TooManyMethods](pmd_rules_java_codesize.html#toomanymethods): A class with too many methods is probably a good suspect for refactoring, in order to reduce its ... diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md index 50f170b6f..f93c39121 100644 --- a/docs/pages/pmd/rules/java/basic.md +++ b/docs/pages/pmd/rules/java/basic.md @@ -449,13 +449,13 @@ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even i ``` public class JumbledIncrementerRule1 { - public void foo() { - for (int i = 0; i < 10; i++) { // only references 'i' - for (int k = 0; k < 20; i++) { // references both 'i' and 'k' - System.out.println("Hello"); - } - } - } + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } } ``` diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md index 774419302..e338ab110 100644 --- a/docs/pages/pmd/rules/java/codesize.md +++ b/docs/pages/pmd/rules/java/codesize.md @@ -8,6 +8,8 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/codesize.xml --- ## CyclomaticComplexity +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + **Since:** 1.03 **Priority:** Medium (3) @@ -204,6 +206,8 @@ public class Foo { ## ModifiedCyclomaticComplexity +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + **Since:** 5.1.2 **Priority:** Medium (3) @@ -421,6 +425,8 @@ void bar() { // this is something more complex than it needs to be, ## StdCyclomaticComplexity +<span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> + **Since:** 5.1.2 **Priority:** Medium (3) From 2bff86d0f7cb67aabb60c591e784afc2c27422da Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Sat, 12 Aug 2017 11:16:08 +0200 Subject: [PATCH 20/24] [doc] Output XPath expression and link to rule class implementation --- .../pmd/docs/RuleDocGenerator.java | 46 ++++++++++++++++++- pmd-doc/src/test/resources/expected/sample.md | 43 +++++++++++++++-- 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index 2925ce0dc..b3a54e706 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.docs; +import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -42,6 +43,8 @@ public class RuleDocGenerator { private static final String DEPRECATION_LABEL_SMALL = "<span style=\"border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;\">Deprecated</span> "; private static final String DEPRECATION_LABEL = "<span style=\"border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;\">Deprecated</span> "; + private static final String GITHUB_SOURCE_LINK = "https://github.com/pmd/pmd/blob/master/"; + private final Path root; private final FileWriter writer; @@ -277,7 +280,7 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add(""); } if (rule.getSince() != null) { - lines.add("**Since:** " + rule.getSince()); + lines.add("**Since:** PMD " + rule.getSince()); lines.add(""); } lines.add("**Priority:** " + rule.getPriority() + " (" + rule.getPriority().getPriority() + ")"); @@ -285,6 +288,20 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add(StringUtils.stripToEmpty(rule.getDescription())); lines.add(""); + + if (rule instanceof XPathRule || rule instanceof RuleReference && ((RuleReference) rule).getRule() instanceof XPathRule) { + lines.add("```"); + lines.add(StringUtils.stripToEmpty(rule.getProperty(XPathRule.XPATH_DESCRIPTOR))); + lines.add("```"); + lines.add(""); + } else { + lines.add("**This rule is defined by the following Java class:** " + + "[" + rule.getRuleClass() + "](" + + GITHUB_SOURCE_LINK + getRuleClassSourceFilepath(rule.getRuleClass()) + + ")"); + lines.add(""); + } + if (!rule.getExamples().isEmpty()) { lines.add("**Example(s):**"); lines.add(""); @@ -358,7 +375,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO return super.visitFile(file, attrs); } }); - + if (!foundPathResult.isEmpty()) { Path foundPath = foundPathResult.get(0); foundPath = root.relativize(foundPath); @@ -367,4 +384,29 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO return StringUtils.chomp(ruleset.getFileName()); } + + private String getRuleClassSourceFilepath(String ruleClass) throws IOException { + final String relativeSourceFilename = ruleClass.replaceAll("\\.", File.separator) + ".java"; + final List<Path> foundPathResult = new LinkedList<>(); + + Files.walkFileTree(root, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String path = file.toString(); + if (path.contains("src") && path.endsWith(relativeSourceFilename)) { + foundPathResult.add(file); + return FileVisitResult.TERMINATE; + } + return super.visitFile(file, attrs); + } + }); + + if (!foundPathResult.isEmpty()) { + Path foundPath = foundPathResult.get(0); + foundPath = root.relativize(foundPath); + return FilenameUtils.normalize(foundPath.toString(), true); + } + + return FilenameUtils.normalize(relativeSourceFilename, true); + } } diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index bc50e5667..2ff1e0527 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -10,20 +10,33 @@ editmepath: ../rulesets/ruledoctest/sample.xml <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Just some description of a deprecated rule. +``` +//ForStatement +``` + ## JumbledIncrementer -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +``` +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + **Example(s):** ``` @@ -44,12 +57,21 @@ public class JumbledIncrementerRule1 { The rule has been moved to another ruleset. Use instead: [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer) -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +``` +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + **Example(s):** ``` @@ -66,12 +88,14 @@ public class JumbledIncrementerRule1 { ## OverrideBothEqualsAndHashcode -**Since:** 0.4 +**Since:** PMD 0.4 **Priority:** Medium (3) Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule](https://github.com/pmd/pmd/blob/master/net/sourceforge/pmd/lang/java/rule/basic/OverrideBothEqualsAndHashcodeRule.java) + **Example(s):** ``` @@ -103,12 +127,21 @@ public class Foo { // perfect, both methods provided This rule has been renamed. Use instead: [JumbledIncrementer](#jumbledincrementer) -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +``` +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + **Example(s):** ``` From f1630932f2ad0b95f5af2675034c0f1e81ea4a3b Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Sat, 12 Aug 2017 11:47:47 +0200 Subject: [PATCH 21/24] [doc] update generated documentation --- docs/pages/pmd/rules/apex/apexunit.md | 8 +- docs/pages/pmd/rules/apex/braces.md | 32 +- docs/pages/pmd/rules/apex/complexity.md | 36 +- docs/pages/pmd/rules/apex/performance.md | 8 +- docs/pages/pmd/rules/apex/security.md | 44 +- docs/pages/pmd/rules/apex/style.md | 24 +- docs/pages/pmd/rules/ecmascript/basic.md | 83 ++- docs/pages/pmd/rules/ecmascript/braces.md | 28 +- .../pages/pmd/rules/ecmascript/unnecessary.md | 22 +- docs/pages/pmd/rules/java/android.md | 48 +- docs/pages/pmd/rules/java/basic.md | 196 ++++++- docs/pages/pmd/rules/java/braces.md | 27 +- docs/pages/pmd/rules/java/clone.md | 67 ++- docs/pages/pmd/rules/java/codesize.md | 65 ++- docs/pages/pmd/rules/java/comments.md | 16 +- docs/pages/pmd/rules/java/controversial.md | 198 ++++++- docs/pages/pmd/rules/java/coupling.md | 20 +- docs/pages/pmd/rules/java/design.md | 498 ++++++++++++++++-- docs/pages/pmd/rules/java/empty.md | 81 ++- docs/pages/pmd/rules/java/finalizers.md | 57 +- docs/pages/pmd/rules/java/imports.md | 26 +- docs/pages/pmd/rules/java/j2ee.md | 131 ++++- docs/pages/pmd/rules/java/javabeans.md | 20 +- docs/pages/pmd/rules/java/junit.md | 118 ++++- .../pmd/rules/java/logging-jakarta-commons.md | 34 +- docs/pages/pmd/rules/java/logging-java.md | 41 +- docs/pages/pmd/rules/java/migrating.md | 104 +++- docs/pages/pmd/rules/java/naming.md | 147 +++++- docs/pages/pmd/rules/java/optimizations.md | 112 +++- docs/pages/pmd/rules/java/strictexception.md | 102 +++- docs/pages/pmd/rules/java/strings.md | 80 ++- docs/pages/pmd/rules/java/sunsecure.md | 8 +- docs/pages/pmd/rules/java/unnecessary.md | 107 +++- docs/pages/pmd/rules/java/unusedcode.md | 16 +- docs/pages/pmd/rules/jsp/basic-jsf.md | 6 +- docs/pages/pmd/rules/jsp/basic.md | 68 ++- docs/pages/pmd/rules/plsql/TomKytesDespair.md | 6 +- docs/pages/pmd/rules/plsql/codesize.md | 80 ++- docs/pages/pmd/rules/plsql/dates.md | 23 +- docs/pages/pmd/rules/plsql/strictsyntax.md | 6 +- docs/pages/pmd/rules/vf/security.md | 8 +- docs/pages/pmd/rules/vm/basic.md | 38 +- docs/pages/pmd/rules/xml/basic.md | 6 +- docs/pages/pmd/rules/xsl/xpath.md | 25 +- 44 files changed, 2495 insertions(+), 375 deletions(-) diff --git a/docs/pages/pmd/rules/apex/apexunit.md b/docs/pages/pmd/rules/apex/apexunit.md index a4826becf..ac9c8510c 100644 --- a/docs/pages/pmd/rules/apex/apexunit.md +++ b/docs/pages/pmd/rules/apex/apexunit.md @@ -8,13 +8,15 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/apexunit.xml --- ## ApexUnitTestClassShouldHaveAsserts -**Since:** 5.5.1 +**Since:** PMD 5.5.1 **Priority:** Medium (3) Apex unit tests should include at least one assertion. This makes the tests more robust, and using assert with messages provide the developer a clearer idea of what the test does. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestClassShouldHaveAsserts](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/ApexUnitTestClassShouldHaveAsserts.java) + **Example(s):** ``` @@ -39,12 +41,14 @@ public class Foo { ## ApexUnitTestShouldNotUseSeeAllDataTrue -**Since:** 5.5.1 +**Since:** PMD 5.5.1 **Priority:** Medium (3) Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database data for unexpected modification by tests. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.apexunit.ApexUnitTestShouldNotUseSeeAllDataTrue](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/apexunit/ApexUnitTestShouldNotUseSeeAllDataTrue.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/apex/braces.md b/docs/pages/pmd/rules/apex/braces.md index 4018e5747..35799ce58 100644 --- a/docs/pages/pmd/rules/apex/braces.md +++ b/docs/pages/pmd/rules/apex/braces.md @@ -8,7 +8,7 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/braces.xml --- ## ForLoopsMustUseBraces -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) @@ -16,6 +16,14 @@ Avoid using 'for' statements without using surrounding braces. If the code forma indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//ForLoopStatement +[child::ExpressionStatement] +| +//ForEachStatement +[child::ExpressionStatement] +``` + **Example(s):** ``` @@ -37,7 +45,7 @@ for (int i = 0; i < 42; i++) { // preferred approach ## IfElseStmtsMustUseBraces -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) @@ -45,6 +53,14 @@ Avoid using if..else statements without using surrounding braces. If the code fo or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//ExpressionStatement[parent::IfBlockStatement] +| +//ExpressionStatement[parent::IfElseBlockStatement] +| +//IfElseBlockStatement[parent::IfBlockStatement] +``` + **Example(s):** ``` @@ -68,7 +84,7 @@ if (foo) ## IfStmtsMustUseBraces -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) @@ -76,6 +92,10 @@ Avoid using if statements without using braces to surround the code block. If th formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//IfBlockStatement/ExpressionStatement +``` + **Example(s):** ``` @@ -97,7 +117,7 @@ if (foo) { // preferred approach ## WhileLoopsMustUseBraces -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) @@ -105,6 +125,10 @@ Avoid using 'while' statements without using braces to surround the code block. formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//WhileLoopStatement/ExpressionStatement +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/apex/complexity.md b/docs/pages/pmd/rules/apex/complexity.md index 11df749c4..7fb9358c9 100644 --- a/docs/pages/pmd/rules/apex/complexity.md +++ b/docs/pages/pmd/rules/apex/complexity.md @@ -8,12 +8,14 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/complexity.xml --- ## AvoidDeeplyNestedIfStmts -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.AvoidDeeplyNestedIfStmtsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/AvoidDeeplyNestedIfStmtsRule.java) + **Example(s):** ``` @@ -41,7 +43,7 @@ public class Foo { ## ExcessiveClassLength -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -49,6 +51,8 @@ Excessive class file lengths are usually indications that the class may be burde responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveClassLengthRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveClassLengthRule.java) + **Example(s):** ``` @@ -81,13 +85,15 @@ public class Foo { ## ExcessiveParameterList -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveParameterListRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessiveParameterListRule.java) + **Example(s):** ``` @@ -114,7 +120,7 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { ## ExcessivePublicCount -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -123,6 +129,8 @@ since combinational side effects grow rapidly and increase risk. Refactoring the smaller ones not only increases testability and reliability but also allows new variations to be developed easily. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.ExcessivePublicCountRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/ExcessivePublicCountRule.java) + **Example(s):** ``` @@ -152,7 +160,7 @@ public class Foo { ## NcssConstructorCount -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -160,6 +168,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.NcssConstructorCountRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssConstructorCountRule.java) + **Example(s):** ``` @@ -189,7 +199,7 @@ public class Foo extends Bar { ## NcssMethodCount -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -197,6 +207,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.NcssMethodCountRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssMethodCountRule.java) + **Example(s):** ``` @@ -225,7 +237,7 @@ public class Foo extends Bar { ## NcssTypeCount -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -233,6 +245,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.NcssTypeCountRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/NcssTypeCountRule.java) + **Example(s):** ``` @@ -263,7 +277,7 @@ public class Foo extends Bar { ## StdCyclomaticComplexity -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -272,6 +286,8 @@ plus one for the method entry. The decision points include 'if', 'while', 'for' Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.StdCyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/StdCyclomaticComplexityRule.java) + **Example(s):** ``` @@ -327,7 +343,7 @@ high complexity, and 11+ is very high complexity. ## TooManyFields -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -335,6 +351,8 @@ Classes that have too many fields can become unwieldy and could be redesigned to possibly through grouping related fields in new objects. For example, a class with individual city/state/zip fields could park them within a single Address field. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.complexity.TooManyFieldsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/complexity/TooManyFieldsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md index 80ea8bb85..6779c939b 100644 --- a/docs/pages/pmd/rules/apex/performance.md +++ b/docs/pages/pmd/rules/apex/performance.md @@ -8,12 +8,14 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/performance.xml --- ## AvoidDmlStatementsInLoops -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) Avoid DML statements inside loops to avoid hitting the DML governor limit. Instead, try to batch up the data into a list and invoke your DML once on that list of data outside the loop. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.performance.AvoidDmlStatementsInLoopsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidDmlStatementsInLoopsRule.java) + **Example(s):** ``` @@ -38,12 +40,14 @@ public class Something { ## AvoidSoqlInLoops -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) New objects created within loops should be checked to see if they can created outside them and reused. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.performance.AvoidSoqlInLoopsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/performance/AvoidSoqlInLoopsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md index 49186a95e..c27fdac3e 100644 --- a/docs/pages/pmd/rules/apex/security.md +++ b/docs/pages/pmd/rules/apex/security.md @@ -8,13 +8,15 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/security.xml --- ## ApexBadCrypto -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) The rule makes sure you are using randomly generated IVs and keys for `Crypto` calls. Hard-wiring these values greatly compromises the security of encrypted data. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexBadCryptoRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexBadCryptoRule.java) + **Example(s):** ``` @@ -36,7 +38,7 @@ public without sharing class Foo { ## ApexCRUDViolation -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) @@ -44,6 +46,8 @@ The rule validates you are checking for access permissions before a SOQL/SOSL/DM Since Apex runs in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexCRUDViolationRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java) + **Example(s):** ``` @@ -73,13 +77,15 @@ public class Foo { ## ApexCSRF -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Check to avoid making DML operations in Apex class constructor/init method. This prevents modification of the database just by accessing a page. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexCSRFRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java) + **Example(s):** ``` @@ -104,7 +110,7 @@ public class Foo { ## ApexDangerousMethods -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) @@ -117,6 +123,8 @@ opens the door to several attacks and requires manual validation, which is unrel * Calling `System.debug` passing sensitive data as parameter, which could lead to exposure of private data. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexDangerousMethodsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java) + **Example(s):** ``` @@ -137,13 +145,15 @@ public class Foo { ## ApexInsecureEndpoint -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Checks against accessing endpoints under plain **http**. You should always use **https** for security. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexInsecureEndpointRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java) + **Example(s):** ``` @@ -165,13 +175,15 @@ public without sharing class Foo { ## ApexOpenRedirect -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Checks against redirects to user-controlled locations. This prevents attackers from redirecting users to phishing sites. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexOpenRedirectRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java) + **Example(s):** ``` @@ -193,13 +205,15 @@ public without sharing class Foo { ## ApexSharingViolations -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Detect classes declared without explicit sharing mode if DML methods are used. This forces the developer to take access restrictions into account before modifying objects. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexSharingViolationsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java) + **Example(s):** ``` @@ -218,12 +232,14 @@ public without sharing class Foo { ## ApexSOQLInjection -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Detects the usage of untrusted / unescaped variables in DML queries. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexSOQLInjectionRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java) + **Example(s):** ``` @@ -244,7 +260,7 @@ public class Foo { ## ApexSuggestUsingNamedCred -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) @@ -262,6 +278,8 @@ Instead, you should use *Named Credentials* and a callout endpoint. For more information, you can check [this](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials.htm) +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexSuggestUsingNamedCredRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java) + **Example(s):** ``` @@ -284,7 +302,7 @@ public class Foo { ## ApexXSSFromEscapeFalse -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) @@ -292,6 +310,8 @@ Reports on calls to `addError` with disabled escaping. The message passed to `ad will be displayed directly to the user in the UI, making it prime ground for XSS attacks if unescaped. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromEscapeFalseRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java) + **Example(s):** ``` @@ -310,13 +330,15 @@ public without sharing class Foo { ## ApexXSSFromURLParam -**Since:** 5.5.3 +**Since:** PMD 5.5.3 **Priority:** Medium (3) Makes sure that all values obtained from URL parameters are properly escaped / sanitized to avoid XSS attacks. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.security.ApexXSSFromURLParamRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/apex/style.md b/docs/pages/pmd/rules/apex/style.md index 0885a4dca..067dd9b1a 100644 --- a/docs/pages/pmd/rules/apex/style.md +++ b/docs/pages/pmd/rules/apex/style.md @@ -8,13 +8,15 @@ editmepath: ../pmd-apex/src/main/resources/rulesets/apex/style.xml --- ## AvoidGlobalModifier -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) Global classes should be avoided (especially in managed packages) as they can never be deleted or changed in signature. Always check twice if something needs to be global. Many interfaces (e.g. Batch) required global modifiers in the past but don't require this anymore. Don't lock yourself in. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.AvoidGlobalModifierRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidGlobalModifierRule.java) + **Example(s):** ``` @@ -35,7 +37,7 @@ global class Unchangeable { ## AvoidLogicInTrigger -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -44,6 +46,8 @@ Therefore delegate the triggers work to a regular class (often called Trigger ha See more here: https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.AvoidLogicInTriggerRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/AvoidLogicInTriggerRule.java) + **Example(s):** ``` @@ -72,12 +76,14 @@ trigger Accounts on Account (before insert, before update, before delete, after ## ClassNamingConventions -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** High (1) Class names should always begin with an upper case character. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.ClassNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/ClassNamingConventionsRule.java) + **Example(s):** ``` @@ -94,12 +100,14 @@ public class Foo {} ## MethodNamingConventions -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** High (1) Method names should always begin with a lower case character, and should not contain underscores. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.MethodNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodNamingConventionsRule.java) + **Example(s):** ``` @@ -119,12 +127,14 @@ public class Foo { ## MethodWithSameNameAsEnclosingClass -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) Non-constructor methods should not have the same name as the enclosing class. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.MethodWithSameNameAsEnclosingClassRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/MethodWithSameNameAsEnclosingClassRule.java) + **Example(s):** ``` @@ -146,7 +156,7 @@ public class MyClass { ## VariableNamingConventions -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** High (1) @@ -154,6 +164,8 @@ A variable naming conventions rule - customize this to your liking. Currently, checks for final variables that should be fully capitalized and non-final variables that should not include underscores. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.style.VariableNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/style/VariableNamingConventionsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/ecmascript/basic.md b/docs/pages/pmd/rules/ecmascript/basic.md index 31967073d..bbc859cf5 100644 --- a/docs/pages/pmd/rules/ecmascript/basic.md +++ b/docs/pages/pmd/rules/ecmascript/basic.md @@ -8,13 +8,27 @@ editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/basic.xml --- ## AssignmentInOperand -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium High (2) Avoid assignments in operands; this can make code more complicated and harder to read. This is sometime indicative of the bug where the assignment operator '=' was used instead of the equality operator '=='. +``` +//IfStatement[$allowIf = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +| + //WhileLoop[$allowWhile = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +| + //DoLoop[$allowWhile = "false"]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +| + //ForLoop[$allowFor = "false"]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +| + //ConditionalExpression[$allowTernary = "false"]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +| + //ConditionalExpression[$allowTernaryResults = "false"]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UnaryExpression[$allowIncrementDecrement = "false" and (@Image = "--" or @Image = "++")]] +``` + **Example(s):** ``` @@ -42,12 +56,18 @@ function getX() { ## AvoidTrailingComma -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** High (1) This rule helps improve code portability due to differences in browser treatment of trailing commas in object or array literals. +``` +//ObjectLiteral[$allowObjectLiteral = "false" and @TrailingComma = 'true'] +| + //ArrayLiteral[$allowArrayLiteral = "false" and @TrailingComma = 'true'] +``` + **Example(s):** ``` @@ -69,7 +89,7 @@ function(arg) { ## ConsistentReturn -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium High (2) @@ -77,6 +97,8 @@ ECMAScript does provide for return types on functions, and therefore there is no However, when a function does use returns they should all have a value, or all with no value. Mixed return usage is likely a bug, or at best poor style. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.ecmascript.rule.basic.ConsistentReturnRule](https://github.com/pmd/pmd/blob/master/pmd-javascript/src/main/java/net/sourceforge/pmd/lang/ecmascript/rule/basic/ConsistentReturnRule.java) + **Example(s):** ``` @@ -107,13 +129,22 @@ function bar() { ## EqualComparison -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Using == in condition may lead to unexpected results, as the variables are automatically casted to be of the same type. The === operator avoids the casting. +``` +//InfixExpression[(@Image = "==" or @Image = "!=") + and + (child::KeywordLiteral[@Image = "true" or @Image = "false"] + or + child::NumberLiteral) +] +``` + **Example(s):** ``` @@ -137,13 +168,17 @@ if (someVar != 3) { ## GlobalVariable -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** High (1) This rule helps to avoid using accidently global variables by simply missing the "var" declaration. Global variables can lead to side-effects that are hard to debug. +``` +//Assignment[Name/@GlobalName = 'true'] +``` + **Example(s):** ``` @@ -158,13 +193,21 @@ function(arg) { ## InnaccurateNumericLiteral -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium High (2) The numeric literal will have at different value at runtime, which can happen if you provide too much precision in a floating point number. This may result in numeric calculations being in error. +``` +//NumberLiteral[ + @Image != @Number + and translate(@Image, "e", "E") != @Number + and concat(@Image, ".0") != @Number + and @Image != substring-before(translate(@Number, ".", ""), "E")] +``` + **Example(s):** ``` @@ -179,7 +222,7 @@ var z = 1.12345678901234567; // Not good ## ScopeForInVariable -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** High (1) @@ -190,6 +233,10 @@ has finished, the variable will contain the last value used in the for-in, and t the for-in loop will be gone. Since the for-in variable name is most likely intended to be a temporary name, it is better to explicitly scope the variable name to the nearest enclosing scope with 'var'. +``` +//ForInLoop[not(child::VariableDeclaration)]/Name[1] +``` + **Example(s):** ``` @@ -223,13 +270,23 @@ function bar() { ## UnreachableCode -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** High (1) A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these will never execute. This is a bug, or extremely poor style. +``` +//ReturnStatement[following-sibling::node()] +| + //ContinueStatement[following-sibling::node()] +| + //BreakStatement[following-sibling::node()] +| + //ThrowStatement[following-sibling::node()] +``` + **Example(s):** ``` @@ -247,12 +304,20 @@ function bar() { ## UseBaseWithParseInt -**Since:** 5.0.1 +**Since:** PMD 5.0.1 **Priority:** High (1) TODO +``` +//FunctionCall/Name[ + @Image = 'parseInt' + and + count(../*) < 3 +] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/ecmascript/braces.md b/docs/pages/pmd/rules/ecmascript/braces.md index 42a080587..47ff893a4 100644 --- a/docs/pages/pmd/rules/ecmascript/braces.md +++ b/docs/pages/pmd/rules/ecmascript/braces.md @@ -8,12 +8,18 @@ editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/braces.xml --- ## ForLoopsMustUseBraces -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using 'for' statements without using curly braces. +``` +//ForLoop[not(child::Scope)] +| + //ForInLoop[not(child::Scope)] +``` + **Example(s):** ``` @@ -29,12 +35,18 @@ for (var i = 0; i < 42; i++) ## IfElseStmtsMustUseBraces -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using if..else statements without using curly braces. +``` +//ExpressionStatement[parent::IfStatement[@Else = "true"]] + [not(child::Scope)] + [not(child::IfStatement)] +``` + **Example(s):** ``` @@ -54,12 +66,16 @@ else ## IfStmtsMustUseBraces -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using if statements without using curly braces. +``` +//IfStatement[@Else = "false" and not(child::Scope)] +``` + **Example(s):** ``` @@ -75,12 +91,16 @@ if (foo) ## WhileLoopsMustUseBraces -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using 'while' statements without using curly braces. +``` +//WhileLoop[not(child::Scope)] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/ecmascript/unnecessary.md b/docs/pages/pmd/rules/ecmascript/unnecessary.md index 34b353857..a87140ecc 100644 --- a/docs/pages/pmd/rules/ecmascript/unnecessary.md +++ b/docs/pages/pmd/rules/ecmascript/unnecessary.md @@ -8,7 +8,7 @@ editmepath: ../pmd-javascript/src/main/resources/rulesets/ecmascript/unnecessary --- ## NoElseReturn -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Medium (3) @@ -17,6 +17,10 @@ The else block in a if-else-construct is unnecessary if the `if` block contains See also: http://eslint.org/docs/rules/no-else-return +``` +//IfStatement[@Else="true"][Scope[1]/ReturnStatement] +``` + **Example(s):** ``` @@ -36,7 +40,7 @@ return z; ## UnnecessaryBlock -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) @@ -44,6 +48,14 @@ An unnecessary Block is present. Such Blocks are often used in other languages introduce a new variable scope. Blocks do not behave like this in ECMAScipt, and using them can be misleading. Considering removing this unnecessary Block. +``` +//Block[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop + or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)] +| + //Scope[not(parent::FunctionNode or parent::IfStatement or parent::ForLoop or parent::ForInLoop + or parent::WhileLoop or parent::DoLoop or parent::TryStatement or parent::CatchClause)] +``` + **Example(s):** ``` @@ -59,12 +71,16 @@ if (bar) { ## UnnecessaryParentheses -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) Unnecessary parentheses should be removed. +``` +//ParenthesizedExpression/ParenthesizedExpression +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/android.md b/docs/pages/pmd/rules/java/android.md index 703492904..2f454543d 100644 --- a/docs/pages/pmd/rules/java/android.md +++ b/docs/pages/pmd/rules/java/android.md @@ -8,12 +8,32 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/android.xml --- ## CallSuperFirst -**Since:** 4.2.5 +**Since:** PMD 4.2.5 **Priority:** Medium (3) Super should be called at the start of the method +``` +//MethodDeclaration[MethodDeclarator[ + @Image='onCreate' or + @Image='onConfigurationChanged' or + @Image='onPostCreate' or + @Image='onPostResume' or + @Image='onRestart' or + @Image='onRestoreInstanceState' or + @Image='onResume' or + @Image='onStart' + ]] + /Block[not( + (BlockStatement[1]/Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image]))] +[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[ + typeof(@Image, 'android.app.Activity', 'Activity') or + typeof(@Image, 'android.app.Application', 'Application') or + typeof(@Image, 'android.app.Service', 'Service') +]]] +``` + **Example(s):** ``` @@ -27,12 +47,30 @@ public class DummyActivity extends Activity { ## CallSuperLast -**Since:** 4.2.5 +**Since:** PMD 4.2.5 **Priority:** Medium (3) Super should be called at the end of the method +``` +//MethodDeclaration[MethodDeclarator[ + @Image='finish' or + @Image='onDestroy' or + @Image='onPause' or + @Image='onSaveInstanceState' or + @Image='onStop' or + @Image='onTerminate' + ]] + /Block/BlockStatement[last()] + [not(Statement/StatementExpression/PrimaryExpression[./PrimaryPrefix[@SuperModifier='true']]/PrimarySuffix[@Image= ancestor::MethodDeclaration/MethodDeclarator/@Image])] +[ancestor::ClassOrInterfaceDeclaration[ExtendsList/ClassOrInterfaceType[ + typeof(@Image, 'android.app.Activity', 'Activity') or + typeof(@Image, 'android.app.Application', 'Application') or + typeof(@Image, 'android.app.Service', 'Service') +]]] +``` + **Example(s):** ``` @@ -46,12 +84,16 @@ public class DummyActivity extends Activity { ## DoNotHardCodeSDCard -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium (3) Use Environment.getExternalStorageDirectory() instead of "/sdcard" +``` +//Literal[starts-with(@Image,'"/sdcard')] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/basic.md b/docs/pages/pmd/rules/java/basic.md index f93c39121..190861d67 100644 --- a/docs/pages/pmd/rules/java/basic.md +++ b/docs/pages/pmd/rules/java/basic.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/basic.xml --- ## AvoidBranchingStatementAsLastInLoop -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium High (2) Using a branching statement as the last part of a loop may be a bug, and/or is confusing. Ensure that the usage is not a bug, or consider using another approach. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.AvoidBranchingStatementAsLastInLoopRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidBranchingStatementAsLastInLoopRule.java) + **Example(s):** ``` @@ -44,7 +46,7 @@ for (int i = 0; i < 10; i++) { ## AvoidDecimalLiteralsInBigDecimalConstructor -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) @@ -58,6 +60,28 @@ The (String) constructor, on the other hand, is perfectly predictable: 'new BigD exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the (String) constructor be used in preference to this one. +``` +//AllocationExpression +[ClassOrInterfaceType[@Image="BigDecimal"]] +[Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix + [ + Literal[(not(ends-with(@Image,'"'))) and contains(@Image,".")] + or + Name[ancestor::Block/BlockStatement/LocalVariableDeclaration + [Type[PrimitiveType[@Image='double' or @Image='float'] + or ReferenceType/ClassOrInterfaceType[@Image='Double' or @Image='Float']]] + /VariableDeclarator/VariableDeclaratorId/@Image = @Image + ] + or + Name[ancestor::MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter + [Type[PrimitiveType[@Image='double' or @Image='float'] + or ReferenceType/ClassOrInterfaceType[@Image='Double' or @Image='Float']]] + /VariableDeclaratorId/@Image = @Image + ] + ] +] +``` + **Example(s):** ``` @@ -70,13 +94,15 @@ BigDecimal bd = new BigDecimal(12); // preferred approach, ok for integer v ## AvoidMultipleUnaryOperators -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium High (2) The use of multiple unary operators may be problematic, and/or confusing. Ensure that the intended usage is not a bug, or consider simplifying the expression. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.AvoidMultipleUnaryOperatorsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidMultipleUnaryOperatorsRule.java) + **Example(s):** ``` @@ -101,13 +127,18 @@ int j = -~7; ## AvoidThreadGroup -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment it contains methods that are not thread-safe. +``` +//AllocationExpression/ClassOrInterfaceType[pmd-java:typeof(@Image, 'java.lang.ThreadGroup')]| +//PrimarySuffix[contains(@Image, 'getThreadGroup')] +``` + **Example(s):** ``` @@ -123,13 +154,15 @@ public class Bar { ## AvoidUsingHardCodedIP -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) Application with hard-coded IP addresses can become impossible to deploy in some cases. Externalizing IP adresses is preferable. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.AvoidUsingHardCodedIPRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingHardCodedIPRule.java) + **Example(s):** ``` @@ -147,13 +180,15 @@ public class Foo { ## AvoidUsingOctalValues -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) Integer literals should not start with zero since this denotes that the rest of literal will be interpreted as an octal value. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.AvoidUsingOctalValuesRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/AvoidUsingOctalValuesRule.java) + **Example(s):** ``` @@ -170,13 +205,15 @@ k = i * j; // set k with 80 not 120 ## BigIntegerInstantiation -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) Don't create instances of already existing BigInteger (BigInteger.ZERO, BigInteger.ONE) and for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN) +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.BigIntegerInstantiationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/BigIntegerInstantiationRule.java) + **Example(s):** ``` @@ -189,12 +226,14 @@ bi4 = new BigInteger(0); // reference BigInteger.ZERO instead ## BooleanInstantiation -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** Medium High (2) Avoid instantiating Boolean objects; you can reference Boolean.TRUE, Boolean.FALSE, or call Boolean.valueOf() instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.BooleanInstantiationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/BooleanInstantiationRule.java) + **Example(s):** ``` @@ -204,13 +243,15 @@ Boolean buz = Boolean.valueOf(false); // ...., just reference Boolean.FALSE; ## BrokenNullCheck -**Since:** 3.8 +**Since:** PMD 3.8 **Priority:** Medium High (2) The null check is broken since it will throw a NullPointerException itself. It is likely that you used || instead of && or vice versa. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.BrokenNullCheckRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/BrokenNullCheckRule.java) + **Example(s):** ``` @@ -226,13 +267,15 @@ public String bar(String string) { ## CheckResultSet -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) Always check the return values of navigation methods (next, previous, first, last) of a ResultSet. If the value return is 'false', it should be handled properly. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.CheckResultSetRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/CheckResultSetRule.java) + **Example(s):** ``` @@ -252,12 +295,14 @@ if (rst.next()) { // result is properly examined and used ## CheckSkipResult -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) The skip() method may skip a smaller number of bytes than requested. Check the returned value to find out if it was the case or not. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.CheckSkipResultRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/CheckSkipResultRule.java) + **Example(s):** ``` @@ -281,7 +326,7 @@ public class Foo { ## ClassCastExceptionWithToArray -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) @@ -289,6 +334,18 @@ When deriving an array of a specific class from your Collection, one should prov the same class as the parameter of the toArray() method. Doing otherwise you will will result in a ClassCastException. +``` +//CastExpression[Type/ReferenceType/ClassOrInterfaceType[@Image != +"Object"]]/PrimaryExpression +[ + PrimaryPrefix/Name[ends-with(@Image, '.toArray')] + and + PrimarySuffix/Arguments[count(*) = 0] +and +count(PrimarySuffix) = 1 +] +``` + **Example(s):** ``` @@ -305,12 +362,21 @@ Integer[] b = (Integer [])c.toArray(new Integer[c.size()]); ## CollapsibleIfStatements -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. +``` +//IfStatement[@Else='false']/Statement + /IfStatement[@Else='false'] + | +//IfStatement[@Else='false']/Statement + /Block[count(BlockStatement)=1]/BlockStatement + /Statement/IfStatement[@Else='false'] +``` + **Example(s):** ``` @@ -331,12 +397,27 @@ void bar() { ## DontCallThreadRun -**Since:** 4.3 +**Since:** PMD 4.3 **Priority:** Medium Low (4) Explicitly calling Thread.run() method will execute in the caller's thread of control. Instead, call Thread.start() for the intended behavior. +``` +//StatementExpression/PrimaryExpression +[ + PrimaryPrefix + [ + ./Name[ends-with(@Image, '.run') or @Image = 'run'] + and substring-before(Name/@Image, '.') =//VariableDeclarator/VariableDeclaratorId/@Image + [../../../Type/ReferenceType[ClassOrInterfaceType/@Image = 'Thread']] + or ( + ./AllocationExpression/ClassOrInterfaceType[@Image = 'Thread'] + and ../PrimarySuffix[@Image = 'run']) + ] +] +``` + **Example(s):** ``` @@ -347,7 +428,7 @@ new Thread().run(); // same violation ## DontUseFloatTypeForLoopIndices -**Since:** 4.3 +**Since:** PMD 4.3 **Priority:** Medium (3) @@ -355,6 +436,11 @@ Don't use floating point for loop indices. If you must use floating point, use d unless you're certain that float provides enough precision and you have a compelling performance need (space or time). +``` +//ForStatement/ForInit/LocalVariableDeclaration +/Type/PrimitiveType[@Image="float"] +``` + **Example(s):** ``` @@ -373,7 +459,7 @@ public class Count { ## DoubleCheckedLocking -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** High (1) @@ -386,6 +472,8 @@ Note: With Java 5, you can make Double checked locking work, if you declare the For more details refer to: http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html or http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.DoubleCheckedLockingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/DoubleCheckedLockingRule.java) + **Example(s):** ``` @@ -406,12 +494,16 @@ public class Foo { ## ExtendsObject -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) No need to explicitly extend Object. +``` +//ExtendsList/ClassOrInterfaceType[@Image='Object' or @Image='java.lang.Object'] +``` + **Example(s):** ``` @@ -421,12 +513,21 @@ public class Foo extends Object { // not required ## ForLoopShouldBeWhileLoop -**Since:** 1.02 +**Since:** PMD 1.02 **Priority:** Medium (3) Some for loops can be simplified to while loops, this makes them more concise. +``` +//ForStatement + [count(*) > 1] + [not(LocalVariableDeclaration)] + [not(ForInit)] + [not(ForUpdate)] + [not(Type and Expression and Statement)] +``` + **Example(s):** ``` @@ -439,12 +540,21 @@ public class Foo { ## JumbledIncrementer -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. +``` +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + **Example(s):** ``` @@ -461,13 +571,33 @@ public class JumbledIncrementerRule1 { ## MisplacedNullCheck -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) The null check here is misplaced. If the variable is null a NullPointerException will be thrown. Either the check is useless (the variable will never be "null") or it is incorrect. +``` +//Expression + /*[self::ConditionalOrExpression or self::ConditionalAndExpression] + /descendant::PrimaryExpression/PrimaryPrefix + /Name[starts-with(@Image, + concat(ancestor::PrimaryExpression/following-sibling::EqualityExpression + [./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] + /PrimaryExpression/PrimaryPrefix + /Name[count(../../PrimarySuffix)=0]/@Image,".") + ) + ] + [count(ancestor::ConditionalAndExpression/EqualityExpression + [@Image='!='] + [./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] + [starts-with(following-sibling::*/PrimaryExpression/PrimaryPrefix/Name/@Image, + concat(./PrimaryExpression/PrimaryPrefix/Name/@Image, '.'))] + ) = 0 + ] +``` + **Example(s):** ``` @@ -488,12 +618,14 @@ public class Foo { ## OverrideBothEqualsAndHashcode -**Since:** 0.4 +**Since:** PMD 0.4 **Priority:** Medium (3) Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/basic/OverrideBothEqualsAndHashcodeRule.java) + **Example(s):** ``` @@ -521,12 +653,16 @@ public class Foo { // perfect, both methods provided ## ReturnFromFinallyBlock -**Since:** 1.05 +**Since:** PMD 1.05 **Priority:** Medium (3) Avoid returning from a finally block, this can discard exceptions. +``` +//FinallyStatement//ReturnStatement +``` + **Example(s):** ``` @@ -545,7 +681,7 @@ public class Bar { ## SimplifiedTernary -**Since:** 5.4.0 +**Since:** PMD 5.4.0 **Priority:** Medium (3) @@ -559,6 +695,12 @@ or `!condition || foo` when the literalBoolean is true `condition && foo` when the literalBoolean is false +``` +//ConditionalExpression[@Ternary='true'][not(PrimaryExpression/*/Literal) and (Expression/PrimaryExpression/*/Literal/BooleanLiteral)] +| +//ConditionalExpression[@Ternary='true'][not(Expression/PrimaryExpression/*/Literal) and (PrimaryExpression/*/Literal/BooleanLiteral)] +``` + **Example(s):** ``` @@ -583,12 +725,18 @@ public class Foo { ## UnconditionalIfStatement -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) Do not use "if" statements whose conditionals are always true or always false. +``` +//IfStatement/Expression + [count(PrimaryExpression)=1] + /PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/braces.md b/docs/pages/pmd/rules/java/braces.md index 9fac8304e..66434c31e 100644 --- a/docs/pages/pmd/rules/java/braces.md +++ b/docs/pages/pmd/rules/java/braces.md @@ -8,7 +8,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/braces.xml --- ## ForLoopsMustUseBraces -**Since:** 0.7 +**Since:** PMD 0.7 **Priority:** Medium (3) @@ -16,6 +16,10 @@ Avoid using 'for' statements without using curly braces. If the code formatting indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//ForStatement[not(Statement/Block)] +``` + **Example(s):** ``` @@ -25,7 +29,7 @@ for (int i = 0; i < 42; i++) ## IfElseStmtsMustUseBraces -**Since:** 0.2 +**Since:** PMD 0.2 **Priority:** Medium (3) @@ -33,6 +37,13 @@ Avoid using if..else statements without using surrounding braces. If the code fo or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//Statement + [parent::IfStatement[@Else='true']] + [not(child::Block)] + [not(child::IfStatement)] +``` + **Example(s):** ``` @@ -48,7 +59,7 @@ if (foo) ## IfStmtsMustUseBraces -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) @@ -56,6 +67,10 @@ Avoid using if statements without using braces to surround the code block. If th formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//IfStatement[count(*) < 3][not(Statement/Block)] +``` + **Example(s):** ``` @@ -69,7 +84,7 @@ if (foo) { // preferred approach ## WhileLoopsMustUseBraces -**Since:** 0.7 +**Since:** PMD 0.7 **Priority:** Medium (3) @@ -77,6 +92,10 @@ Avoid using 'while' statements without using braces to surround the code block. formatting or indentation is lost then it becomes difficult to separate the code being controlled from the rest. +``` +//WhileStatement[not(Statement/Block)] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md index 5b48edda4..0cabfe576 100644 --- a/docs/pages/pmd/rules/java/clone.md +++ b/docs/pages/pmd/rules/java/clone.md @@ -8,13 +8,21 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/clone.xml --- ## CloneMethodMustBePublic -**Since:** 5.4.0 +**Since:** PMD 5.4.0 **Priority:** Medium (3) The java Manual says "By convention, classes that implement this interface should override Object.clone (which is protected) with a public method." +``` +//MethodDeclaration[@Public='false'] +[ +MethodDeclarator/@Image = 'clone' +and MethodDeclarator/FormalParameters/@ParameterCount = 0 +] +``` + **Example(s):** ``` @@ -38,12 +46,27 @@ public class Foo implements Cloneable { ## CloneMethodMustImplementCloneable -**Since:** 1.9 +**Since:** PMD 1.9 **Priority:** Medium (3) The method clone() should only be implemented if the class implements the Cloneable interface with the exception of a final method that only throws CloneNotSupportedException. +``` +//ClassOrInterfaceDeclaration +[not(./ExtendsList/ClassOrInterfaceType[@Image='Cloneable'])] +[not(./ImplementsList/ClassOrInterfaceType[@Image='Cloneable'])] +/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration +[MethodDeclaration +[MethodDeclarator[@Image += 'clone' and count(FormalParameters/*) = 0]] +[not((../MethodDeclaration[@Final = 'true'] or ancestor::ClassOrInterfaceDeclaration[1][@Final = 'true']) +and Block[count(BlockStatement)=1] +/BlockStatement/Statement/ThrowStatement/Expression +/PrimaryExpression/PrimaryPrefix/AllocationExpression +/ClassOrInterfaceType[@Image = 'CloneNotSupportedException'])]] +``` + **Example(s):** ``` @@ -56,7 +79,7 @@ public class MyClass { ## CloneMethodReturnTypeMustMatchClassName -**Since:** 5.4.0 +**Since:** PMD 5.4.0 **Priority:** Medium (3) @@ -65,6 +88,15 @@ of the clone method doesn't need to cast the returned clone to the correct type. Note: This is only possible with Java 1.5 or higher. +``` +//MethodDeclaration +[ +MethodDeclarator/@Image = 'clone' +and MethodDeclarator/FormalParameters/@ParameterCount = 0 +and not (ResultType//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration[1]/@Image) +] +``` + **Example(s):** ``` @@ -83,12 +115,25 @@ public class Foo implements Cloneable { ## CloneThrowsCloneNotSupportedException -**Since:** 1.9 +**Since:** PMD 1.9 **Priority:** Medium (3) The method clone() should throw a CloneNotSupportedException. +``` +//MethodDeclaration +[ +MethodDeclarator/@Image = 'clone' +and count(MethodDeclarator/FormalParameters/*) = 0 +and count(NameList/Name[contains +(@Image,'CloneNotSupportedException')]) = 0 +] +[ +../../../../ClassOrInterfaceDeclaration[@Final = 'false'] +] +``` + **Example(s):** ``` @@ -102,12 +147,24 @@ public class MyClass implements Cloneable{ ## ProperCloneImplementation -**Since:** 1.4 +**Since:** PMD 1.4 **Priority:** Medium High (2) Object clone() should be implemented with super.clone(). +``` +//MethodDeclarator +[@Image = 'clone'] +[count(FormalParameters/*) = 0] +[count(../Block//*[ + (self::AllocationExpression) and + (./ClassOrInterfaceType/@Image = ancestor:: +ClassOrInterfaceDeclaration[1]/@Image) + ])> 0 +] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/codesize.md b/docs/pages/pmd/rules/java/codesize.md index e338ab110..792e488c3 100644 --- a/docs/pages/pmd/rules/java/codesize.md +++ b/docs/pages/pmd/rules/java/codesize.md @@ -10,7 +10,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/codesize.xml <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> -**Since:** 1.03 +**Since:** PMD 1.03 **Priority:** Medium (3) @@ -19,6 +19,8 @@ plus one for the method entry. The decision points include 'if', 'while', 'for' Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.CyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/CyclomaticComplexityRule.java) + **Example(s):** ``` @@ -70,7 +72,7 @@ public class Foo { // This has a Cyclomatic Complexity = 12 ## ExcessiveClassLength -**Since:** 0.6 +**Since:** PMD 0.6 **Priority:** Medium (3) @@ -78,6 +80,8 @@ Excessive class file lengths are usually indications that the class may be burde responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.ExcessiveClassLengthRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/ExcessiveClassLengthRule.java) + **Example(s):** ``` @@ -109,7 +113,7 @@ public class Foo { ## ExcessiveMethodLength -**Since:** 0.6 +**Since:** PMD 0.6 **Priority:** Medium (3) @@ -118,6 +122,8 @@ name/signature might suggest. They also become challenging for others to digest scrolling causes readers to lose focus. Try to reduce the method length by creating helper methods and removing any copy/pasted code. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.ExcessiveMethodLengthRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/ExcessiveMethodLengthRule.java) + **Example(s):** ``` @@ -138,13 +144,15 @@ public void doSomething() { ## ExcessiveParameterList -**Since:** 0.9 +**Since:** PMD 0.9 **Priority:** Medium (3) Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.ExcessiveParameterListRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/ExcessiveParameterListRule.java) + **Example(s):** ``` @@ -171,7 +179,7 @@ public void addPerson( // preferred approach ## ExcessivePublicCount -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) @@ -180,6 +188,8 @@ since combinational side effects grow rapidly and increase risk. Refactoring the smaller ones not only increases testability and reliability but also allows new variations to be developed easily. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.ExcessivePublicCountRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/ExcessivePublicCountRule.java) + **Example(s):** ``` @@ -208,7 +218,7 @@ public class Foo { <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> -**Since:** 5.1.2 +**Since:** PMD 5.1.2 **Priority:** Medium (3) @@ -218,6 +228,8 @@ Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate c high complexity, and 11+ is very high complexity. Modified complexity treats switch statements as a single decision point. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.ModifiedCyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/ModifiedCyclomaticComplexityRule.java) + **Example(s):** ``` @@ -269,7 +281,7 @@ public class Foo { // This has a Cyclomatic Complexity = 9 ## NcssConstructorCount -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) @@ -277,6 +289,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given constructor. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.NcssConstructorCountRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/NcssConstructorCountRule.java) + **Example(s):** ``` @@ -304,7 +318,7 @@ public class Foo extends Bar { ## NcssMethodCount -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) @@ -312,6 +326,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.NcssMethodCountRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/NcssMethodCountRule.java) + **Example(s):** ``` @@ -339,7 +355,7 @@ public class Foo extends Bar { ## NcssTypeCount -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) @@ -347,6 +363,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.NcssTypeCountRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/NcssTypeCountRule.java) + **Example(s):** ``` @@ -374,7 +392,7 @@ public class Foo extends Bar { ## NPathComplexity -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) @@ -382,6 +400,8 @@ The NPath complexity of a method is the number of acyclic execution paths throug A threshold of 200 is generally considered the point where measures should be taken to reduce complexity and increase readability. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.NPathComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/NPathComplexityRule.java) + **Example(s):** ``` @@ -427,7 +447,7 @@ void bar() { // this is something more complex than it needs to be, <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> -**Since:** 5.1.2 +**Since:** PMD 5.1.2 **Priority:** Medium (3) @@ -436,6 +456,8 @@ plus one for the method entry. The decision points include 'if', 'while', 'for' Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.StdCyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/StdCyclomaticComplexityRule.java) + **Example(s):** ``` @@ -487,7 +509,7 @@ public class Foo { // This has a Cyclomatic Complexity = 12 ## TooManyFields -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -495,6 +517,8 @@ Classes that have too many fields can become unwieldy and could be redesigned to possibly through grouping related fields in new objects. For example, a class with individual city/state/zip fields could park them within a single Address field. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.codesize.TooManyFieldsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/codesize/TooManyFieldsRule.java) + **Example(s):** ``` @@ -520,13 +544,28 @@ public class Person { // this is more manageable ## TooManyMethods -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium (3) A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects. +``` +//ClassOrInterfaceDeclaration/ClassOrInterfaceBody + [ + count(./ClassOrInterfaceBodyDeclaration/MethodDeclaration/MethodDeclarator[ + not ( + starts-with(@Image,'get') + or + starts-with(@Image,'set') + or + starts-with(@Image,'is') + ) + ]) > $maxmethods + ] +``` + **This rule has the following properties:** |Name|Default Value|Description| diff --git a/docs/pages/pmd/rules/java/comments.md b/docs/pages/pmd/rules/java/comments.md index 96007472d..419423e79 100644 --- a/docs/pages/pmd/rules/java/comments.md +++ b/docs/pages/pmd/rules/java/comments.md @@ -8,12 +8,14 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/comments.xml --- ## CommentContent -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) A rule for the politically correct... we don't want to offend anyone. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.comments.CommentContentRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentContentRule.java) + **Example(s):** ``` @@ -30,7 +32,7 @@ A rule for the politically correct... we don't want to offend anyone. ## CommentDefaultAccessModifier -**Since:** 5.4.0 +**Since:** PMD 5.4.0 **Priority:** Medium (3) @@ -38,6 +40,8 @@ To avoid mistakes if we want that a Method, Field or Nested class have a default we must add a comment at the beginning of the Method, Field or Nested class. By default the comment must be /* default */, if you want another, you have to provide a regex. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.comments.CommentDefaultAccessModifierRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentDefaultAccessModifierRule.java) + **Example(s):** ``` @@ -71,12 +75,14 @@ public class Foo { ## CommentRequired -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Denotes whether comments are required (or unwanted) for specific language elements. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.comments.CommentRequiredRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentRequiredRule.java) + **Example(s):** ``` @@ -100,12 +106,14 @@ Denotes whether comments are required (or unwanted) for specific language elemen ## CommentSize -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Determines whether the dimensions of non-header comments found are within the specified limits. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.comments.CommentSizeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/comments/CommentSizeRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/controversial.md b/docs/pages/pmd/rules/java/controversial.md index 9ca7454da..6a42df6e7 100644 --- a/docs/pages/pmd/rules/java/controversial.md +++ b/docs/pages/pmd/rules/java/controversial.md @@ -8,12 +8,14 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/controversial.xml --- ## AssignmentInOperand -**Since:** 1.03 +**Since:** PMD 1.03 **Priority:** Medium (3) Avoid assignments in operands; this can make code more complicated and harder to read. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.AssignmentInOperandRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/AssignmentInOperandRule.java) + **Example(s):** ``` @@ -36,12 +38,23 @@ public void bar() { ## AtLeastOneConstructor -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) Each class should declare at least one constructor. +``` +//ClassOrInterfaceDeclaration[ + not(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) + and + (@Static = 'false') + and + (count(./descendant::MethodDeclaration[@Static = 'true']) < 1) +] + [@Interface='false'] +``` + **Example(s):** ``` @@ -54,7 +67,7 @@ public class Foo { ## AvoidAccessibilityAlteration -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) @@ -62,6 +75,31 @@ Methods such as getDeclaredConstructors(), getDeclaredConstructor(Class[]) and s as the interface PrivilegedAction, allows for the runtime alteration of variable, class, or method visibility, even if they are private. This violates the principle of encapsulation. +``` +//PrimaryExpression[ + ( + (PrimarySuffix[ + ends-with(@Image,'getDeclaredConstructors') + or + ends-with(@Image,'getDeclaredConstructor') + or + ends-with(@Image,'setAccessible') + ]) + or + (PrimaryPrefix/Name[ + ends-with(@Image,'getDeclaredConstructor') + or + ends-with(@Image,'getDeclaredConstructors') + or + starts-with(@Image,'AccessibleObject.setAccessible') + ]) + ) + and + (//ImportDeclaration/Name[ + contains(@Image,'java.security.PrivilegedAction')]) + ] +``` + **Example(s):** ``` @@ -96,12 +134,25 @@ public class Violation { ## AvoidFinalLocalVariable -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) Avoid using final local variables, turn them into fields. +``` +//LocalVariableDeclaration[ + @Final = 'true' + and not(../../ForStatement) + and + ( + (count(VariableDeclarator/VariableInitializer) = 0) + or + (VariableDeclarator/VariableInitializer/Expression/PrimaryExpression/PrimaryPrefix/Literal) + ) +] +``` + **Example(s):** ``` @@ -114,7 +165,7 @@ public class MyClass { ## AvoidLiteralsInIfCondition -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium (3) @@ -122,6 +173,13 @@ Avoid using hard-coded literals in conditional statements. By declaring them as or private members with descriptive names maintainability is enhanced. By default, the literals "-1" and "0" are ignored. More exceptions can be defined with the property "ignoreMagicNumbers". +``` +//IfStatement/Expression/*/PrimaryExpression/PrimaryPrefix/Literal +[not(NullLiteral)] +[not(BooleanLiteral)] +[empty(index-of(tokenize($ignoreMagicNumbers, ','), @Image))] +``` + **Example(s):** ``` @@ -153,7 +211,7 @@ public void checkRequests() { ## AvoidPrefixingMethodParameters -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) @@ -161,6 +219,12 @@ Prefixing parameters by 'in' or 'out' pollutes the name of the parameters and re To indicate whether or not a parameter will be modify in a method, its better to document method behavior with Javadoc. +``` +//MethodDeclaration/MethodDeclarator/FormalParameters/FormalParameter/VariableDeclaratorId[ + pmd:matches(@Image,'^in[A-Z].*','^out[A-Z].*','^in$','^out$') +] +``` + **Example(s):** ``` @@ -192,13 +256,17 @@ public class Foo { ## AvoidUsingNativeCode -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium High (2) Unnecessary reliance on Java Native Interface (JNI) calls directly reduces application portability and increases the maintenance burden. +``` +//Name[starts-with(@Image,'System.loadLibrary')] +``` + **Example(s):** ``` @@ -220,7 +288,7 @@ public class SomeJNIClass { ## AvoidUsingShortType -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** High (1) @@ -229,6 +297,10 @@ arithmetic capabilities for the short type: the JVM must convert the short into and convert the int back to a short. Thus any storage gains found through use of the 'short' type may be offset by adverse impacts on performance. +``` +//PrimitiveType[@Image = 'short'][name(../..) != 'CastExpression'] +``` + **Example(s):** ``` @@ -244,7 +316,7 @@ public class UsingShort { ## AvoidUsingVolatile -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium High (2) @@ -252,6 +324,12 @@ Use of the keyword 'volatile' is generally used to fine tune a Java application, a good expertise of the Java Memory Model. Moreover, its range of action is somewhat misknown. Therefore, the volatile keyword should not be used for maintenance purpose and portability. +``` +//FieldDeclaration[ + contains(@Volatile,'true') + ] +``` + **Example(s):** ``` @@ -263,13 +341,20 @@ public class ThrDeux { ## CallSuperInConstructor -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) It is a good practice to call super() in a constructor. If super() is not called but another constructor (such as an overloaded constructor) is called, this rule will not report it. +``` +//ClassOrInterfaceDeclaration[ count (ExtendsList/*) > 0 ] +/ClassOrInterfaceBody + /ClassOrInterfaceBodyDeclaration + /ConstructorDeclaration[ count (.//ExplicitConstructorInvocation)=0 ] +``` + **Example(s):** ``` @@ -288,7 +373,7 @@ public class Foo extends Bar{ ## DataflowAnomalyAnalysis -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Low (5) @@ -299,6 +384,8 @@ From those informations there can be found various problems. 2. DU - Anomaly: A recently defined variable is undefined. These anomalies may appear in normal source text. 3. DD - Anomaly: A recently defined variable is redefined. This is ominous but don't have to be a bug. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.DataflowAnomalyAnalysisRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DataflowAnomalyAnalysisRule.java) + **Example(s):** ``` @@ -319,16 +406,27 @@ public void foo() { ## DefaultPackage -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Use explicit scoping instead of accidental usage of default package private level. The rule allows methods and fields annotated with Guava's @VisibleForTesting. +``` +//ClassOrInterfaceDeclaration[@Interface='false'] +/ClassOrInterfaceBody +/ClassOrInterfaceBodyDeclaration +[not(Annotation//Name[ends-with(@Image, 'VisibleForTesting')])] +[ +FieldDeclaration[@PackagePrivate='true'] +or MethodDeclaration[@PackagePrivate='true'] +] +``` + ## DoNotCallGarbageCollectionExplicitly -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium High (2) @@ -337,6 +435,18 @@ same behavior whether the garbage collection is disabled using the option -Xdisa Moreover, "modern" jvms do a very good job handling garbage collections. If memory usage issues unrelated to memory leaks develop within an application, it should be dealt with JVM options rather than within the code itself. +``` +//Name[ +(starts-with(@Image, 'System.') and +(starts-with(@Image, 'System.gc') or +starts-with(@Image, 'System.runFinalization'))) or +( +starts-with(@Image,'Runtime.getRuntime') and +../../PrimarySuffix[ends-with(@Image,'gc')] +) +] +``` + **Example(s):** ``` @@ -365,12 +475,14 @@ public class GCCall { ## DontImportSun -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium Low (4) Avoid importing anything from the 'sun.*' packages. These packages are not portable and are likely to change. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.DontImportSunRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/DontImportSunRule.java) + **Example(s):** ``` @@ -380,7 +492,7 @@ public class Foo {} ## NullAssignment -**Since:** 1.02 +**Since:** PMD 1.02 **Priority:** Medium (3) @@ -389,6 +501,8 @@ of assignment is an indication that the programmer doesn't completely understand NOTE: This sort of assignment may used in some cases to dereference objects and encourage garbage collection. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.NullAssignmentRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/NullAssignmentRule.java) + **Example(s):** ``` @@ -403,13 +517,19 @@ public void bar() { ## OneDeclarationPerLine -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) Java allows the use of several variables declaration of the same type on one line. However, it can lead to quite messy code. This rule looks for several declarations on the same line. +``` +//LocalVariableDeclaration + [count(VariableDeclarator) > 1] + [$strictMode or count(distinct-values(VariableDeclarator/@BeginLine)) != count(VariableDeclarator)] +``` + **Example(s):** ``` @@ -431,12 +551,14 @@ String name, ## OnlyOneReturn -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) A method should have only one exit point, and that should be the last statement in the method. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.OnlyOneReturnRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/OnlyOneReturnRule.java) + **Example(s):** ``` @@ -452,7 +574,7 @@ public class OneReturnOnly1 { ## SuspiciousOctalEscape -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) @@ -467,6 +589,8 @@ Any octal escape sequence followed by non-octal digits can be confusing, e.g. "\038" is interpreted as the octal escape sequence "\03" followed by the literal character "8". +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.controversial.SuspiciousOctalEscapeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/controversial/SuspiciousOctalEscapeRule.java) + **Example(s):** ``` @@ -478,13 +602,23 @@ public void foo() { ## UnnecessaryConstructor -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) This rule detects when a constructor is not necessary; i.e., when there is only one constructor, its public, has an empty body, and takes no arguments. +``` +//ClassOrInterfaceBody[count(ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)=1] +/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration +[@Public='true'] +[not(FormalParameters/*)] +[not(BlockStatement)] +[not(NameList)] +[count(ExplicitConstructorInvocation/Arguments/ArgumentList/Expression)=0] +``` + **Example(s):** ``` @@ -495,12 +629,21 @@ public class Foo { ## UnnecessaryParentheses -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) Sometimes expressions are wrapped in unnecessary parentheses, making them look like function calls. +``` +//Expression + /PrimaryExpression + /PrimaryPrefix + /Expression[count(*)=1] + /PrimaryExpression + /PrimaryPrefix +``` + **Example(s):** ``` @@ -513,13 +656,18 @@ public class Foo { ## UseConcurrentHashMap -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium (3) Since Java5 brought a new implementation of the Map designed for multi-threaded access, you can perform efficient map reads without blocking other threads. +``` +//Type[../VariableDeclarator/VariableInitializer//AllocationExpression/ClassOrInterfaceType[@Image != 'ConcurrentHashMap']] +/ReferenceType/ClassOrInterfaceType[@Image = 'Map'] +``` + **Example(s):** ``` @@ -536,7 +684,7 @@ public class ConcurrentApp { ## UseObjectForClearerAPI -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium (3) @@ -547,6 +695,12 @@ API (such as doWork(Workload workload), rather than a tedious series of Strings) point to pass extra data, you'll be able to do so by simply modifying or extending Workload without any modification to your API. +``` +//MethodDeclaration[@Public]/MethodDeclarator/FormalParameters[ + count(FormalParameter/Type/ReferenceType/ClassOrInterfaceType[@Image = 'String']) > 3 +] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/coupling.md b/docs/pages/pmd/rules/java/coupling.md index 30f6880a9..0a1e5330b 100644 --- a/docs/pages/pmd/rules/java/coupling.md +++ b/docs/pages/pmd/rules/java/coupling.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/coupling.xml --- ## CouplingBetweenObjects -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) This rule counts the number of unique attributes, local variables, and return types within an object. A number higher than the specified threshold can indicate a high degree of coupling. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.coupling.CouplingBetweenObjectsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/CouplingBetweenObjectsRule.java) + **Example(s):** ``` @@ -44,7 +46,7 @@ public class Foo { ## ExcessiveImports -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) @@ -52,6 +54,8 @@ A high number of imports can indicate a high degree of coupling within an object counts the number of unique imports and reports a violation if the count is above the user-specified threshold. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.coupling.ExcessiveImportsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/ExcessiveImportsRule.java) + **Example(s):** ``` @@ -73,7 +77,7 @@ public class Foo { ## LawOfDemeter -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) @@ -84,6 +88,8 @@ K.J. Lieberherr and I.M. Holland. Assuring good style for object-oriented progra http://www.ccs.neu.edu/home/lieber/LoD.html; http://en.wikipedia.org/wiki/Law_of_Demeter +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.coupling.LawOfDemeterRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LawOfDemeterRule.java) + **Example(s):** ``` @@ -112,7 +118,7 @@ public class Foo { ## LooseCoupling -**Since:** 0.7 +**Since:** PMD 0.7 **Priority:** Medium (3) @@ -120,6 +126,8 @@ The use of implementation types as object references limits your ability to use implementations in the future as requirements change. Whenever available, referencing objects by their interface types provides much more flexibility. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.coupling.LooseCouplingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LooseCouplingRule.java) + **Example(s):** ``` @@ -140,13 +148,15 @@ public Set getFoo() { ## LoosePackageCoupling -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using classes from the configured package hierarchy outside of the package hierarchy, except when using one of the configured allowed classes. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.coupling.LoosePackageCouplingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/coupling/LoosePackageCouplingRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index b0960aa3a..b172fe2cf 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -8,7 +8,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/design.xml --- ## AbstractClassWithoutAbstractMethod -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -17,6 +17,14 @@ an incomplete implementation, which is to be completed by subclasses implementin abstract methods. If the class is intended to be used as a base class only (not to be instantiated directly) a protected constructor can be provided prevent direct instantiation. +``` +//ClassOrInterfaceDeclaration + [@Abstract='true' + and count( .//MethodDeclaration[@Abstract='true'] )=0 ] + [count(ImplementsList)=0] + [count(.//ExtendsList)=0] +``` + **Example(s):** ``` @@ -30,7 +38,7 @@ public abstract class Foo { ## AbstractClassWithoutAnyMethod -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** High (1) @@ -38,6 +46,14 @@ If an abstract class does not provides any methods, it may be acting as a simple that is not meant to be instantiated. In this case, it is probably better to use a private or protected constructor in order to prevent instantiation than make the class misleadingly abstract. +``` +//ClassOrInterfaceDeclaration[ + (@Abstract = 'true') + and + (count(//MethodDeclaration) + count(//ConstructorDeclaration) = 0) +] +``` + **Example(s):** ``` @@ -49,7 +65,7 @@ public class abstract Example { ## AccessorClassGeneration -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) @@ -59,6 +75,8 @@ situation. The generated class file is actually an interface. It gives the acce to invoke a new hidden package scope constructor that takes the interface as a supplementary parameter. This turns a private constructor effectively into one with package scope, and is challenging to discern. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.AccessorClassGenerationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorClassGenerationRule.java) + **Example(s):** ``` @@ -74,7 +92,7 @@ public class Outer { ## AccessorMethodGeneration -**Since:** 5.5.4 +**Since:** PMD 5.5.4 **Priority:** Medium (3) @@ -82,6 +100,8 @@ When accessing a private field / method from another class, the Java compiler wi with package-private visibility. This adds overhead, and to the dex method count on Android. This situation can be avoided by changing the visibility of the field / method from private to package-private. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.AccessorMethodGenerationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorMethodGenerationRule.java) + **Example(s):** ``` @@ -103,12 +123,14 @@ public class OuterClass { ## AssignmentToNonFinalStatic -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) Identifies a possible unsafe usage of a static field. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.AssignmentToNonFinalStaticRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AssignmentToNonFinalStaticRule.java) + **Example(s):** ``` @@ -122,12 +144,14 @@ public class StaticField { ## AvoidDeeplyNestedIfStmts -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.AvoidDeeplyNestedIfStmtsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidDeeplyNestedIfStmtsRule.java) + **Example(s):** ``` @@ -152,12 +176,21 @@ public class Foo { ## AvoidInstanceofChecksInCatchClause -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) Each caught exception type should be handled in its own catch clause. +``` +//CatchStatement/FormalParameter + /following-sibling::Block//InstanceOfExpression/PrimaryExpression/PrimaryPrefix + /Name[ + @Image = ./ancestor::Block/preceding-sibling::FormalParameter + /VariableDeclaratorId/@Image + ] +``` + **Example(s):** ``` @@ -177,13 +210,19 @@ try { // Prefer this: ## AvoidProtectedFieldInFinalClass -**Since:** 2.1 +**Since:** PMD 2.1 **Priority:** Medium (3) Do not use protected fields in final classes since they cannot be subclassed. Clarify your intent by using private or package access modifiers instead. +``` +//ClassOrInterfaceDeclaration[@Final='true'] +/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration +/FieldDeclaration[@Protected='true'] +``` + **Example(s):** ``` @@ -196,7 +235,7 @@ public final class Bar { ## AvoidProtectedMethodInFinalClassNotExtending -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -204,6 +243,12 @@ Do not use protected methods in most final classes since they cannot be subclass only be allowed in final classes that extend other classes with protected methods (whose visibility cannot be reduced). Clarify your intent by using private or package access modifiers instead. +``` +//ClassOrInterfaceDeclaration[@Final='true' and not(ExtendsList)] +/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration +/MethodDeclaration[@Protected='true'][MethodDeclarator/@Image != 'finalize'] +``` + **Example(s):** ``` @@ -215,12 +260,14 @@ public final class Foo { ## AvoidReassigningParameters -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium High (2) Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.AvoidReassigningParametersRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AvoidReassigningParametersRule.java) + **Example(s):** ``` @@ -233,7 +280,7 @@ public class Foo { ## AvoidSynchronizedAtMethodLevel -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -241,6 +288,10 @@ Method-level synchronization can cause problems when new code is added to the me Block-level synchronization helps to ensure that only the code that needs synchronization gets it. +``` +//MethodDeclaration[@Synchronized='true'] +``` + **Example(s):** ``` @@ -268,13 +319,19 @@ public class Foo { ## BadComparison -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** Medium (3) Avoid equality comparisons with Double.NaN. Due to the implicit lack of representation precision when comparing floating point numbers these are likely to cause logic errors. +``` +//EqualityExpression[@Image='=='] + /PrimaryExpression/PrimaryPrefix + /Name[@Image='Double.NaN' or @Image='Float.NaN'] +``` + **Example(s):** ``` @@ -283,13 +340,21 @@ boolean x = (y == Double.NaN); ## ClassWithOnlyPrivateConstructorsShouldBeFinal -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** High (1) A class with only private constructors should be final, unless the private constructor is invoked by a inner class. +``` +TypeDeclaration[count(../TypeDeclaration) = 1]/ClassOrInterfaceDeclaration +[@Final = 'false'] +[count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private = 'true']) >= 1 ] +[count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[(@Public = 'true') or (@Protected = 'true') or (@PackagePrivate = 'true')]) = 0 ] +[not(.//ClassOrInterfaceDeclaration)] +``` + **Example(s):** ``` @@ -300,12 +365,14 @@ public class Foo { //Should be final ## CloseResource -**Since:** 1.2.2 +**Since:** PMD 1.2.2 **Priority:** Medium (3) Ensure that resources (like Connection, Statement, and ResultSet objects) are always closed after use. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.CloseResourceRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CloseResourceRule.java) + **Example(s):** ``` @@ -334,12 +401,14 @@ public class Bar { ## CompareObjectsWithEquals -**Since:** 3.2 +**Since:** PMD 3.2 **Priority:** Medium (3) Use equals() to compare object references; avoid comparing them with ==. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.CompareObjectsWithEqualsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/CompareObjectsWithEqualsRule.java) + **Example(s):** ``` @@ -352,7 +421,7 @@ class Foo { ## ConfusingTernary -**Since:** 1.9 +**Since:** PMD 1.9 **Priority:** Medium (3) @@ -366,6 +435,8 @@ Most "if (x != y)" cases without an "else" are often return cases, so consistent rule makes the code easier to read. Also, this resolves trivial ordering problems, such as "does the error case go first?" or "does the common case go first?". +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.ConfusingTernaryRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ConfusingTernaryRule.java) + **Example(s):** ``` @@ -382,13 +453,17 @@ boolean bar(int x, int y) { ## ConstantsInInterface -**Since:** 5.5 +**Since:** PMD 5.5 **Priority:** Medium (3) Avoid constants in interfaces. Interfaces should define types, constants are implementation details better placed in classes or enums. See Effective Java, item 19. +``` +//ClassOrInterfaceDeclaration[@Interface='true'][$ignoreIfHasMethods='false' or not(.//MethodDeclaration)]//FieldDeclaration +``` + **Example(s):** ``` @@ -422,7 +497,7 @@ public interface YetAnotherConstantInterface { ## ConstructorCallsOverridableMethod -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** High (1) @@ -434,6 +509,8 @@ contains a call to an overridable method, the subclass may be completely uninsta this includes method calls throughout the control flow graph - i.e., if a constructor Foo() calls a private method bar() that calls a public method buz(), this denotes a problem. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.ConstructorCallsOverridableMethodRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ConstructorCallsOverridableMethodRule.java) + **Example(s):** ``` @@ -459,12 +536,18 @@ public class JuniorClass extends SeniorClass { ## DefaultLabelNotLastInSwitchStmt -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) By convention, the default label should be the last label in a switch statement. +``` +//SwitchStatement + [not(SwitchLabel[position() = last()][@Default='true'])] + [SwitchLabel[@Default='true']] +``` + **Example(s):** ``` @@ -484,13 +567,31 @@ public class Foo { ## EmptyMethodInAbstractClassShouldBeAbstract -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** High (1) Empty or auto-generated methods in an abstract class should be tagged as abstract. This helps to remove their inapproprate usage by developers who should be implementing their own versions in the concrete subclasses. +``` +//ClassOrInterfaceDeclaration[@Abstract = 'true'] + /ClassOrInterfaceBody + /ClassOrInterfaceBodyDeclaration + /MethodDeclaration[@Abstract = 'false' and @Native = 'false'] + [ + ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral) = 'true' ) + or + ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image = '0']) = 'true' ) + or + ( boolean(./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal[string-length(@Image) = 2]) = 'true' ) + or + (./Block[count(./BlockStatement) = 1]/BlockStatement/Statement/EmptyStatement) + or + ( count (./Block/*) = 0 ) + ] +``` + **Example(s):** ``` @@ -507,12 +608,28 @@ public abstract class ShouldBeAbstract { ## EqualsNull -**Since:** 1.9 +**Since:** PMD 1.9 **Priority:** High (1) Tests for null should not use the equals() method. The '==' operator should be used instead. +``` +//PrimaryExpression + [ + PrimaryPrefix[Name[ends-with(@Image, 'equals')]] + [following-sibling::node()/Arguments/ArgumentList[count(Expression)=1] + /Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] + + or + + PrimarySuffix[ends-with(@Image, 'equals')] + [following-sibling::node()/Arguments/ArgumentList[count(Expression)=1] + /Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] + + ] +``` + **Example(s):** ``` @@ -529,12 +646,14 @@ if (x == null) { // preferred ## FieldDeclarationsShouldBeAtStartOfClass -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.FieldDeclarationsShouldBeAtStartOfClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/FieldDeclarationsShouldBeAtStartOfClassRule.java) + **Example(s):** ``` @@ -562,13 +681,20 @@ public class HelloWorldBean { ## FinalFieldCouldBeStatic -**Since:** 1.1 +**Since:** PMD 1.1 **Priority:** Medium (3) If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead in each object at runtime. +``` +//FieldDeclaration + [@Final='true' and @Static='false'] + /VariableDeclarator/VariableInitializer/Expression + /PrimaryExpression[not(PrimarySuffix)]/PrimaryPrefix/Literal +``` + **Example(s):** ``` @@ -579,7 +705,7 @@ public class Foo { ## GodClass -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) @@ -591,14 +717,18 @@ Michele Lanza and Radu Marinescu. Object-Oriented Metrics in Practice: Using Software Metrics to Characterize, Evaluate, and Improve the Design of Object-Oriented Systems. Springer, Berlin, 1 edition, October 2006. Page 80. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.GodClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/GodClassRule.java) + ## IdempotentOperations -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) Avoid idempotent operations - they have no effect. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.IdempotentOperationsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/IdempotentOperationsRule.java) + **Example(s):** ``` @@ -612,13 +742,15 @@ public class Foo { ## ImmutableField -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) Identifies private fields whose values never change once they are initialized either in the declaration of the field or by a constructor. This helps in converting existing classes to becoming immutable ones. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.ImmutableFieldRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/ImmutableFieldRule.java) + **Example(s):** ``` @@ -635,12 +767,21 @@ public class Foo { ## InstantiationToGetClass -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium Low (4) Avoid instantiating an object just to call getClass() on it; use the .class public member instead. +``` +//PrimarySuffix + [@Image='getClass'] + [parent::PrimaryExpression + [PrimaryPrefix/AllocationExpression] + [count(PrimarySuffix) = 2] + ] +``` + **Example(s):** ``` @@ -653,12 +794,16 @@ Class c = String.class; ## LogicInversion -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Use opposite operator instead of negating the whole expression with a logic complement operator. +``` +//UnaryExpressionNotPlusMinus[@Image='!']/PrimaryExpression/PrimaryPrefix/Expression[EqualityExpression or RelationalExpression] +``` + **Example(s):** ``` @@ -678,13 +823,25 @@ public boolean bar(int a, int b) { ## MissingBreakInSwitch -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) Switch statements without break or return statements for each case option may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through. +``` +//SwitchStatement +[(count(.//BreakStatement) + + count(BlockStatement//Statement/ReturnStatement) + + count(BlockStatement//Statement/ContinueStatement) + + count(BlockStatement//Statement/ThrowStatement) + + count(BlockStatement//Statement/IfStatement[@Else='true' and Statement[2][ReturnStatement|ContinueStatement|ThrowStatement]]/Statement[1][ReturnStatement|ContinueStatement|ThrowStatement]) + + count(SwitchLabel[name(following-sibling::node()) = 'SwitchLabel']) + + count(SwitchLabel[count(following-sibling::node()) = 0]) + < count (SwitchLabel))] +``` + **Example(s):** ``` @@ -709,12 +866,54 @@ public void bar(int status) { ## MissingStaticMethodInNonInstantiatableClass -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) A class that has private constructors and does not have any static methods or fields cannot be used. +``` +//ClassOrInterfaceDeclaration[@Nested='false'] +[ + ( + count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)>0 + and + count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration) = count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Private='true']) + ) + and + count(.//MethodDeclaration[@Static='true'])=0 + and + count(.//FieldDeclaration[@Private='false'][@Static='true'])=0 + and + count(.//ClassOrInterfaceDeclaration[@Nested='true'] + [@Public='true'] + [@Static='true'] + [count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration[@Public='true']) > 0] + [count(./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration + [@Public='true'] + [./ResultType/Type/ReferenceType/ClassOrInterfaceType + [@Image = //ClassOrInterfaceDeclaration[@Nested='false']/@Image] + ] + ) > 0] + ) = 0 + and + count(//ClassOrInterfaceDeclaration + [@Nested='true'] + [@Static='true'] + [@Public='true'] + [.//MethodDeclaration + [@Public='true'] + [.//ReturnStatement//AllocationExpression + [ClassOrInterfaceType + [@Image = //ClassOrInterfaceDeclaration/@Image] + ] + [./Arguments//PrimaryPrefix/@ThisModifier='true'] + ] + ] + ) = 0 +] +``` + **Example(s):** ``` @@ -730,13 +929,17 @@ public class Foo { ## NonCaseLabelInSwitchStatement -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) A non-case label (e.g. a named break/continue label) was present in a switch statement. This legal, but confusing. It is easy to mix up the case labels and the non-case labels. +``` +//SwitchStatement//BlockStatement/Statement/LabeledStatement +``` + **Example(s):** ``` @@ -757,7 +960,7 @@ public class Foo { ## NonStaticInitializer -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) @@ -765,6 +968,10 @@ A non-static initializer block will be called any time a constructor is invoked invoking the constructor). While this is a valid language construct, it is rarely used and is confusing. +``` +//Initializer[@Static='false'] +``` + **Example(s):** ``` @@ -778,7 +985,7 @@ public class MyClass { ## NonThreadSafeSingleton -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) @@ -794,6 +1001,8 @@ performance penalty. [Reference](http://www.cs.umd.edu/~pugh/java/memoryModel/Do See Effective Java, item 48. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.NonThreadSafeSingletonRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/NonThreadSafeSingletonRule.java) + **Example(s):** ``` @@ -817,7 +1026,7 @@ public static Foo getFoo() { ## OptimizableToArrayCall -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** Medium (3) @@ -825,6 +1034,16 @@ Calls to a collection's toArray() method should specify target arrays sized to m collection. Initial arrays that are too small are discarded in favour of new ones that have to be created that are the proper size. +``` +//PrimaryExpression +[PrimaryPrefix/Name[ends-with(@Image, 'toArray')]] +[ +PrimarySuffix/Arguments/ArgumentList/Expression + /PrimaryExpression/PrimaryPrefix/AllocationExpression + /ArrayDimsAndInits/Expression/PrimaryExpression/PrimaryPrefix/Literal[@Image='0'] +] +``` + **Example(s):** ``` @@ -840,13 +1059,30 @@ Foo[] fooArray = foos.toArray(new Foo[foos.size()]); ## PositionLiteralsFirstInCaseInsensitiveComparisons -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Position literals first in comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. +``` +//PrimaryExpression[ + PrimaryPrefix[Name + [ + (ends-with(@Image, '.equalsIgnoreCase')) + ] + ] + [ + (../PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal) + and + ( count(../PrimarySuffix/Arguments/ArgumentList/Expression) = 1 ) + ] +] +[not(ancestor::Expression/ConditionalAndExpression//EqualityExpression[@Image='!=']//NullLiteral)] +[not(ancestor::Expression/ConditionalOrExpression//EqualityExpression[@Image='==']//NullLiteral)] +``` + **Example(s):** ``` @@ -859,13 +1095,30 @@ class Foo { ## PositionLiteralsFirstInComparisons -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) Position literals first in comparisons, if the second argument is null then NullPointerExceptions can be avoided, they will just return false. +``` +//PrimaryExpression[ + PrimaryPrefix[Name + [ + (ends-with(@Image, '.equals')) + ] + ] + [ + (../PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral='true']) + and + ( count(../PrimarySuffix/Arguments/ArgumentList/Expression) = 1 ) + ] +] +[not(ancestor::Expression/ConditionalAndExpression//EqualityExpression[@Image='!=']//NullLiteral)] +[not(ancestor::Expression/ConditionalOrExpression//EqualityExpression[@Image='==']//NullLiteral)] +``` + **Example(s):** ``` @@ -878,7 +1131,7 @@ class Foo { ## PreserveStackTrace -**Since:** 3.7 +**Since:** PMD 3.7 **Priority:** Medium (3) @@ -886,6 +1139,8 @@ Throwing a new exception from a catch block without passing the original excepti new exception will cause the original stack trace to be lost making it difficult to debug effectively. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.PreserveStackTraceRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/PreserveStackTraceRule.java) + **Example(s):** ``` @@ -914,7 +1169,7 @@ public class Foo { ## ReturnEmptyArrayRatherThanNull -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** High (1) @@ -922,6 +1177,15 @@ For any method that returns an array, it is a better to return an empty array ra null reference. This removes the need for null checking all results and avoids inadvertent NullPointerExceptions. +``` +//MethodDeclaration + [ + (./ResultType/Type[@Array='true']) + and + (./Block/BlockStatement/Statement/ReturnStatement/Expression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral) + ] +``` + **Example(s):** ``` @@ -942,13 +1206,19 @@ public class Example { ## SimpleDateFormatNeedsLocale -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) Be sure to specify a Locale when creating SimpleDateFormat instances to ensure that locale-appropriate formatting is used. +``` +//AllocationExpression + [ClassOrInterfaceType[@Image='SimpleDateFormat']] + [Arguments[@ArgumentCount=1]] +``` + **Example(s):** ``` @@ -960,12 +1230,17 @@ public class Foo { ## SimplifyBooleanExpressions -**Since:** 1.05 +**Since:** PMD 1.05 **Priority:** Medium (3) Avoid unnecessary comparisons in boolean expressions, they serve no purpose and impacts readability. +``` +//EqualityExpression/PrimaryExpression + /PrimaryPrefix/Literal/BooleanLiteral +``` + **Example(s):** ``` @@ -980,13 +1255,15 @@ public class Bar { ## SimplifyBooleanReturns -**Since:** 0.9 +**Since:** PMD 0.9 **Priority:** Medium (3) Avoid unnecessary if-then-else statements when returning a boolean. The result of the conditional test can be returned instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.SimplifyBooleanReturnsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SimplifyBooleanReturnsRule.java) + **Example(s):** ``` @@ -1007,12 +1284,39 @@ public boolean isBarEqualTo(int x) { ## SimplifyConditional -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) No need to check for null before an instanceof; the instanceof keyword returns false when given a null argument. +``` +//Expression + [ConditionalOrExpression + [EqualityExpression[@Image='=='] + //NullLiteral + and + UnaryExpressionNotPlusMinus + [@Image='!']//InstanceOfExpression[PrimaryExpression + //Name/@Image = ancestor::ConditionalOrExpression/EqualityExpression + /PrimaryExpression/PrimaryPrefix/Name/@Image] + and + (count(UnaryExpressionNotPlusMinus) + 1 = count(*)) + ] +or +ConditionalAndExpression + [EqualityExpression[@Image='!=']//NullLiteral + and +InstanceOfExpression + [PrimaryExpression[count(PrimarySuffix[@ArrayDereference='true'])=0] + //Name[not(contains(@Image,'.'))]/@Image = ancestor::ConditionalAndExpression + /EqualityExpression/PrimaryExpression/PrimaryPrefix/Name/@Image] + and +(count(InstanceOfExpression) + 1 = count(*)) + ] +] +``` + **Example(s):** ``` @@ -1027,7 +1331,7 @@ class Foo { ## SingleMethodSingleton -**Since:** 5.4 +**Since:** PMD 5.4 **Priority:** Medium High (2) @@ -1035,6 +1339,8 @@ Some classes contain overloaded getInstance. The problem with overloaded getInst is that the instance created using the overloaded method is not cached and so, for each call and new objects will be created for every invocation. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.SingleMethodSingletonRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingleMethodSingletonRule.java) + **Example(s):** ``` @@ -1056,7 +1362,7 @@ public static Singleton getInstance(Object obj){ ## SingletonClassReturningNewInstance -**Since:** 5.4 +**Since:** PMD 5.4 **Priority:** Medium High (2) @@ -1064,6 +1370,8 @@ Some classes contain overloaded getInstance. The problem with overloaded getInst is that the instance created using the overloaded method is not cached and so, for each call and new objects will be created for every invocation. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.SingletonClassReturningNewInstanceRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingletonClassReturningNewInstanceRule.java) + **Example(s):** ``` @@ -1079,7 +1387,7 @@ class Singleton { ## SingularField -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) @@ -1087,6 +1395,8 @@ Fields whose scopes are limited to just single methods do not rely on the contai object to provide them to other methods. They may be better implemented as local variables within those methods. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.SingularFieldRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SingularFieldRule.java) + **Example(s):** ``` @@ -1108,7 +1418,7 @@ public class Foo { ## SwitchDensity -**Since:** 1.02 +**Since:** PMD 1.02 **Priority:** Medium (3) @@ -1116,6 +1426,8 @@ A high ratio of statements to labels in a switch statement implies that the swit is overloaded. Consider moving the statements into new methods or creating subclasses based on the switch variable. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.SwitchDensityRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/SwitchDensityRule.java) + **Example(s):** ``` @@ -1144,12 +1456,16 @@ public class Foo { ## SwitchStmtsShouldHaveDefault -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) All switch statements should include a default option to catch any unspecified values. +``` +//SwitchStatement[not(SwitchLabel[@Default='true'])] +``` + **Example(s):** ``` @@ -1165,7 +1481,7 @@ public void bar() { ## TooFewBranchesForASwitchStatement -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium (3) @@ -1173,6 +1489,12 @@ Switch statements are indended to be used to support complex branching behaviour cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the if-then statement to increase code readability. +``` +//SwitchStatement[ + (count(.//SwitchLabel) < $minimumNumberCaseForASwitch) +] +``` + **Example(s):** ``` @@ -1198,7 +1520,7 @@ public class Foo { ## UncommentedEmptyConstructor -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) @@ -1207,6 +1529,10 @@ contain statements, but there is no comment. By explicitly commenting empty constructors it is easier to distinguish between intentional (commented) and unintentional empty constructors. +``` +//ConstructorDeclaration[@Private='false'][count(BlockStatement) = 0 and ($ignoreExplicitConstructorInvocation = 'true' or not(ExplicitConstructorInvocation)) and @containsComment = 'false'] +``` + **Example(s):** ``` @@ -1223,7 +1549,7 @@ public Foo() { ## UncommentedEmptyMethodBody -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) @@ -1232,6 +1558,10 @@ statements, but there is no comment. By explicitly commenting empty method bodie it is easier to distinguish between intentional (commented) and unintentional empty methods. +``` +//MethodDeclaration/Block[count(BlockStatement) = 0 and @containsComment = 'false'] +``` + **Example(s):** ``` @@ -1241,12 +1571,14 @@ public void doSomething() { ## UnnecessaryLocalBeforeReturn -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) Avoid the creation of unnecessary local variables +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.UnnecessaryLocalBeforeReturnRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UnnecessaryLocalBeforeReturnRule.java) + **Example(s):** ``` @@ -1266,7 +1598,7 @@ public class Foo { ## UnsynchronizedStaticDateFormatter -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) @@ -1274,6 +1606,8 @@ SimpleDateFormat instances are not synchronized. Sun recommends using separate f for each thread. If multiple threads must access a static formatter, the formatter must be synchronized either on method or block level. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.UnsynchronizedStaticDateFormatterRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UnsynchronizedStaticDateFormatterRule.java) + **Example(s):** ``` @@ -1290,13 +1624,15 @@ public class Foo { ## UseCollectionIsEmpty -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium (3) The isEmpty() method on java.util.Collection is provided to determine if a collection has any elements. Comparing the value of size() to 0 does not convey intent as well as the isEmpty() method. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.UseCollectionIsEmptyRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseCollectionIsEmptyRule.java) + **Example(s):** ``` @@ -1319,13 +1655,29 @@ public class Foo { ## UseLocaleWithCaseConversions -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that have unusual conventions, i.e. Turkish. +``` +//PrimaryExpression +[ +PrimaryPrefix +[Name[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')]] +[following-sibling::PrimarySuffix[position() = 1]/Arguments[@ArgumentCount=0]] + +or + +PrimarySuffix +[ends-with(@Image, 'toLowerCase') or ends-with(@Image, 'toUpperCase')] +[following-sibling::PrimarySuffix[position() = 1]/Arguments[@ArgumentCount=0]] +] +[not(PrimaryPrefix/Name[ends-with(@Image, 'toHexString')])] +``` + **Example(s):** ``` @@ -1346,13 +1698,24 @@ class Foo { ## UseNotifyAllInsteadOfNotify -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead. +``` +//StatementExpression/PrimaryExpression +[PrimarySuffix/Arguments[@ArgumentCount = '0']] +[ +PrimaryPrefix[./Name[@Image='notify' or ends-with(@Image,'.notify')] +or ../PrimarySuffix/@Image='notify' +or (./AllocationExpression and ../PrimarySuffix[@Image='notify']) +] +] +``` + **Example(s):** ``` @@ -1366,7 +1729,7 @@ void bar() { ## UseUtilityClass -**Since:** 0.3 +**Since:** PMD 0.3 **Priority:** Medium (3) @@ -1376,6 +1739,8 @@ well include non-static methods. Also, if you want this class to be a utility c remember to add a private constructor to prevent instantiation. (Note, that this use was known before PMD 5.1.0 as UseSingleton). +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.design.UseUtilityClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/UseUtilityClassRule.java) + **Example(s):** ``` @@ -1387,7 +1752,7 @@ public class MaybeAUtility { ## UseVarargs -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) @@ -1395,6 +1760,25 @@ Java 5 introduced the varargs parameter declaration for methods and constructors sugar provides flexibility for users of these methods and constructors, allowing them to avoid having to deal with the creation of an array. +``` +//FormalParameters/FormalParameter + [position()=last()] + [@Array='true'] + [@Varargs='false'] + [not (./Type/ReferenceType[@Array='true'][PrimitiveType[@Image='byte']])] + [not (./Type/ReferenceType[ClassOrInterfaceType[@Image='Byte']])] + [not (./Type/PrimitiveType[@Image='byte'])] + [not (ancestor::MethodDeclaration/preceding-sibling::Annotation/*/Name[@Image='Override'])] + [not( + ancestor::MethodDeclaration + [@Public='true' and @Static='true'] + [child::ResultType[@Void='true']] and + ancestor::MethodDeclarator[@Image='main'] and + ..[@ParameterCount='1'] and + ./Type/ReferenceType[ClassOrInterfaceType[@Image='String']] + )] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/empty.md b/docs/pages/pmd/rules/java/empty.md index e02a136a6..28767e824 100644 --- a/docs/pages/pmd/rules/java/empty.md +++ b/docs/pages/pmd/rules/java/empty.md @@ -8,7 +8,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/empty.xml --- ## EmptyCatchBlock -**Since:** 0.1 +**Since:** PMD 0.1 **Priority:** Medium (3) @@ -16,6 +16,15 @@ Empty Catch Block finds instances where an exception is caught, but nothing is d In most circumstances, this swallows an exception which should either be acted on or reported. +``` +//CatchStatement + [count(Block/BlockStatement) = 0 and ($allowCommentedBlocks != 'true' or Block/@containsComment = 'false')] + [FormalParameter/Type/ReferenceType + /ClassOrInterfaceType[@Image != 'InterruptedException' and @Image != 'CloneNotSupportedException'] + ] + [FormalParameter/VariableDeclaratorId[not(matches(@Image, $allowExceptionNameRegex))]] +``` + **Example(s):** ``` @@ -37,12 +46,16 @@ public void doSomething() { ## EmptyFinallyBlock -**Since:** 0.4 +**Since:** PMD 0.4 **Priority:** Medium (3) Empty finally blocks serve no purpose and should be removed. +``` +//FinallyStatement[count(Block/BlockStatement) = 0] +``` + **Example(s):** ``` @@ -59,12 +72,17 @@ public class Foo { ## EmptyIfStmt -**Since:** 0.1 +**Since:** PMD 0.1 **Priority:** Medium (3) Empty If Statement finds instances where a condition is checked but nothing is done about it. +``` +//IfStatement/Statement + [EmptyStatement or Block[count(*) = 0]] +``` + **Example(s):** ``` @@ -79,12 +97,16 @@ public class Foo { ## EmptyInitializer -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Empty initializers serve no purpose and should be removed. +``` +//Initializer/Block[count(*)=0] +``` + **Example(s):** ``` @@ -99,12 +121,16 @@ public class Foo { ## EmptyStatementBlock -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Empty block statements serve no purpose and should be removed. +``` +//BlockStatement/Statement/Block[count(*) = 0] +``` + **Example(s):** ``` @@ -122,7 +148,7 @@ public class Foo { ## EmptyStatementNotInLoop -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) @@ -130,6 +156,19 @@ An empty statement (or a semicolon by itself) that is not used as the sole body or 'while' loop is probably a bug. It could also be a double semicolon, which has no purpose and should be removed. +``` +//EmptyStatement + [not( + ../../../ForStatement + or ../../../WhileStatement + or ../../../BlockStatement/ClassOrInterfaceDeclaration + or ../../../../../../ForStatement/Statement[1] + /Block[1]/BlockStatement[1]/Statement/EmptyStatement + or ../../../../../../WhileStatement/Statement[1] + /Block[1]/BlockStatement[1]/Statement/EmptyStatement) + ] +``` + **Example(s):** ``` @@ -143,12 +182,16 @@ public void doit() { ## EmptyStaticInitializer -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) An empty static initializer serve no purpose and should be removed. +``` +//Initializer[@Static='true']/Block[count(*)=0] +``` + **Example(s):** ``` @@ -161,12 +204,16 @@ public class Foo { ## EmptySwitchStatements -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Empty switch statements serve no purpose and should be removed. +``` +//SwitchStatement[count(*) = 1] +``` + **Example(s):** ``` @@ -181,12 +228,16 @@ public void bar() { ## EmptySynchronizedBlock -**Since:** 1.3 +**Since:** PMD 1.3 **Priority:** Medium (3) Empty synchronized blocks serve no purpose and should be removed. +``` +//SynchronizedStatement/Block[1][count(*) = 0] +``` + **Example(s):** ``` @@ -201,12 +252,16 @@ public class Foo { ## EmptyTryBlock -**Since:** 0.4 +**Since:** PMD 0.4 **Priority:** Medium (3) Avoid empty try blocks - what's the point? +``` +//TryStatement[not(ResourceSpecification)]/Block[1][count(*) = 0] +``` + **Example(s):** ``` @@ -222,7 +277,7 @@ public class Foo { ## EmptyWhileStmt -**Since:** 0.2 +**Since:** PMD 0.2 **Priority:** Medium (3) @@ -230,6 +285,10 @@ Empty While Statement finds all instances where a while statement does nothing. If it is a timing loop, then you should use Thread.sleep() for it; if it is a while loop that does a lot in the exit expression, rewrite it to make it clearer. +``` +//WhileStatement/Statement[./Block[count(*) = 0] or ./EmptyStatement] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/finalizers.md b/docs/pages/pmd/rules/java/finalizers.md index 9b3101b03..2bcac84b5 100644 --- a/docs/pages/pmd/rules/java/finalizers.md +++ b/docs/pages/pmd/rules/java/finalizers.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/finalizers.xml --- ## AvoidCallingFinalize -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) The method Object.finalize() is called by the garbage collector on an object when garbage collection determines that there are no more references to the object. It should not be invoked by application logic. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.finalizers.AvoidCallingFinalizeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/finalizers/AvoidCallingFinalizeRule.java) + **Example(s):** ``` @@ -26,12 +28,17 @@ void foo() { ## EmptyFinalizer -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) Empty finalize methods serve no purpose and should be removed. +``` +//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]] + /Block[count(*)=0] +``` + **Example(s):** ``` @@ -42,12 +49,29 @@ public class Foo { ## FinalizeDoesNotCallSuperFinalize -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) If the finalize() is implemented, its last action should be to call super.finalize. +``` +//MethodDeclaration[MethodDeclarator[@Image='finalize'][not(FormalParameters/*)]] + /Block + /BlockStatement[last()] + [not(Statement/StatementExpression/PrimaryExpression + [./PrimaryPrefix[@SuperModifier='true']] + [./PrimarySuffix[@Image='finalize']] + ) + ] + [not(Statement/TryStatement/FinallyStatement + /Block/BlockStatement/Statement/StatementExpression/PrimaryExpression + [./PrimaryPrefix[@SuperModifier='true']] + [./PrimarySuffix[@Image='finalize']] + ) + ] +``` + **Example(s):** ``` @@ -59,12 +83,22 @@ protected void finalize() { ## FinalizeOnlyCallsSuperFinalize -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) If the finalize() is implemented, it should do something besides just calling super.finalize(). +``` +//MethodDeclaration[MethodDeclarator[@Image="finalize"][not(FormalParameters/*)]] + /Block[count(BlockStatement)=1] + /BlockStatement[ + Statement/StatementExpression/PrimaryExpression + [./PrimaryPrefix[@SuperModifier='true']] + [./PrimarySuffix[@Image='finalize']] + ] +``` + **Example(s):** ``` @@ -75,13 +109,18 @@ protected void finalize() { ## FinalizeOverloaded -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) Methods named finalize() should not have parameters. It is confusing and most likely an attempt to overload Object.finalize(). It will not be called by the VM. +``` +//MethodDeclaration + /MethodDeclarator[@Image='finalize'][FormalParameters[count(*)>0]] +``` + **Example(s):** ``` @@ -94,13 +133,19 @@ public class Foo { ## FinalizeShouldBeProtected -**Since:** 1.1 +**Since:** PMD 1.1 **Priority:** Medium (3) When overriding the finalize(), the new method should be set as protected. If made public, other classes may invoke it at inappropriate times. +``` +//MethodDeclaration[@Protected="false"] + /MethodDeclarator[@Image="finalize"] + [not(FormalParameters/*)] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/imports.md b/docs/pages/pmd/rules/java/imports.md index 2938c323c..5949d3ac8 100644 --- a/docs/pages/pmd/rules/java/imports.md +++ b/docs/pages/pmd/rules/java/imports.md @@ -8,12 +8,14 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/imports.xml --- ## DontImportJavaLang -**Since:** 0.5 +**Since:** PMD 0.5 **Priority:** Medium Low (4) Avoid importing anything from the package 'java.lang'. These classes are automatically imported (JLS 7.5.3). +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.imports.DontImportJavaLangRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/DontImportJavaLangRule.java) + **Example(s):** ``` @@ -30,12 +32,14 @@ public class Foo {} ## DuplicateImports -**Since:** 0.5 +**Since:** PMD 0.5 **Priority:** Medium Low (4) Duplicate or overlapping import statements should be avoided. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.imports.DuplicateImportsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/DuplicateImportsRule.java) + **Example(s):** ``` @@ -46,12 +50,14 @@ public class Foo {} ## ImportFromSamePackage -**Since:** 1.02 +**Since:** PMD 1.02 **Priority:** Medium (3) There is no need to import a type that lives in the same package. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.imports.ImportFromSamePackageRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/ImportFromSamePackageRule.java) + **Example(s):** ``` @@ -65,7 +71,7 @@ package foo; ## TooManyStaticImports -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) @@ -74,6 +80,10 @@ unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from (Sun 1.5 Language Guide). +``` +.[count(ImportDeclaration[@Static = 'true']) > $maximumStaticImports] +``` + **Example(s):** ``` @@ -92,13 +102,15 @@ import static Yoko; // Too much ! ## UnnecessaryFullyQualifiedName -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) Import statements allow the use of non-fully qualified names. The use of a fully qualified name which is covered by an import statement is redundant. Consider using the non-fully qualified name. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.imports.UnnecessaryFullyQualifiedNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnnecessaryFullyQualifiedNameRule.java) + **Example(s):** ``` @@ -112,12 +124,14 @@ public class Foo { ## UnusedImports -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium Low (4) Avoid the use of unused import statements to prevent unwanted dependencies. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.imports.UnusedImportsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/imports/UnusedImportsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/j2ee.md b/docs/pages/pmd/rules/java/j2ee.md index 013793cd9..c626ab806 100644 --- a/docs/pages/pmd/rules/java/j2ee.md +++ b/docs/pages/pmd/rules/java/j2ee.md @@ -8,13 +8,21 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/j2ee.xml --- ## DoNotCallSystemExit -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) Web applications should not call System.exit(), since only the web container or the application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). +``` +//Name[ + starts-with(@Image,'System.exit') + or + (starts-with(@Image,'Runtime.getRuntime') and ../../PrimarySuffix[ends-with(@Image,'exit')]) +] +``` + **Example(s):** ``` @@ -28,12 +36,16 @@ public void foo() { ## DoNotUseThreads -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) The J2EE specification explicitly forbids the use of threads. +``` +//ClassOrInterfaceType[@Image = 'Thread' or @Image = 'Runnable'] +``` + **Example(s):** ``` @@ -52,12 +64,26 @@ public class OtherThread implements Runnable { ## LocalHomeNamingConvention -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) The Local Home interface of a Session EJB should be suffixed by 'LocalHome'. +``` +//ClassOrInterfaceDeclaration +[ + ( + (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalHome')]) + ) + and + not + ( + ends-with(@Image,'LocalHome') + ) +] +``` + **Example(s):** ``` @@ -68,12 +94,26 @@ public interface MyBeautifulLocalHome extends javax.ejb.EJBLocalHome {}// proper ## LocalInterfaceSessionNamingConvention -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) The Local Interface of a Session EJB should be suffixed by 'Local'. +``` +//ClassOrInterfaceDeclaration +[ + ( + (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalObject')]) + ) + and + not + ( + ends-with(@Image,'Local') + ) +] +``` + **Example(s):** ``` @@ -84,12 +124,28 @@ public interface MyLocal extends javax.ejb.EJBLocalObject {} // proper name ## MDBAndSessionBeanNamingConvention -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) The EJB Specification states that any MessageDrivenBean or SessionBean should be suffixed by 'Bean'. +``` +//TypeDeclaration/ClassOrInterfaceDeclaration +[ + ( + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'SessionBean')]) + or + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'MessageDrivenBean')]) + ) + and + not + ( + ends-with(@Image,'Bean') + ) +] +``` + **Example(s):** ``` @@ -100,12 +156,29 @@ public class MissingTheProperSuffix implements SessionBean {} // non-standard ## RemoteInterfaceNamingConvention -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) Remote Interface of a Session EJB should not have a suffix. +``` +//ClassOrInterfaceDeclaration +[ + ( + (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBObject')]) + ) + and + ( + ends-with(@Image,'Session') + or + ends-with(@Image,'EJB') + or + ends-with(@Image,'Bean') + ) +] +``` + **Example(s):** ``` @@ -121,12 +194,26 @@ Remote Interface of a Session EJB should not have a suffix. ## RemoteSessionInterfaceNamingConvention -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) A Remote Home interface type of a Session EJB should be suffixed by 'Home'. +``` +//ClassOrInterfaceDeclaration +[ + ( + (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBHome')]) + ) + and + not + ( + ends-with(@Image,'Home') + ) +] +``` + **Example(s):** ``` @@ -137,7 +224,7 @@ public interface MissingProperSuffix extends javax.ejb.EJBHome {} // non-standar ## StaticEJBFieldShouldBeFinal -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) @@ -145,6 +232,28 @@ According to the J2EE specification, an EJB should not have any static fields with write access. However, static read-only fields are allowed. This ensures proper behavior especially when instances are distributed by the container on several JREs. +``` +//ClassOrInterfaceDeclaration[ + ( + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'SessionBean')]) + or + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBHome')]) + or + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalObject')]) + or + (./ImplementsList/ClassOrInterfaceType[ends-with(@Image,'EJBLocalHome')]) + or + (./ExtendsList/ClassOrInterfaceType[ends-with(@Image,'EJBObject')]) + ) + and + (./ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration[ + (./FieldDeclaration[@Static = 'true']) + and + (./FieldDeclaration[@Final = 'false']) + ]) +] +``` + **Example(s):** ``` @@ -158,13 +267,17 @@ public class SomeEJB extends EJBObject implements EJBLocalHome { ## UseProperClassLoader -**Since:** 3.7 +**Since:** PMD 3.7 **Priority:** Medium (3) In J2EE, the getClassLoader() method might not work as expected. Use Thread.currentThread().getContextClassLoader() instead. +``` +//PrimarySuffix[@Image='getClassLoader'] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/javabeans.md b/docs/pages/pmd/rules/java/javabeans.md index 7c00cee20..b00eeb182 100644 --- a/docs/pages/pmd/rules/java/javabeans.md +++ b/docs/pages/pmd/rules/java/javabeans.md @@ -8,7 +8,7 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/javabeans.xml --- ## BeanMembersShouldSerialize -**Since:** 1.1 +**Since:** PMD 1.1 **Priority:** Medium (3) @@ -17,6 +17,8 @@ Member variables need to be marked as transient, static, or have accessor method variables as transient is the safest and easiest modification. Accessor methods should follow the Java naming conventions, i.e. for a variable named foo, getFoo() and setFoo() accessor methods should be provided. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.javabeans.BeanMembersShouldSerializeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/javabeans/BeanMembersShouldSerializeRule.java) + **Example(s):** ``` @@ -42,12 +44,26 @@ private int getMoreFoo(){ ## MissingSerialVersionUID -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) Serializable classes should provide a serialVersionUID field. +``` +//ClassOrInterfaceDeclaration + [ + count(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration + /FieldDeclaration/VariableDeclarator/VariableDeclaratorId[@Image='serialVersionUID']) = 0 +and + count(ImplementsList + [ClassOrInterfaceType/@Image='Serializable' + or ClassOrInterfaceType/@Image='java.io.Serializable']) =1 +and + @Abstract = 'false' +] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/junit.md b/docs/pages/pmd/rules/java/junit.md index 5823e297d..79989296a 100644 --- a/docs/pages/pmd/rules/java/junit.md +++ b/docs/pages/pmd/rules/java/junit.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/junit.xml --- ## JUnitAssertionsShouldIncludeMessage -**Since:** 1.04 +**Since:** PMD 1.04 **Priority:** Medium (3) JUnit assertions should include an informative message - i.e., use the three-argument version of assertEquals(), not the two-argument version. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.junit.JUnitAssertionsShouldIncludeMessageRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/junit/JUnitAssertionsShouldIncludeMessageRule.java) + **Example(s):** ``` @@ -30,12 +32,21 @@ public class Foo extends TestCase { ## JUnitSpelling -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Some JUnit framework methods are easy to misspell. +``` +//MethodDeclarator[(not(@Image = 'setUp') + and translate(@Image, 'SETuP', 'setUp') = 'setUp') + or (not(@Image = 'tearDown') + and translate(@Image, 'TEARdOWN', 'tearDown') = 'tearDown')] + [FormalParameters[count(*) = 0]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -49,12 +60,19 @@ public class Foo extends TestCase { ## JUnitStaticSuite -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) The suite() method in a JUnit test needs to be both public and static. +``` +//MethodDeclaration[not(@Static='true') or not(@Public='true')] +[MethodDeclarator/@Image='suite'] +[MethodDeclarator/FormalParameters/@ParameterCount=0] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -68,7 +86,7 @@ public class Foo extends TestCase { ## JUnitTestContainsTooManyAsserts -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) @@ -76,6 +94,10 @@ JUnit tests should not contain too many asserts. Many asserts are indicative of it is harder to verify correctness. Consider breaking the test scenario into multiple, shorter test scenarios. Customize the maximum number of assertions used by this Rule to suit your needs. +``` +//MethodDeclarator[(@Image[fn:matches(.,'^test')] or ../../Annotation/MarkerAnnotation/Name[@Image='Test']) and count(..//PrimaryPrefix/Name[@Image[fn:matches(.,'^assert')]]) > $maximumAsserts] +``` + **Example(s):** ``` @@ -103,13 +125,15 @@ public class MyTestCase extends TestCase { ## JUnitTestsShouldIncludeAssert -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) JUnit tests should include at least one assertion. This makes the tests more robust, and using assert with messages provide the developer a clearer idea of what the test does. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.junit.JUnitTestsShouldIncludeAssertRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/junit/JUnitTestsShouldIncludeAssertRule.java) + **Example(s):** ``` @@ -125,7 +149,7 @@ public class Foo extends TestCase { ## SimplifyBooleanAssertion -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) @@ -139,6 +163,18 @@ as: assertFalse(expr); +``` +//StatementExpression +[ +.//Name[@Image='assertTrue' or @Image='assertFalse'] +and +PrimaryExpression/PrimarySuffix/Arguments/ArgumentList + /Expression/UnaryExpressionNotPlusMinus[@Image='!'] +/PrimaryExpression/PrimaryPrefix +] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -152,13 +188,15 @@ public class SimpleTest extends TestCase { ## TestClassWithoutTestCases -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, since most people will assume it is a test case. Test classes have test methods named testXXX. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.junit.TestClassWithoutTestCasesRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/junit/TestClassWithoutTestCasesRule.java) + **Example(s):** ``` @@ -174,7 +212,7 @@ public class CarTest { ## UnnecessaryBooleanAssertion -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -183,6 +221,20 @@ Consider using flow control (in case of assertTrue(false) or similar) or simply statements like assertTrue(true) and assertFalse(false). If you just want a test to halt after finding an error, use the fail() method and provide an indication message of why it did. +``` +//StatementExpression +[ +PrimaryExpression/PrimaryPrefix/Name[@Image='assertTrue' or @Image='assertFalse'] +and +PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression +[PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral +or +UnaryExpressionNotPlusMinus[@Image='!'] +/PrimaryExpression/PrimaryPrefix[Literal/BooleanLiteral or Name[count(../../*)=1]]] +] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -195,12 +247,22 @@ public class SimpleTest extends TestCase { ## UseAssertEqualsInsteadOfAssertTrue -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals. +``` +//PrimaryExpression[ + PrimaryPrefix/Name[@Image = 'assertTrue'] +][ + PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name + [ends-with(@Image, '.equals')] +] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -215,13 +277,24 @@ public class FooTest extends TestCase { ## UseAssertNullInsteadOfAssertTrue -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertNull, assertNotNull. +``` +//PrimaryExpression[ + PrimaryPrefix/Name[@Image = 'assertTrue' or @Image = 'assertFalse'] +][ + PrimarySuffix/Arguments/ArgumentList[ + Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Literal/NullLiteral + ] +] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -238,13 +311,24 @@ public class FooTest extends TestCase { ## UseAssertSameInsteadOfAssertTrue -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertSame, assertNotSame. +``` +//PrimaryExpression[ + PrimaryPrefix/Name + [@Image = 'assertTrue' or @Image = 'assertFalse'] +] +[PrimarySuffix/Arguments + /ArgumentList/Expression + /EqualityExpression[count(.//NullLiteral) = 0]] +[ancestor::ClassOrInterfaceDeclaration[//ClassOrInterfaceType[pmd-java:typeof(@Image, 'junit.framework.TestCase','TestCase')] or //MarkerAnnotation/Name[pmd-java:typeof(@Image, 'org.junit.Test', 'Test')]]] +``` + **Example(s):** ``` @@ -259,12 +343,22 @@ public class FooTest extends TestCase { ## UseAssertTrueInsteadOfAssertEquals -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) When asserting a value is the same as a literal or Boxed boolean, use assertTrue/assertFalse, instead of assertEquals. +``` +//PrimaryExpression[PrimaryPrefix/Name[@Image = 'assertEquals']] +[ + PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Literal/BooleanLiteral + or + PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix + /Name[(@Image = 'Boolean.TRUE' or @Image = 'Boolean.FALSE')] +] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/logging-jakarta-commons.md b/docs/pages/pmd/rules/java/logging-jakarta-commons.md index 886641e22..2575ed403 100644 --- a/docs/pages/pmd/rules/java/logging-jakarta-commons.md +++ b/docs/pages/pmd/rules/java/logging-jakarta-commons.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-jakarta-commons --- ## GuardDebugLogging -**Since:** 4.3 +**Since:** PMD 4.3 **Priority:** Medium (3) When log messages are composed by concatenating strings, the whole section should be guarded by a isDebugEnabled() check to avoid performance and memory issues. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.logging.GuardDebugLoggingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardDebugLoggingRule.java) + **Example(s):** ``` @@ -50,13 +52,15 @@ public class Test { ## GuardLogStatement -**Since:** 5.1.0 +**Since:** PMD 5.1.0 **Priority:** Medium High (2) Whenever using a log level, one should check if the loglevel is actually enabled, or otherwise skip the associate String creation and manipulation. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.logging.GuardLogStatementRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementRule.java) + **Example(s):** ``` @@ -74,7 +78,7 @@ otherwise skip the associate String creation and manipulation. ## ProperLogger -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) @@ -82,6 +86,18 @@ A logger should normally be defined private static final and be associated with Private final Log log; is also allowed for rare cases where loggers need to be passed around, with the restriction that the logger needs to be passed into the constructor. +``` +//ClassOrInterfaceBodyDeclaration[FieldDeclaration//ClassOrInterfaceType[@Image='Log'] + and + not(FieldDeclaration[@Final='true'][@Static='true'][@Private='true'][.//VariableDeclaratorId[@Image=$staticLoggerName]] + //ArgumentList//ClassOrInterfaceType/@Image = ancestor::ClassOrInterfaceDeclaration/@Image) + and + not(FieldDeclaration[@Final='true'][@Private='true'][.//VariableDeclaratorId[@Image='log']] + [count(.//VariableInitializer)=0] + [ancestor::ClassOrInterfaceBody//StatementExpression[.//PrimaryExpression/descendant::*[@Image='log']][count(.//AllocationExpression)=0]] + )] +``` + **Example(s):** ``` @@ -101,12 +117,22 @@ public class Foo { ## UseCorrectExceptionLogging -**Since:** 3.2 +**Since:** PMD 3.2 **Priority:** Medium (3) To make sure the full stacktrace is printed out, use the logging statement with two arguments: a String and a Throwable. +``` +//CatchStatement/Block/BlockStatement/Statement/StatementExpression +/PrimaryExpression[PrimaryPrefix/Name[starts-with(@Image, +concat(ancestor::ClassOrInterfaceDeclaration/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration +[Type//ClassOrInterfaceType[@Image='Log']] +/VariableDeclarator/VariableDeclaratorId/@Image, '.'))]] +[PrimarySuffix/Arguments[@ArgumentCount='1']] +[PrimarySuffix/Arguments//Name/@Image = ancestor::CatchStatement/FormalParameter/VariableDeclaratorId/@Image] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/logging-java.md b/docs/pages/pmd/rules/java/logging-java.md index 34a4a85eb..751fbd507 100644 --- a/docs/pages/pmd/rules/java/logging-java.md +++ b/docs/pages/pmd/rules/java/logging-java.md @@ -8,12 +8,18 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/logging-java.xml --- ## AvoidPrintStackTrace -**Since:** 3.2 +**Since:** PMD 3.2 **Priority:** Medium (3) Avoid printStackTrace(); use a logger call instead. +``` +//PrimaryExpression + [PrimaryPrefix/Name[contains(@Image,'printStackTrace')]] + [PrimarySuffix[not(boolean(Arguments/ArgumentList/Expression))]] +``` + **Example(s):** ``` @@ -30,13 +36,15 @@ class Foo { ## GuardLogStatementJavaUtil -**Since:** 5.1.0 +**Since:** PMD 5.1.0 **Priority:** Medium High (2) Whenever using a log level, one should check if the loglevel is actually enabled, or otherwise skip the associate String creation and manipulation. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.logging.GuardLogStatementJavaUtilRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/GuardLogStatementJavaUtilRule.java) + **Example(s):** ``` @@ -54,12 +62,14 @@ otherwise skip the associate String creation and manipulation. ## InvalidSlf4jMessageFormat -**Since:** 5.5.0 +**Since:** PMD 5.5.0 **Priority:** Low (5) Check for messages in slf4j loggers with non matching number of arguments and placeholders. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.logging.InvalidSlf4jMessageFormatRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/InvalidSlf4jMessageFormatRule.java) + **Example(s):** ``` @@ -70,12 +80,21 @@ LOGGER.error("param {}", "arg1", new IllegalStateException("arg")); //The except ## LoggerIsNotStaticFinal -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium High (2) In most cases, the Logger reference can be declared as static and final. +``` +//VariableDeclarator + [parent::FieldDeclaration] + [../Type/ReferenceType + /ClassOrInterfaceType[@Image='Logger'] + and + (..[@Final='false'] or ..[@Static = 'false'] ) ] +``` + **Example(s):** ``` @@ -88,12 +107,14 @@ public class Foo{ ## MoreThanOneLogger -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium High (2) Normally only one logger is used in each class. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.logging.MoreThanOneLoggerRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/logging/MoreThanOneLoggerRule.java) + **Example(s):** ``` @@ -107,7 +128,7 @@ public class Foo { ## SystemPrintln -**Since:** 2.1 +**Since:** PMD 2.1 **Priority:** Medium High (2) @@ -115,6 +136,14 @@ References to System.(out|err).print are usually intended for debugging purposes the codebase even in production code. By using a logger one can enable/disable this behaviour at will (and by priority) and avoid clogging the Standard out log. +``` +//Name[ + starts-with(@Image, 'System.out.print') + or + starts-with(@Image, 'System.err.print') + ] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/migrating.md b/docs/pages/pmd/rules/java/migrating.md index ab95e3aa1..b2b884c6c 100644 --- a/docs/pages/pmd/rules/java/migrating.md +++ b/docs/pages/pmd/rules/java/migrating.md @@ -8,12 +8,16 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/migrating.xml --- ## AvoidAssertAsIdentifier -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium High (2) Use of the term 'assert' will conflict with newer versions of Java since it is a reserved word. +``` +//VariableDeclaratorId[@Image='assert'] +``` + **Example(s):** ``` @@ -26,12 +30,16 @@ public class A { ## AvoidEnumAsIdentifier -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium High (2) Use of the term 'enum' will conflict with newer versions of Java since it is a reserved word. +``` +//VariableDeclaratorId[@Image='enum'] +``` + **Example(s):** ``` @@ -44,13 +52,20 @@ public class A { ## ByteInstantiation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium High (2) Calling new Byte() causes memory allocation that can be avoided by the static Byte.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. +``` +//PrimaryPrefix/AllocationExpression +[not (ArrayDimsAndInits) +and (ClassOrInterfaceType/@Image='Byte' +or ClassOrInterfaceType/@Image='java.lang.Byte')] +``` + **Example(s):** ``` @@ -61,13 +76,21 @@ public class Foo { ## IntegerInstantiation -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium High (2) Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. +``` +//PrimaryPrefix + /AllocationExpression + [not (ArrayDimsAndInits) + and (ClassOrInterfaceType/@Image='Integer' + or ClassOrInterfaceType/@Image='java.lang.Integer')] +``` + **Example(s):** ``` @@ -78,13 +101,19 @@ public class Foo { ## JUnit4SuitesShouldUseSuiteAnnotation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) In JUnit 3, test suites are indicated by the suite() method. In JUnit 4, suites are indicated through the @RunWith(Suite.class) annotation. +``` +//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='suite']] +[MethodDeclaration/ResultType/Type/ReferenceType/ClassOrInterfaceType[@Image='Test' or @Image = 'junit.framework.Test']] +[not(MethodDeclaration/Block//ClassOrInterfaceType[@Image='JUnit4TestAdapter'])] +``` + **Example(s):** ``` @@ -103,13 +132,19 @@ public class GoodTest { ## JUnit4TestShouldUseAfterAnnotation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) In JUnit 3, the tearDown method was used to clean up all data entities required in running tests. JUnit 4 skips the tearDown method and executes all methods annotated with @After after running each test +``` +//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])] +//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='tearDown']] +[count(Annotation//Name[@Image='After'])=0] +``` + **Example(s):** ``` @@ -127,13 +162,19 @@ public class MyTest2 { ## JUnit4TestShouldUseBeforeAnnotation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) In JUnit 3, the setUp method was used to set up all data entities required in running tests. JUnit 4 skips the setUp method and executes all methods annotated with @Before before all tests +``` +//CompilationUnit[not(ImportDeclaration/Name[starts-with(@Image, "org.testng")])] +//ClassOrInterfaceBodyDeclaration[MethodDeclaration/MethodDeclarator[@Image='setUp']] +[count(Annotation//Name[@Image='Before'])=0] +``` + **Example(s):** ``` @@ -151,13 +192,18 @@ public class MyTest2 { ## JUnit4TestShouldUseTestAnnotation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) In JUnit 3, the framework executed all methods which started with the word test as a unit test. In JUnit 4, only methods annotated with the @Test annotation are executed. +``` +//ClassOrInterfaceBodyDeclaration[MethodDeclaration[@Public='true']/MethodDeclarator[starts-with(@Image,'test')]] +[count(Annotation//Name[@Image='Test'])=0] +``` + **Example(s):** ``` @@ -175,12 +221,14 @@ public class MyTest { ## JUnitUseExpected -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) In JUnit4, use the @Test(expected) annotation to denote tests that should throw exceptions. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.migrating.JUnitUseExpectedRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/migrating/JUnitUseExpectedRule.java) + **Example(s):** ``` @@ -203,13 +251,21 @@ public class MyTest { ## LongInstantiation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium High (2) Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. +``` +//PrimaryPrefix +/AllocationExpression +[not (ArrayDimsAndInits) +and (ClassOrInterfaceType/@Image='Long' +or ClassOrInterfaceType/@Image='java.lang.Long')] +``` + **Example(s):** ``` @@ -220,12 +276,16 @@ public class Foo { ## ReplaceEnumerationWithIterator -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Consider replacing Enumeration usages with the newer java.util.Iterator +``` +//ImplementsList/ClassOrInterfaceType[@Image='Enumeration'] +``` + **Example(s):** ``` @@ -242,12 +302,16 @@ public class Foo implements Enumeration { ## ReplaceHashtableWithMap -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Consider replacing Hashtable usage with the newer java.util.Map if thread safety is not required. +``` +//Type/ReferenceType/ClassOrInterfaceType[@Image='Hashtable'] +``` + **Example(s):** ``` @@ -260,12 +324,16 @@ public class Foo { ## ReplaceVectorWithList -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Consider replacing Vector usages with the newer java.util.ArrayList if expensive thread-safe operations are not required. +``` +//Type/ReferenceType/ClassOrInterfaceType[@Image='Vector'] +``` + **Example(s):** ``` @@ -278,13 +346,21 @@ public class Foo { ## ShortInstantiation -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium High (2) Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. +``` +//PrimaryPrefix +/AllocationExpression +[not (ArrayDimsAndInits) +and (ClassOrInterfaceType/@Image='Short' +or ClassOrInterfaceType/@Image='java.lang.Short')] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/naming.md b/docs/pages/pmd/rules/java/naming.md index f4f942ebf..7de5e4d40 100644 --- a/docs/pages/pmd/rules/java/naming.md +++ b/docs/pages/pmd/rules/java/naming.md @@ -8,12 +8,23 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/naming.xml --- ## AbstractNaming -**Since:** 1.4 +**Since:** PMD 1.4 **Priority:** Medium (3) Abstract classes should be named 'AbstractXXX'. +``` +//ClassOrInterfaceDeclaration + [@Abstract='true' and @Interface='false'] + [not (starts-with(@Image,'Abstract'))] +| +//ClassOrInterfaceDeclaration + [@Abstract='false'] + [$strict='true'] + [starts-with(@Image, 'Abstract')] +``` + **Example(s):** ``` @@ -29,12 +40,14 @@ public abstract class Foo { // should be AbstractFoo ## AvoidDollarSigns -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) Avoid using dollar signs in variable/method/class/interface names. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.AvoidDollarSignsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/AvoidDollarSignsRule.java) + **Example(s):** ``` @@ -44,7 +57,7 @@ public class Fo$o { // not a recommended name ## AvoidFieldNameMatchingMethodName -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -52,6 +65,8 @@ It can be confusing to have a field name with the same name as a method. While t having information (field) and actions (method) is not clear naming. Developers versed in Smalltalk often prefer this approach as the methods denote accessor methods. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.AvoidFieldNameMatchingMethodNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/AvoidFieldNameMatchingMethodNameRule.java) + **Example(s):** ``` @@ -65,13 +80,15 @@ public class Foo { ## AvoidFieldNameMatchingTypeName -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) It is somewhat confusing to have a field name matching the declaring class name. This probably means that type and/or field names should be chosen more carefully. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.AvoidFieldNameMatchingTypeNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/AvoidFieldNameMatchingTypeNameRule.java) + **Example(s):** ``` @@ -82,7 +99,7 @@ public class Foo extends Bar { ## BooleanGetMethodName -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium Low (4) @@ -90,6 +107,16 @@ Methods that return boolean results should be named as predicate statements to d I.e, 'isReady()', 'hasValues()', 'canCommit()', 'willFail()', etc. Avoid the use of the 'get' prefix for these methods. +``` +//MethodDeclaration[ +MethodDeclarator[count(FormalParameters/FormalParameter) = 0 or $checkParameterizedMethods = 'true'] + [starts-with(@Image, 'get')] +and +ResultType/Type/PrimitiveType[@Image = 'boolean'] +and not(../Annotation//Name[@Image = 'Override']) +] +``` + **Example(s):** ``` @@ -106,12 +133,14 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true ## ClassNamingConventions -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** High (1) Class names should always begin with an upper case character. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.ClassNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/ClassNamingConventionsRule.java) + **Example(s):** ``` @@ -120,12 +149,20 @@ public class Foo {} ## GenericsNaming -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium Low (4) Names for references to generic values should be limited to a single uppercase letter. +``` +//TypeDeclaration/ClassOrInterfaceDeclaration/TypeParameters/TypeParameter[ + string-length(@Image) > 1 + or + string:upper-case(@Image) != @Image +] +``` + **Example(s):** ``` @@ -148,12 +185,16 @@ public interface GenericDao<EF extends BaseModel, K extends Serializable> { ## LongVariable -**Since:** 0.3 +**Since:** PMD 0.3 **Priority:** Medium (3) Fields, formal arguments, or local variable names that are too long can make the code difficult to follow. +``` +//VariableDeclaratorId[string-length(@Image) > $minimum] +``` + **Example(s):** ``` @@ -176,12 +217,14 @@ public class Something { ## MethodNamingConventions -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** High (1) Method names should always begin with a lower case character, and should not contain underscores. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.MethodNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/MethodNamingConventionsRule.java) + **Example(s):** ``` @@ -199,12 +242,14 @@ public class Foo { ## MethodWithSameNameAsEnclosingClass -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) Non-constructor methods should not have the same name as the enclosing class. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.MethodWithSameNameAsEnclosingClassRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/MethodWithSameNameAsEnclosingClassRule.java) + **Example(s):** ``` @@ -218,12 +263,18 @@ public class MyClass { ## MisleadingVariableName -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Detects when a non-field has a name starting with 'm_'. This usually denotes a field and could be confusing. +``` +//VariableDeclaratorId +[starts-with(@Image, 'm_')] +[not (../../../FieldDeclaration)] +``` + **Example(s):** ``` @@ -237,12 +288,16 @@ public class Foo { ## NoPackage -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) Detects when a class or interface does not have a package definition. +``` +//ClassOrInterfaceDeclaration[count(preceding::PackageDeclaration) = 0] +``` + **Example(s):** ``` @@ -253,12 +308,16 @@ public class ClassInDefaultPackage { ## PackageCase -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) Detects when a package definition contains uppercase characters. +``` +//PackageDeclaration/Name[lower-case(@Image)!=@Image] +``` + **Example(s):** ``` @@ -270,12 +329,16 @@ public class SomeClass { ## ShortClassName -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) Short Classnames with fewer than e.g. five characters are not recommended. +``` +//ClassOrInterfaceDeclaration[string-length(@Image) < $minimum] +``` + **Example(s):** ``` @@ -291,12 +354,16 @@ public class Foo { ## ShortMethodName -**Since:** 0.3 +**Since:** PMD 0.3 **Priority:** Medium (3) Method names that are very short are not helpful to the reader. +``` +//MethodDeclarator[string-length(@Image) < $minimum] +``` + **Example(s):** ``` @@ -314,12 +381,19 @@ public class ShortMethod { ## ShortVariable -**Since:** 0.3 +**Since:** PMD 0.3 **Priority:** Medium (3) Fields, local variables, or parameter names that are very short are not helpful to the reader. +``` +//VariableDeclaratorId[string-length(@Image) < $minimum] + [not(ancestor::ForInit)] + [not(../../VariableDeclarator and ../../../LocalVariableDeclaration and ../../../../ForStatement)] + [not((ancestor::FormalParameter) and (ancestor::TryStatement))] +``` + **Example(s):** ``` @@ -345,13 +419,20 @@ public class Something { ## SuspiciousConstantFieldName -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium (3) Field names using all uppercase characters - Sun's Java naming conventions indicating constants - should be declared as final. +``` +//ClassOrInterfaceDeclaration[@Interface='false'] + /ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/FieldDeclaration + [@Final='false'] + [VariableDeclarator/VariableDeclaratorId[upper-case(@Image)=@Image]] +``` + **Example(s):** ``` @@ -365,13 +446,35 @@ public class Foo { ## SuspiciousEqualsMethodName -**Since:** 2.0 +**Since:** PMD 2.0 **Priority:** Medium High (2) The method name and parameter number are suspiciously close to equals(Object), which can denote an intention to override the equals(Object) method. +``` +//MethodDeclarator[@Image = 'equals'] +[ + (count(FormalParameters/*) = 1 + and not (FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType + [@Image = 'Object' or @Image = 'java.lang.Object']) + or not (../ResultType/Type/PrimitiveType[@Image = 'boolean']) + ) or ( + count(FormalParameters/*) = 2 + and ../ResultType/Type/PrimitiveType[@Image = 'boolean'] + and FormalParameters//ClassOrInterfaceType[@Image = 'Object' or @Image = 'java.lang.Object'] + and not(../../Annotation/MarkerAnnotation/Name[@Image='Override']) + ) +] +| //MethodDeclarator[@Image = 'equal'] +[ + count(FormalParameters/*) = 1 + and FormalParameters/FormalParameter/Type/ReferenceType/ClassOrInterfaceType + [@Image = 'Object' or @Image = 'java.lang.Object'] +] +``` + **Example(s):** ``` @@ -390,13 +493,15 @@ public class Foo { ## SuspiciousHashcodeMethodName -**Since:** 1.5 +**Since:** PMD 1.5 **Priority:** Medium (3) The method name and return type are suspiciously close to hashCode(), which may denote an intention to override the hashCode() method. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.SuspiciousHashcodeMethodNameRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/SuspiciousHashcodeMethodNameRule.java) + **Example(s):** ``` @@ -409,7 +514,7 @@ public class Foo { ## VariableNamingConventions -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** High (1) @@ -417,6 +522,8 @@ A variable naming conventions rule - customize this to your liking. Currently, checks for final variables that should be fully capitalized and non-final variables that should not include underscores. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.naming.VariableNamingConventionsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/naming/VariableNamingConventionsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/optimizations.md b/docs/pages/pmd/rules/java/optimizations.md index efdf79976..de38a654f 100644 --- a/docs/pages/pmd/rules/java/optimizations.md +++ b/docs/pages/pmd/rules/java/optimizations.md @@ -8,13 +8,17 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/optimizations.xml --- ## AddEmptyString -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) The conversion of literals to strings by concatenating them with empty strings is inefficient. It is much better to use one of the type-specific toString() methods instead. +``` +//AdditiveExpression/PrimaryExpression/PrimaryPrefix/Literal[@Image='""'] +``` + **Example(s):** ``` @@ -24,12 +28,31 @@ String t = Integer.toString(456); // preferred approach ## AvoidArrayLoops -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead. +``` +//Statement[(ForStatement or WhileStatement) and +count(*//AssignmentOperator[@Image = '='])=1 +and +*/Statement +[ +./Block/BlockStatement/Statement/StatementExpression/PrimaryExpression +/PrimaryPrefix/Name/../../PrimarySuffix/Expression +[(PrimaryExpression or AdditiveExpression) and count +(.//PrimaryPrefix/Name)=1]//PrimaryPrefix/Name/@Image +and +./Block/BlockStatement/Statement/StatementExpression/Expression/PrimaryExpression +/PrimaryPrefix/Name/../../PrimarySuffix[count +(..//PrimarySuffix)=1]/Expression[(PrimaryExpression +or AdditiveExpression) and count(.//PrimaryPrefix/Name)=1] +//PrimaryPrefix/Name/@Image +]] +``` + **Example(s):** ``` @@ -53,12 +76,14 @@ public class Test { ## AvoidInstantiatingObjectsInLoops -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) New objects created within loops should be checked to see if they can created outside them and reused. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.AvoidInstantiatingObjectsInLoopsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/AvoidInstantiatingObjectsInLoopsRule.java) + **Example(s):** ``` @@ -73,12 +98,14 @@ public class Something { ## LocalVariableCouldBeFinal -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) A local variable assigned only once can be declared final. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.LocalVariableCouldBeFinalRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/LocalVariableCouldBeFinalRule.java) + **Example(s):** ``` @@ -92,12 +119,14 @@ public class Bar { ## MethodArgumentCouldBeFinal -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) A method argument that is never re-assigned within the method can be declared final. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.MethodArgumentCouldBeFinalRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/MethodArgumentCouldBeFinalRule.java) + **Example(s):** ``` @@ -112,12 +141,14 @@ public void foo2 (final String param) { // better, do stuff with param never ass ## PrematureDeclaration -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.PrematureDeclarationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/PrematureDeclarationRule.java) + **Example(s):** ``` @@ -137,13 +168,15 @@ public int getLength(String[] strings) { ## RedundantFieldInitializer -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Java will initialize fields with known default values so any explicit initialization of those same defaults is redundant and results in a larger class file (approximately three additional bytecode instructions per field). +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.RedundantFieldInitializerRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/RedundantFieldInitializerRule.java) + **Example(s):** ``` @@ -170,13 +203,26 @@ public class C { ## SimplifyStartsWith -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0) at the expense of some readability. +``` +//PrimaryExpression + [PrimaryPrefix/Name + [ends-with(@Image, '.startsWith')] or PrimarySuffix[@Image='startsWith']] + [PrimarySuffix/Arguments/ArgumentList + /Expression/PrimaryExpression/PrimaryPrefix + /Literal + [string-length(@Image)=3] + [starts-with(@Image, '"')] + [ends-with(@Image, '"')] + ] +``` + **Example(s):** ``` @@ -194,7 +240,7 @@ public class Foo { ## UnnecessaryWrapperObjectCreation -**Since:** 3.8 +**Since:** PMD 3.8 **Priority:** Medium (3) @@ -202,6 +248,8 @@ Most wrapper classes provide static conversion methods that avoid the need to cr just to create the primitive forms. Using these avoids the cost of creating objects that also need to be garbage-collected later. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.UnnecessaryWrapperObjectCreationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/UnnecessaryWrapperObjectCreationRule.java) + **Example(s):** ``` @@ -223,12 +271,18 @@ public int convert(String s) { ## UseArrayListInsteadOfVector -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required. +``` +//CompilationUnit[count(ImportDeclaration) = 0 or count(ImportDeclaration/Name[@Image='java.util.Vector']) > 0] + //AllocationExpression/ClassOrInterfaceType + [@Image='Vector' or @Image='java.util.Vector'] +``` + **Example(s):** ``` @@ -242,13 +296,45 @@ public class SimpleTest extends TestCase { ## UseArraysAsList -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from an array of objects. It is faster than executing a loop to copy all the elements of the array one by one. +``` +//Statement[ + (ForStatement) and (ForStatement//VariableInitializer//Literal[@IntLiteral='true' and @Image='0']) and (count(.//IfStatement)=0) + ] + //StatementExpression[ + PrimaryExpression/PrimaryPrefix/Name[ + substring-before(@Image,'.add') = ancestor::MethodDeclaration//LocalVariableDeclaration[ + ./Type//ClassOrInterfaceType[ + @Image = 'Collection' or + @Image = 'List' or @Image='ArrayList' + ] + ] + /VariableDeclarator/VariableDeclaratorId[ + count(..//AllocationExpression/ClassOrInterfaceType[ + @Image="ArrayList" + ] + )=1 + ]/@Image + ] + and + PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name + [ + @Image = ancestor::MethodDeclaration//LocalVariableDeclaration[@Array="true"]/VariableDeclarator/VariableDeclaratorId/@Image + or + @Image = ancestor::MethodDeclaration//FormalParameter/VariableDeclaratorId/@Image + ] + /../..[count(.//PrimarySuffix) + =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix + /Name + ] +``` + **Example(s):** ``` @@ -268,7 +354,7 @@ public class Test { ## UseStringBufferForStringAppends -**Since:** 3.1 +**Since:** PMD 3.1 **Priority:** Medium (3) @@ -276,6 +362,8 @@ The use of the '+=' operator for appending strings causes the JVM to create and If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or threadsafe StringBuffer is recommended to avoid this. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.optimizations.UseStringBufferForStringAppendsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/optimizations/UseStringBufferForStringAppendsRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/strictexception.md b/docs/pages/pmd/rules/java/strictexception.md index 116668861..b8cf10895 100644 --- a/docs/pages/pmd/rules/java/strictexception.md +++ b/docs/pages/pmd/rules/java/strictexception.md @@ -8,12 +8,19 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/strictexception.xml --- ## AvoidCatchingGenericException -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium (3) Avoid catching generic exceptions such as NullPointerException, RuntimeException, Exception in try-catch block +``` +//CatchStatement/FormalParameter/Type/ReferenceType/ClassOrInterfaceType[ + @Image='NullPointerException' or + @Image='Exception' or + @Image='RuntimeException'] +``` + **Example(s):** ``` @@ -37,13 +44,18 @@ public class PrimitiveType { ## AvoidCatchingNPE -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** Medium (3) Code should never throw NullPointerExceptions under normal circumstances. A catch block may hide the original error, causing other, more subtle problems later on. +``` +//CatchStatement/FormalParameter/Type + /ReferenceType/ClassOrInterfaceType[@Image='NullPointerException'] +``` + **Example(s):** ``` @@ -59,13 +71,15 @@ public class Foo { ## AvoidCatchingThrowable -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** Medium (3) Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as OutOfMemoryError that should be exposed and managed separately. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strictexception.AvoidCatchingThrowableRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strictexception/AvoidCatchingThrowableRule.java) + **Example(s):** ``` @@ -80,13 +94,28 @@ public void bar() { ## AvoidLosingExceptionInformation -**Since:** 4.2.6 +**Since:** PMD 4.2.6 **Priority:** Medium High (2) Statements in a catch block that invoke accessors on the exception without using the information only add to code size. Either remove the invocation, or use the return result. +``` +//CatchStatement/Block/BlockStatement/Statement/StatementExpression/PrimaryExpression/PrimaryPrefix/Name +[ + @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getMessage') + or + @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getLocalizedMessage') + or + @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getCause') + or + @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.getStackTrace') + or + @Image = concat(../../../../../../../FormalParameter/VariableDeclaratorId/@Image, '.toString') +] +``` + **Example(s):** ``` @@ -101,12 +130,19 @@ public void bar() { ## AvoidRethrowingException -**Since:** 3.8 +**Since:** PMD 3.8 **Priority:** Medium (3) Catch blocks that merely rethrow a caught exception only add to code size and runtime complexity. +``` +//CatchStatement[FormalParameter + /VariableDeclaratorId/@Image = Block/BlockStatement/Statement + /ThrowStatement/Expression/PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix/Name/@Image + and count(Block/BlockStatement/Statement) =1] +``` + **Example(s):** ``` @@ -121,13 +157,25 @@ public void bar() { ## AvoidThrowingNewInstanceOfSameException -**Since:** 4.2.5 +**Since:** PMD 4.2.5 **Priority:** Medium (3) Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to code size and runtime complexity. +``` +//CatchStatement[ + count(Block/BlockStatement/Statement) = 1 + and + FormalParameter/Type/ReferenceType/ClassOrInterfaceType/@Image = Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/ClassOrInterfaceType/@Image + and + count(Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/Arguments/ArgumentList/Expression) = 1 + and + FormalParameter/VariableDeclaratorId = Block/BlockStatement/Statement/ThrowStatement/Expression/PrimaryExpression/PrimaryPrefix/AllocationExpression/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name + ] +``` + **Example(s):** ``` @@ -143,7 +191,7 @@ public void bar() { ## AvoidThrowingNullPointerException -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** High (1) @@ -151,6 +199,10 @@ Avoid throwing NullPointerExceptions. These are confusing because most people wi virtual machine threw it. Consider using an IllegalArgumentException instead; this will be clearly seen as a programmer-initiated exception. +``` +//AllocationExpression/ClassOrInterfaceType[@Image='NullPointerException'] +``` + **Example(s):** ``` @@ -163,13 +215,26 @@ public class Foo { ## AvoidThrowingRawExceptionTypes -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** High (1) Avoid throwing certain exception types. Rather than throw a raw RuntimeException, Throwable, Exception, or Error, use a subclassed exception or error instead. +``` +//ThrowStatement//AllocationExpression + /ClassOrInterfaceType[ + (@Image='Throwable' and count(//ImportDeclaration/Name[ends-with(@Image,'Throwable')]) = 0) +or + (@Image='Exception' and count(//ImportDeclaration/Name[ends-with(@Image,'Exception')]) = 0) +or + (@Image='Error' and count(//ImportDeclaration/Name[ends-with(@Image,'Error')]) = 0) +or +( @Image='RuntimeException' and count(//ImportDeclaration/Name[ends-with(@Image,'RuntimeException')]) = 0) +] +``` + **Example(s):** ``` @@ -182,12 +247,17 @@ public class Foo { ## DoNotExtendJavaLangError -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) Errors are system exceptions. Do not extend them. +``` +//ClassOrInterfaceDeclaration/ExtendsList/ClassOrInterfaceType + [@Image="Error" or @Image="java.lang.Error"] +``` + **Example(s):** ``` @@ -196,7 +266,7 @@ public class Foo extends Error { } ## DoNotThrowExceptionInFinally -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium Low (4) @@ -204,6 +274,10 @@ Throwing exceptions within a 'finally' block is confusing since they may mask ot or code defects. Note: This is a PMD implementation of the Lint4j rule "A throw in a finally block" +``` +//FinallyStatement[descendant::ThrowStatement] +``` + **Example(s):** ``` @@ -223,13 +297,15 @@ public class Foo { ## ExceptionAsFlowControl -**Since:** 1.8 +**Since:** PMD 1.8 **Priority:** Medium (3) Using Exceptions as form of flow control is not recommended as they obscure true exceptions when debugging. Either add the necessary validation or use an alternate control structure. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strictexception.ExceptionAsFlowControlRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strictexception/ExceptionAsFlowControlRule.java) + **Example(s):** ``` @@ -248,13 +324,15 @@ public void bar() { ## SignatureDeclareThrowsException -**Since:** 1.2 +**Since:** PMD 1.2 **Priority:** Medium (3) Methods that declare the generic Exception as a possible throwable are not very helpful since their failure modes are unclear. Use a class derived from RuntimeException or a more specific checked exception. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strictexception.SignatureDeclareThrowsExceptionRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strictexception/SignatureDeclareThrowsExceptionRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/strings.md b/docs/pages/pmd/rules/java/strings.md index d99550a71..8ee7c03c5 100644 --- a/docs/pages/pmd/rules/java/strings.md +++ b/docs/pages/pmd/rules/java/strings.md @@ -8,12 +8,14 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/strings.xml --- ## AppendCharacterWithChar -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.AppendCharacterWithCharRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AppendCharacterWithCharRule.java) + **Example(s):** ``` @@ -26,12 +28,14 @@ sb.append('a'); // use this instead ## AvoidDuplicateLiterals -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Code containing duplicate String literals can usually be improved by declaring the String as a constant field. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.AvoidDuplicateLiteralsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/AvoidDuplicateLiteralsRule.java) + **Example(s):** ``` @@ -57,13 +61,17 @@ private void bar() { ## AvoidStringBufferField -**Since:** 4.2 +**Since:** PMD 4.2 **Priority:** Medium (3) StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaks if held within objects with long lifetimes. +``` +//FieldDeclaration/Type/ReferenceType/ClassOrInterfaceType[@Image = 'StringBuffer' or @Image = 'StringBuilder'] +``` + **Example(s):** ``` @@ -74,13 +82,15 @@ public class Foo { ## ConsecutiveAppendsShouldReuse -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performance by producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be found [here](https://github.com/pmd/pmd/issues/202#issuecomment-274349067) +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.ConsecutiveAppendsShouldReuseRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveAppendsShouldReuseRule.java) + **Example(s):** ``` @@ -97,12 +107,14 @@ buf.append("Hello").append(foo).append("World"); // good ## ConsecutiveLiteralAppends -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) Consecutively calling StringBuffer/StringBuilder.append with String literals +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.ConsecutiveLiteralAppendsRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/ConsecutiveLiteralAppendsRule.java) + **Example(s):** ``` @@ -119,7 +131,7 @@ buf.append("Hello World"); // good ## InefficientEmptyStringCheck -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) @@ -129,6 +141,8 @@ loops through a string, checking Character.isWhitespace() on each character and false if a non-whitespace character is found. You can refer to Apache's StringUtils#isBlank (in commons-lang) or Spring's StringUtils#hasText (in the Springs framework) for existing implementations. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.InefficientEmptyStringCheckRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InefficientEmptyStringCheckRule.java) + **Example(s):** ``` @@ -141,13 +155,15 @@ public void bar(String string) { ## InefficientStringBuffering -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers will need to be be created and destroyed by the JVM. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.InefficientStringBufferingRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InefficientStringBufferingRule.java) + **Example(s):** ``` @@ -161,7 +177,7 @@ sb.append(System.getProperty("java.io.tmpdir")); ## InsufficientStringBufferDeclaration -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) @@ -171,6 +187,8 @@ passed into StringBuffer.append(), but represents a best guess "worst case" scen StringBuffer/StringBuilder constructor initializes the object to 16 characters. This default is assumed if the length of the constructor can not be determined. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.InsufficientStringBufferDeclarationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InsufficientStringBufferDeclarationRule.java) + **Example(s):** ``` @@ -183,7 +201,7 @@ good.append("This is a long string, which is pre-sized"); ## StringBufferInstantiationWithChar -**Since:** 3.9 +**Since:** PMD 3.9 **Priority:** Medium Low (4) @@ -202,6 +220,16 @@ new StringBuilder("hello world") // 11 + 16 = 27 new StringBuilder('C') // chr(C) = 67 new StringBuilder("A") // 1 + 16 = 17 +``` +//AllocationExpression/ClassOrInterfaceType +[@Image='StringBuffer' or @Image='StringBuilder'] +/../Arguments/ArgumentList/Expression/PrimaryExpression +/PrimaryPrefix/ +Literal + [starts-with(@Image, "'")] + [ends-with(@Image, "'")] +``` + **Example(s):** ``` @@ -217,12 +245,14 @@ StringBuilder sb4 = new StringBuilder("c"); ## StringInstantiation -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium High (2) Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.StringInstantiationRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/StringInstantiationRule.java) + **Example(s):** ``` @@ -231,12 +261,14 @@ private String bar = new String("bar"); // just do a String bar = "bar"; ## StringToString -**Since:** 1.0 +**Since:** PMD 1.0 **Priority:** Medium (3) Avoid calling toString() on objects already known to be string instances; this is unnecessary. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.StringToStringRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/StringToStringRule.java) + **Example(s):** ``` @@ -248,12 +280,14 @@ private String baz() { ## UnnecessaryCaseChange -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) Using equalsIgnoreCase() is faster than using toUpperCase/toLowerCase().equals() +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.UnnecessaryCaseChangeRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/UnnecessaryCaseChangeRule.java) + **Example(s):** ``` @@ -264,13 +298,21 @@ boolean answer2 = buz.toUpperCase().equalsIgnoreCase("baz"); // another unneces ## UseEqualsToCompareStrings -**Since:** 4.1 +**Since:** PMD 4.1 **Priority:** Medium (3) Using '==' or '!=' to compare strings only works if intern version is used on both sides. Use the equals() method instead. +``` +//EqualityExpression/PrimaryExpression +[(PrimaryPrefix/Literal + [starts-with(@Image, '"')] + [ends-with(@Image, '"')] +and count(PrimarySuffix) = 0)] +``` + **Example(s):** ``` @@ -283,12 +325,14 @@ public boolean test(String s) { ## UseIndexOfChar -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) Use String.indexOf(char) when checking for the index of a single character; it executes faster. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.UseIndexOfCharRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/UseIndexOfCharRule.java) + **Example(s):** ``` @@ -301,12 +345,14 @@ if (s.indexOf('d') {} ## UselessStringValueOf -**Since:** 3.8 +**Since:** PMD 3.8 **Priority:** Medium (3) No need to call String.valueOf to append to a string; just use the valueOf() argument directly. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.UselessStringValueOfRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/UselessStringValueOfRule.java) + **Example(s):** ``` @@ -320,13 +366,15 @@ public String convert(int i) { ## UseStringBufferLength -**Since:** 3.4 +**Since:** PMD 3.4 **Priority:** Medium (3) Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("") or StringBuffer.toString().length() == ... +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.strings.UseStringBufferLengthRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/UseStringBufferLengthRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/sunsecure.md b/docs/pages/pmd/rules/java/sunsecure.md index a34d44125..93d766760 100644 --- a/docs/pages/pmd/rules/java/sunsecure.md +++ b/docs/pages/pmd/rules/java/sunsecure.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/sunsecure.xml --- ## ArrayIsStoredDirectly -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) Constructors and methods receiving arrays should clone objects and store the copy. This prevents future changes from the user from affecting the original array. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.sunsecure.ArrayIsStoredDirectlyRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/sunsecure/ArrayIsStoredDirectlyRule.java) + **Example(s):** ``` @@ -29,13 +31,15 @@ public class Foo { ## MethodReturnsInternalArray -**Since:** 2.2 +**Since:** PMD 2.2 **Priority:** Medium (3) Exposing internal arrays to the caller violates object encapsulation since elements can be removed or replaced outside of the object that owns it. It is safer to return a copy of the array. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.sunsecure.MethodReturnsInternalArrayRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/sunsecure/MethodReturnsInternalArrayRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/unnecessary.md b/docs/pages/pmd/rules/java/unnecessary.md index c9601d5f4..02e4dc8fe 100644 --- a/docs/pages/pmd/rules/java/unnecessary.md +++ b/docs/pages/pmd/rules/java/unnecessary.md @@ -8,13 +8,15 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/unnecessary.xml --- ## UnnecessaryConversionTemporary -**Since:** 0.1 +**Since:** PMD 0.1 **Priority:** Medium (3) Avoid the use temporary objects when converting primitives to Strings. Use the static conversion methods on the wrapper classes instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unnecessary.UnnecessaryConversionTemporaryRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unnecessary/UnnecessaryConversionTemporaryRule.java) + **Example(s):** ``` @@ -27,7 +29,7 @@ public String convert(int x) { ## UnnecessaryFinalModifier -**Since:** 3.0 +**Since:** PMD 3.0 **Priority:** Medium (3) @@ -35,6 +37,16 @@ When a class has the final modifier, all the methods are automatically final and tagged as such. Similarly, methods that can't be overridden (private methods, methods of anonymous classes, methods of enum instance) do not need to be tagged either. +``` +//ClassOrInterfaceDeclaration[@Final='true' and @Interface='false'] + /ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration + [count(./Annotation/MarkerAnnotation/Name[@Image='SafeVarargs' or @Image='java.lang.SafeVarargs']) = 0] + /MethodDeclaration[@Final='true'] +| //MethodDeclaration[@Final='true' and @Private='true'] +| //EnumConstant/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration[@Final='true'] +| //AllocationExpression/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration[@Final='true'] +``` + **Example(s):** ``` @@ -48,7 +60,7 @@ public final class Foo { ## UnnecessaryModifier -**Since:** 1.02 +**Since:** PMD 1.02 **Priority:** Medium (3) @@ -58,6 +70,8 @@ Classes, interfaces or annotations nested in an interface or annotation are auto Nested enums are automatically `static`. For historical reasons, modifiers which are implied by the context are accepted by the compiler, but are superfluous. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unnecessary.UnnecessaryModifierRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unnecessary/UnnecessaryModifierRule.java) + **Example(s):** ``` @@ -83,12 +97,14 @@ public class Bar { ## UnnecessaryReturn -**Since:** 1.3 +**Since:** PMD 1.3 **Priority:** Medium (3) Avoid the use of unnecessary return statements. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unnecessary.UnnecessaryReturnRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unnecessary/UnnecessaryReturnRule.java) + **Example(s):** ``` @@ -102,12 +118,22 @@ public class Foo { ## UnusedNullCheckInEquals -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) After checking an object reference for null, you should invoke equals() on that object rather than passing it to another object's equals() method. +``` +(//PrimaryPrefix[ends-with(Name/@Image, '.equals') and Name/@Image != 'Arrays.equals'] | //PrimarySuffix[@Image='equals' and not(../PrimaryPrefix/Literal)]) + /following-sibling::PrimarySuffix/Arguments/ArgumentList/Expression + /PrimaryExpression[count(PrimarySuffix)=0]/PrimaryPrefix + /Name[@Image = ./../../../../../../../../../../Expression/ConditionalAndExpression + /EqualityExpression[@Image="!=" and count(./preceding-sibling::*)=0 and + ./PrimaryExpression/PrimaryPrefix/Literal/NullLiteral] + /PrimaryExpression/PrimaryPrefix/Name/@Image] +``` + **Example(s):** ``` @@ -150,13 +176,15 @@ public class Test { ## UselessOperationOnImmutable -**Since:** 3.5 +**Since:** PMD 3.5 **Priority:** Medium (3) An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself since the result of the operation is a new object. Therefore, ignoring the operation result is an error. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unnecessary.UselessOperationOnImmutableRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unnecessary/UselessOperationOnImmutableRule.java) + **Example(s):** ``` @@ -176,12 +204,14 @@ class Test { ## UselessOverridingMethod -**Since:** 3.3 +**Since:** PMD 3.3 **Priority:** Medium (3) The overriding method merely calls the same method defined in a superclass. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unnecessary.UselessOverridingMethodRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unnecessary/UselessOverridingMethodRule.java) + **Example(s):** ``` @@ -207,12 +237,62 @@ public Long getId() { ## UselessParentheses -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium Low (4) Useless parentheses should be removed. +``` +//Expression/PrimaryExpression/PrimaryPrefix/Expression +[count(*)=1][count(./CastExpression)=0][count(./ConditionalExpression[@Ternary='true'])=0] +[not(./AdditiveExpression[//Literal[@StringLiteral='true']])] +| +//Expression/ConditionalAndExpression/PrimaryExpression/PrimaryPrefix/Expression[ + count(*)=1 and + count(./CastExpression)=0 and + count(./EqualityExpression/MultiplicativeExpression)=0 and + count(./ConditionalExpression[@Ternary='true'])=0 and + count(./ConditionalOrExpression)=0] +| +//Expression/ConditionalOrExpression/PrimaryExpression/PrimaryPrefix/Expression[ + count(*)=1 and + count(./CastExpression)=0 and + count(./ConditionalExpression[@Ternary='true'])=0 and + count(./EqualityExpression/MultiplicativeExpression)=0] +| +//Expression/ConditionalExpression/PrimaryExpression/PrimaryPrefix/Expression[ + count(*)=1 and + count(./CastExpression)=0 and + count(./EqualityExpression)=0] +| +//Expression/AdditiveExpression[not(./PrimaryExpression/PrimaryPrefix/Literal[@StringLiteral='true'])]/PrimaryExpression[1]/PrimaryPrefix/Expression[ + count(*)=1 and + not(./CastExpression) and + not(./AdditiveExpression[@Image = '-']) and + not(./ShiftExpression) and + not(./RelationalExpression) and + not(./InstanceOfExpression) and + not(./EqualityExpression) and + not(./AndExpression) and + not(./ExclusiveOrExpression) and + not(./InclusiveOrExpression) and + not(./ConditionalAndExpression) and + not(./ConditionalOrExpression) and + not(./ConditionalExpression)] +| +//Expression/EqualityExpression/PrimaryExpression/PrimaryPrefix/Expression[ + count(*)=1 and + count(./CastExpression)=0 and + count(./AndExpression)=0 and + count(./InclusiveOrExpression)=0 and + count(./ExclusiveOrExpression)=0 and + count(./ConditionalExpression)=0 and + count(./ConditionalAndExpression)=0 and + count(./ConditionalOrExpression)=0 and + count(./EqualityExpression)=0] +``` + **Example(s):** ``` @@ -231,12 +311,21 @@ public class Foo { ## UselessQualifiedThis -**Since:** 5.4.0 +**Since:** PMD 5.4.0 **Priority:** Medium (3) Look for qualified this usages in the same class. +``` +//PrimaryExpression +[PrimaryPrefix/Name[@Image]] +[PrimarySuffix[@Arguments='false']] +[not(PrimarySuffix/MemberSelector)] +[ancestor::ClassOrInterfaceBodyDeclaration[1][@AnonymousInnerClass='false']] +/PrimaryPrefix/Name[@Image = ancestor::ClassOrInterfaceDeclaration[1]/@Image] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/java/unusedcode.md b/docs/pages/pmd/rules/java/unusedcode.md index 4b956a988..b120837b7 100644 --- a/docs/pages/pmd/rules/java/unusedcode.md +++ b/docs/pages/pmd/rules/java/unusedcode.md @@ -8,12 +8,14 @@ editmepath: ../pmd-java/src/main/resources/rulesets/java/unusedcode.xml --- ## UnusedFormalParameter -**Since:** 0.8 +**Since:** PMD 0.8 **Priority:** Medium (3) Avoid passing parameters to methods or constructors without actually referencing them in the method body. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedFormalParameterRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedFormalParameterRule.java) + **Example(s):** ``` @@ -32,12 +34,14 @@ public class Foo { ## UnusedLocalVariable -**Since:** 0.1 +**Since:** PMD 0.1 **Priority:** Medium (3) Detects when a local variable is declared and/or assigned, but not used. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedLocalVariableRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedLocalVariableRule.java) + **Example(s):** ``` @@ -50,12 +54,14 @@ public class Foo { ## UnusedPrivateField -**Since:** 0.1 +**Since:** PMD 0.1 **Priority:** Medium (3) Detects when a private field is declared and/or assigned a value, but not used. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedPrivateFieldRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateFieldRule.java) + **Example(s):** ``` @@ -71,12 +77,14 @@ public class Something { ## UnusedPrivateMethod -**Since:** 0.7 +**Since:** PMD 0.7 **Priority:** Medium (3) Unused Private Method detects when a private method is declared but is unused. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedPrivateMethodRule](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedPrivateMethodRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/jsp/basic-jsf.md b/docs/pages/pmd/rules/jsp/basic-jsf.md index 73ceb11d3..2e95c66ed 100644 --- a/docs/pages/pmd/rules/jsp/basic-jsf.md +++ b/docs/pages/pmd/rules/jsp/basic-jsf.md @@ -8,12 +8,16 @@ editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic-jsf.xml --- ## DontNestJsfInJstlIteration -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) Do not nest JSF component custom actions inside a custom action that iterates over its body. +``` +//Element[ @Name="c:forEach" ] // Element[ @NamespacePrefix="h" or @NamespacePrefix="f" ] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/jsp/basic.md b/docs/pages/pmd/rules/jsp/basic.md index 2f3335af1..ff1b4834f 100644 --- a/docs/pages/pmd/rules/jsp/basic.md +++ b/docs/pages/pmd/rules/jsp/basic.md @@ -8,12 +8,14 @@ editmepath: ../pmd-jsp/src/main/resources/rulesets/jsp/basic.xml --- ## DuplicateJspImports -**Since:** 3.7 +**Since:** PMD 3.7 **Priority:** Medium (3) Avoid duplicate import statements inside JSP's. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.jsp.rule.basic.DuplicateJspImportsRule](https://github.com/pmd/pmd/blob/master/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/rule/basic/DuplicateJspImportsRule.java) + **Example(s):** ``` @@ -22,13 +24,17 @@ Avoid duplicate import statements inside JSP's. ## IframeMissingSrcAttribute -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium High (2) IFrames which are missing a src element can cause security information popups in IE if you are accessing the page through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 +``` +//Element[upper-case(@Name)="IFRAME"][count(Attribute[upper-case(@Name)="SRC" ]) = 0] +``` + **Example(s):** ``` @@ -43,12 +49,22 @@ through SSL. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q261188 ## JspEncoding -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) A missing 'meta' tag or page directive will trigger this rule, as well as a non-UTF-8 charset. +``` +//CompilationUnit/Content[ +not(Element[@Name="meta"][ + Attribute[@Name="content"]/AttributeValue[contains(lower-case(@Image),"charset=utf-8")] +]) +and + not(JspDirective[@Name='page']/JspDirectiveAttribute[@Name='contentType'][contains(lower-case(@Value),"charset=utf-8")]) +] +``` + **Example(s):** ``` @@ -61,12 +77,16 @@ Most browsers should be able to interpret the following headers: ## NoClassAttribute -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium High (2) Do not use an attribute called 'class'. Use "styleclass" for CSS styles. +``` +//Attribute[ upper-case(@Name)="CLASS" ] +``` + **Example(s):** ``` @@ -77,7 +97,7 @@ Do not use an attribute called 'class'. Use "styleclass" for CSS styles. ## NoHtmlComments -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium High (2) @@ -85,6 +105,10 @@ In a production system, HTML comments increase the payload between the application server to the client, and serve little other purpose. Consider switching to JSP comments. +``` +//CommentTag +``` + **Example(s):** ``` @@ -99,13 +123,17 @@ In a production system, HTML comments increase the payload ## NoInlineScript -**Since:** 4.0 +**Since:** PMD 4.0 **Priority:** Medium (3) Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the "script" element. Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth. +``` +//HtmlScript[@Image != ''] +``` + **Example(s):** ``` @@ -118,12 +146,14 @@ Most browsers should be able to interpret the following headers: ## NoInlineStyleInformation -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) Style information should be put in CSS files, not in JSPs. Therefore, don't use <B> or <FONT> tags, or attributes like "align='center'". +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.jsp.rule.basic.NoInlineStyleInformationRule](https://github.com/pmd/pmd/blob/master/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/rule/basic/NoInlineStyleInformationRule.java) + **Example(s):** ``` @@ -132,12 +162,16 @@ Style information should be put in CSS files, not in JSPs. Therefore, don't use ## NoJspForward -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) Do not do a forward from within a JSP file. +``` +//Element[ @Name="jsp:forward" ] +``` + **Example(s):** ``` @@ -146,12 +180,16 @@ Do not do a forward from within a JSP file. ## NoLongScripts -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium High (2) Scripts should be part of Tag Libraries, rather than part of JSP pages. +``` +// HtmlScript [ (@EndLine - @BeginLine > 10) ] +``` + **Example(s):** ``` @@ -180,12 +218,18 @@ onload=calcDays; ## NoScriptlets -**Since:** 3.6 +**Since:** PMD 3.6 **Priority:** Medium (3) Scriptlets should be factored into Tag Libraries or JSP declarations, rather than being part of JSP pages. +``` +//JspScriptlet + | + //Element[ upper-case(@Name)="JSP:SCRIPTLET" ] +``` + **Example(s):** ``` @@ -203,13 +247,15 @@ response.setHeader("Pragma", "No-cache"); ## NoUnsanitizedJSPExpression -**Since:** 5.1.4 +**Since:** PMD 5.1.4 **Priority:** Medium (3) Avoid using expressions without escaping / sanitizing. This could lead to cross site scripting - as the expression would be interpreted by the browser directly (e.g. "<script>alert('hello');</script>"). +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.jsp.rule.basic.NoUnsanitizedJSPExpressionRule](https://github.com/pmd/pmd/blob/master/pmd-jsp/src/main/java/net/sourceforge/pmd/lang/jsp/rule/basic/NoUnsanitizedJSPExpressionRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/plsql/TomKytesDespair.md b/docs/pages/pmd/rules/plsql/TomKytesDespair.md index 92c9c160d..3eb56e5a2 100644 --- a/docs/pages/pmd/rules/plsql/TomKytesDespair.md +++ b/docs/pages/pmd/rules/plsql/TomKytesDespair.md @@ -8,12 +8,16 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/TomKytesDespair.xml --- ## TomKytesDespair -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) "WHEN OTHERS THEN NULL" hides all errors - (Re)RAISE an exception or call RAISE_APPLICATION_ERROR +``` +//ExceptionHandler[QualifiedName/@Image='OTHERS' and upper-case(Statement/UnlabelledStatement/Expression/@Image)='NULL'] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/plsql/codesize.md b/docs/pages/pmd/rules/plsql/codesize.md index b583a5a32..7bc5f1b05 100644 --- a/docs/pages/pmd/rules/plsql/codesize.md +++ b/docs/pages/pmd/rules/plsql/codesize.md @@ -8,7 +8,7 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/codesize.xml --- ## CyclomaticComplexity -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -17,6 +17,8 @@ plus one for the method entry. The decision points include 'if', 'while', 'for' Generally, numbers ranging from 1-4 denote low complexity, 5-7 denote moderate complexity, 8-10 denote high complexity, and 11+ is very high complexity. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.CyclomaticComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/CyclomaticComplexityRule.java) + **Example(s):** ``` @@ -146,7 +148,7 @@ END; ## ExcessiveMethodLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -155,6 +157,8 @@ name/signature might suggest. They also become challenging for others to digest scrolling causes readers to lose focus. Try to reduce the method length by creating helper methods and removing any copy/pasted code. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessiveMethodLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessiveMethodLengthRule.java) + **Example(s):** ``` @@ -176,7 +180,7 @@ END; ## ExcessiveObjectLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -184,6 +188,8 @@ Excessive object line lengths are usually indications that the object may be bur responsibilities that could be provided by other objects. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessiveObjectLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessiveObjectLengthRule.java) + **Example(s):** ``` @@ -216,7 +222,7 @@ END; ## ExcessivePackageBodyLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -224,6 +230,8 @@ Excessive class file lengths are usually indications that the class may be burde responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessivePackageBodyLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessivePackageBodyLengthRule.java) + **Example(s):** ``` @@ -256,7 +264,7 @@ END; ## ExcessivePackageSpecificationLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -264,6 +272,8 @@ Excessive class file lengths are usually indications that the class may be burde responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessivePackageSpecificationLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessivePackageSpecificationLengthRule.java) + **Example(s):** ``` @@ -289,13 +299,15 @@ END; ## ExcessiveParameterList -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessiveParameterListRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessiveParameterListRule.java) + **Example(s):** ``` @@ -324,7 +336,7 @@ END; ## ExcessiveTypeLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -332,6 +344,8 @@ Excessive class file lengths are usually indications that the class may be burde responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.ExcessiveTypeLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/ExcessiveTypeLengthRule.java) + **Example(s):** ``` @@ -364,7 +378,7 @@ END; ## NcssMethodCount -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -372,6 +386,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.NcssMethodCountRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/NcssMethodCountRule.java) + **Example(s):** ``` @@ -393,7 +409,7 @@ END; ## NcssObjectCount -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -401,6 +417,8 @@ This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determin of code for a given Oracle object. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.NcssObjectCountRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/NcssObjectCountRule.java) + **Example(s):** ``` @@ -424,7 +442,7 @@ CREATE OR REPLACE PACKAGE pkg_ ## NPathComplexity -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -432,6 +450,8 @@ The NPath complexity of a method is the number of acyclic execution paths throug A threshold of 200 is generally considered the point where measures should be taken to reduce complexity and increase readability. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.NPathComplexityRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/NPathComplexityRule.java) + **Example(s):** ``` @@ -479,7 +499,7 @@ END; ## TooManyFields -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) @@ -487,6 +507,8 @@ Classes that have too many fields can become unwieldy and could be redesigned to possibly through grouping related fields in new objects. For example, a class with individual city/state/zip fields could park them within a single Address field. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codesize.TooManyFieldsRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codesize/TooManyFieldsRule.java) + **Example(s):** ``` @@ -506,13 +528,47 @@ END pkg_too_many_fields; ## TooManyMethods -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) A package or type with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects. +``` +//node() + [ ( + local-name(.) = 'PackageSpecification' + or + local-name(.) = 'TypeSpecification' + ) + and + ( + count(/descendant::ProgramUnit[ + not ( + starts-with(@Image,'get') + or + starts-with(@Image,'set') + or + starts-with(@Image,'is') + ) + ] + ) + + + count(/descendant::TypeMethod[ + not ( + starts-with(@Image,'get') + or + starts-with(@Image,'set') + or + starts-with(@Image,'is') + ) + ] + ) + ) > $maxmethods + ] +``` + **This rule has the following properties:** |Name|Default Value|Description| diff --git a/docs/pages/pmd/rules/plsql/dates.md b/docs/pages/pmd/rules/plsql/dates.md index e92e6ce11..39e9a70d9 100644 --- a/docs/pages/pmd/rules/plsql/dates.md +++ b/docs/pages/pmd/rules/plsql/dates.md @@ -8,12 +8,21 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/dates.xml --- ## TO_DATE_TO_CHAR -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-veriable) +``` +//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_DATE' + and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 + and .//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_CHAR' + and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 + ] + ] +``` + **Example(s):** ``` @@ -34,12 +43,16 @@ END date_utilities ; ## TO_DATEWithoutDateFormat -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) TO_DATE without date format- use TO_DATE(expression, date-format) +``` +//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_DATE' and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 ] +``` + **Example(s):** ``` @@ -73,12 +86,16 @@ END date_utilities ; ## TO_TIMESTAMPWithoutDateFormat -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) +``` +//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_TIMESTAMP' and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 ] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/plsql/strictsyntax.md b/docs/pages/pmd/rules/plsql/strictsyntax.md index 46d222ba6..aac900bae 100644 --- a/docs/pages/pmd/rules/plsql/strictsyntax.md +++ b/docs/pages/pmd/rules/plsql/strictsyntax.md @@ -8,7 +8,7 @@ editmepath: ../pmd-plsql/src/main/resources/rulesets/plsql/strictsyntax.xml --- ## MisplacedPragma -**Since:** 5.5.2 +**Since:** PMD 5.5.2 **Priority:** Medium (3) @@ -16,6 +16,10 @@ Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration but the code does not complain, when being compiled on the 11g DB. https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#BABIIHBJ +``` +//ProgramUnit/Pragma +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/vf/security.md b/docs/pages/pmd/rules/vf/security.md index 7eae45756..79d077f7b 100644 --- a/docs/pages/pmd/rules/vf/security.md +++ b/docs/pages/pmd/rules/vf/security.md @@ -8,12 +8,14 @@ editmepath: ../pmd-visualforce/src/main/resources/rulesets/vf/security.xml --- ## VfCsrf -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vf.rule.security.VfCsrfRule](https://github.com/pmd/pmd/blob/master/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/rule/security/VfCsrfRule.java) + **Example(s):** ``` @@ -22,12 +24,14 @@ Avoid calling VF action upon page load as the action becomes vulnerable to CSRF. ## VfUnescapeEl -**Since:** 5.6.0 +**Since:** PMD 5.6.0 **Priority:** Medium (3) Avoid unescaped user controlled content in EL as it results in XSS. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vf.rule.security.VfUnescapeElRule](https://github.com/pmd/pmd/blob/master/pmd-visualforce/src/main/java/net/sourceforge/pmd/lang/vf/rule/security/VfUnescapeElRule.java) + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/vm/basic.md b/docs/pages/pmd/rules/vm/basic.md index 0919b8e1d..3499c6228 100644 --- a/docs/pages/pmd/rules/vm/basic.md +++ b/docs/pages/pmd/rules/vm/basic.md @@ -8,12 +8,14 @@ editmepath: ../pmd-vm/src/main/resources/rulesets/vm/basic.xml --- ## AvoidDeeplyNestedIfStmts -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.AvoidDeeplyNestedIfStmtsRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/AvoidDeeplyNestedIfStmtsRule.java) + **This rule has the following properties:** |Name|Default Value|Description| @@ -22,44 +24,54 @@ Avoid creating deeply nested if-then statements since they are harder to read an ## AvoidReassigningParameters -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Reassigning values to incoming parameters is not recommended. Use temporary local variables instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.AvoidReassigningParametersRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/AvoidReassigningParametersRule.java) + ## CollapsibleIfStatements -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) Sometimes two consecutive 'if' statements can be consolidated by separating their conditions with a boolean short-circuit operator. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.CollapsibleIfStatementsRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/CollapsibleIfStatementsRule.java) + ## EmptyForeachStmt -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Empty foreach statements should be deleted. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.EmptyForeachStmtRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/EmptyForeachStmtRule.java) + ## EmptyIfStmt -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Empty if statements should be deleted. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.EmptyIfStmtRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/EmptyIfStmtRule.java) + ## ExcessiveTemplateLength -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium (3) The template is too long. It should be broken up into smaller pieces. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.ExcessiveTemplateLengthRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/ExcessiveTemplateLengthRule.java) + **This rule has the following properties:** |Name|Default Value|Description| @@ -70,25 +82,33 @@ The template is too long. It should be broken up into smaller pieces. ## NoInlineJavaScript -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Avoid inline JavaScript. Import .js files instead. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.NoInlineJavaScriptRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/NoInlineJavaScriptRule.java) + ## NoInlineStyles -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Avoid inline styles. Use css classes instead. +``` +//Text[matches(@literal, "<[^>]+\s[sS][tT][yY][lL][eE]\s*=")] +``` + ## UnusedMacroParameter -**Since:** 5.1 +**Since:** PMD 5.1 **Priority:** Medium High (2) Avoid unused macro parameters. They should be deleted. +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.vm.rule.basic.UnusedMacroParameterRule](https://github.com/pmd/pmd/blob/master/pmd-vm/src/main/java/net/sourceforge/pmd/lang/vm/rule/basic/UnusedMacroParameterRule.java) + diff --git a/docs/pages/pmd/rules/xml/basic.md b/docs/pages/pmd/rules/xml/basic.md index ea057818b..c1324f053 100644 --- a/docs/pages/pmd/rules/xml/basic.md +++ b/docs/pages/pmd/rules/xml/basic.md @@ -8,12 +8,16 @@ editmepath: ../pmd-xml/src/main/resources/rulesets/xml/basic.xml --- ## MistypedCDATASection -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) An XML CDATA section begins with a <!CDATA[ marker, which has only one [, and ends with a ]]> marker, which has only two ]. +``` +//cdata-section[starts-with(@Image,'[') or ends-with(@Image,']')] +``` + **Example(s):** ``` diff --git a/docs/pages/pmd/rules/xsl/xpath.md b/docs/pages/pmd/rules/xsl/xpath.md index 7200af7ee..c0ca7a5c8 100644 --- a/docs/pages/pmd/rules/xsl/xpath.md +++ b/docs/pages/pmd/rules/xsl/xpath.md @@ -8,12 +8,29 @@ editmepath: ../pmd-xml/src/main/resources/rulesets/xsl/xpath.xml --- ## AvoidAxisNavigation -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document. +``` +//node()[ + contains(@select,'preceeding::') + or + contains(@select,'following::') + or + contains(@select,'descendant::') + or + contains(@select,'descendant-self::') + or ( + ($checkSelfDescendantAbreviation = 'true' ) + and + contains(@select,'//') + ) +] +``` + **Example(s):** ``` @@ -28,12 +45,16 @@ Avoid using the 'following' or 'preceeding' axes whenever possible, as these can ## UseConcatOnce -**Since:** 5.0 +**Since:** PMD 5.0 **Priority:** Medium (3) The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)". +``` +//node()[contains(substring-after(@select,'concat'),'concat')] +``` + **Example(s):** ``` From a4416a78e2c9948a5d85ac9c22aa172e6f4f9ee3 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Sat, 12 Aug 2017 11:55:40 +0200 Subject: [PATCH 22/24] [doc] add minimum language version, add property for tests --- .../net/sourceforge/pmd/docs/RuleDocGenerator.java | 6 ++++++ pmd-doc/src/test/resources/expected/sample.md | 14 ++++++++++++++ .../test/resources/rulesets/ruledoctest/sample.xml | 4 +++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java index b3a54e706..5eb70b5fa 100644 --- a/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java +++ b/pmd-doc/src/main/java/net/sourceforge/pmd/docs/RuleDocGenerator.java @@ -286,6 +286,12 @@ private void generateRuleSetIndex(Map<Language, List<RuleSet>> rulesets) throws lines.add("**Priority:** " + rule.getPriority() + " (" + rule.getPriority().getPriority() + ")"); lines.add(""); + if (rule.getMinimumLanguageVersion() != null) { + lines.add("**Minimum Language Version:** " + + rule.getLanguage().getName() + " " + rule.getMinimumLanguageVersion().getVersion()); + lines.add(""); + } + lines.add(StringUtils.stripToEmpty(rule.getDescription())); lines.add(""); diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index 2ff1e0527..89496308f 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -51,6 +51,12 @@ public class JumbledIncrementerRule1 { } ``` +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|sampleAdditionalProperty|the value|This is a additional property for tests| + ## MovedRule <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f;">Deprecated</span> @@ -92,6 +98,8 @@ public class JumbledIncrementerRule1 { **Priority:** Medium (3) +**Minimum Language Version:** Java 1.5 + Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule](https://github.com/pmd/pmd/blob/master/net/sourceforge/pmd/lang/java/rule/basic/OverrideBothEqualsAndHashcodeRule.java) @@ -155,3 +163,9 @@ public class JumbledIncrementerRule1 { } } ``` + +**This rule has the following properties:** + +|Name|Default Value|Description| +|----|-------------|-----------| +|sampleAdditionalProperty|the value|This is a additional property for tests| diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index f6148216e..b0139a985 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -13,7 +13,8 @@ Sample ruleset to test rule doc generation. since="0.4" message="Ensure you override both equals() and hashCode()" class="net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule" - externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#overridebothequalsandhashcode"> + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#overridebothequalsandhashcode" + minimumLanguageVersion="1.5"> <description> Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. </description> @@ -67,6 +68,7 @@ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even i ]]> </value> </property> + <property name="sampleAdditionalProperty" type="String" description="This is a additional property for tests" value="the value" /> </properties> <example> <![CDATA[ From ca9004b9f7e66de90f4fcb8a1eee4bf40adf0ea9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Sat, 12 Aug 2017 12:02:03 +0200 Subject: [PATCH 23/24] [doc] add test for simple markdown formatting in rule description --- pmd-doc/src/test/resources/expected/java.md | 2 +- pmd-doc/src/test/resources/expected/sample.md | 4 +++- pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pmd-doc/src/test/resources/expected/java.md b/pmd-doc/src/test/resources/expected/java.md index 474ee48a6..8ddbfc08d 100644 --- a/pmd-doc/src/test/resources/expected/java.md +++ b/pmd-doc/src/test/resources/expected/java.md @@ -11,5 +11,5 @@ List of rulesets and rules contained in each ruleset. * [DeprecatedSample](pmd_rules_java_sample.html#deprecatedsample): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> Just some description of a deprecated rule. * [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. * [MovedRule](pmd_rules_java_sample.html#movedrule): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> The rule has been moved to another ruleset. Use instead [JumbledIncrementer](pmd_rules_java_basic.html#jumbledincrementer). -* [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or ov... +* [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both 'public boolean Object.equals(Object other)', and 'public int Object.hashCode()', o... * [RenamedRule](pmd_rules_java_sample.html#renamedrule): <span style="border-radius: 0.25em; color: #fff; padding: 0.2em 0.6em 0.3em; display: inline; background-color: #d9534f; font-size: 75%;">Deprecated</span> The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index 89496308f..72a9d3cf9 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -100,7 +100,9 @@ public class JumbledIncrementerRule1 { **Minimum Language Version:** Java 1.5 -Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. +Override both `public boolean Object.equals(Object other)`, and `public int Object.hashCode()`, or override neither. +Even if you are inheriting a `hashCode()` from a parent class, consider implementing hashCode and explicitly +delegating to your superclass. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.java.rule.basic.OverrideBothEqualsAndHashcodeRule](https://github.com/pmd/pmd/blob/master/net/sourceforge/pmd/lang/java/rule/basic/OverrideBothEqualsAndHashcodeRule.java) diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index b0139a985..2f3b5c876 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -16,7 +16,9 @@ Sample ruleset to test rule doc generation. externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_sample.html#overridebothequalsandhashcode" minimumLanguageVersion="1.5"> <description> -Override both public boolean Object.equals(Object other), and public int Object.hashCode(), or override neither. Even if you are inheriting a hashCode() from a parent class, consider implementing hashCode and explicitly delegating to your superclass. +Override both `public boolean Object.equals(Object other)`, and `public int Object.hashCode()`, or override neither. +Even if you are inheriting a `hashCode()` from a parent class, consider implementing hashCode and explicitly +delegating to your superclass. </description> <priority>3</priority> <example> From da4272dc7477c74dff1dc0c5ca3137261089cd44 Mon Sep 17 00:00:00 2001 From: Andreas Dangel <adangel@users.sourceforge.net> Date: Sat, 12 Aug 2017 12:08:17 +0200 Subject: [PATCH 24/24] [doc] update generated documentation --- docs/pages/pmd/rules/java/clone.md | 2 ++ docs/pages/pmd/rules/java/design.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/pages/pmd/rules/java/clone.md b/docs/pages/pmd/rules/java/clone.md index 0cabfe576..772bf5d4b 100644 --- a/docs/pages/pmd/rules/java/clone.md +++ b/docs/pages/pmd/rules/java/clone.md @@ -83,6 +83,8 @@ public class MyClass { **Priority:** Medium (3) +**Minimum Language Version:** Java 1.5 + If a class implements cloneable the return type of the method clone() must be the class name. That way, the caller of the clone method doesn't need to cast the returned clone to the correct type. diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index b172fe2cf..7f26c79c6 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -1756,6 +1756,8 @@ public class MaybeAUtility { **Priority:** Medium Low (4) +**Minimum Language Version:** Java 1.5 + Java 5 introduced the varargs parameter declaration for methods and constructors. This syntactic sugar provides flexibility for users of these methods and constructors, allowing them to avoid having to deal with the creation of an array.