diff --git a/.travis-toolchains.xml b/.travis-toolchains.xml deleted file mode 100644 index caba9380c7..0000000000 --- a/.travis-toolchains.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - jdk - - 1.6 - - - /usr/lib/jvm/java-6-openjdk-amd64 - - - - jdk - - 1.7 - - - /usr/lib/jvm/java-7-openjdk-amd64 - - - - jdk - - 1.8 - - - /usr/lib/jvm/java-8-oracle - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index caa0a80e3b..f1a33c1699 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,6 @@ deploy: file: - pmd-dist/target/pmd-*.zip - target/pmd-doc-*.zip - # TODO : This won't copy the changelog to GitHub skip_cleanup: true on: tags: true @@ -54,7 +53,7 @@ env: - secure: "mmHRnK/8CHfgtwaTN3MgjFD1R8EVQhIb/a0Aag3gPaHWW52Ex6xWG7GsF4kRcdzHdIdrQxHZTiDa2oVMWbnQ16CAu4dZJadwTxhBW4JmE1tsi2C6i+uwMBPvnKBXHwt+QOAqNB0L/ByYwWLkucSLoyRs6qU0i7sJ3ZC/EPCuLI8VfBlFUVegSbp2WmclmFnxOi5MKr15Zwd8BGgyWUsvd1OHxhvO3Xr/ZPO4R+1kIgyojloTMu6oGM/shYgsrUXgmI/WvZRTq+25SRCjUmATJtuDXXgVeJtYabi/+Zju5Z7K06oaKvFYM+BgZWPmGQkVCxKVjSlug0rx6+qgRKIf/B/cPxmQDS0ZZVDmDcbxeibBL9JhRqIDwDb0XS9t1qBXvIJ5E4ZmdX/XuvLCnC4xJptu/vHyKl1wbRM3dcXEBk8J0knJc4JvY2yupF3LS32sfEHftLwzr63U3/0dOQvsCSJRBy5zgI8ieABUZAeZmmaQ6RCGOTEYrGO2G4CCF2uVq4YdrCOsfmrb0DzH8llNMkXKzXlITRvmkuBlTRRKxGnPzS3vf0iicdAkmTiU5u7lArFFc7IKcW4ypO+RKDTUpq74K+UZBI9eBjV7Po368EO8epJ5aIx32a2kyS/hYWkS/dZh7I0fNZa2qBUceZO/KZGRjH4dQFW9t0J9Q7LLXJY=" - secure: "geOU/7VR83KYTOCR5XkgFqnHJEnXeB6hNDE7UFcN4ZsL9uVLhxlDVWV3ujJ87nyBzggG1KfSnUx11UwOQrbBl0K6sEXo/B2q5ytOsWoSLi7+0qm/uhhw/DTBOq57p8TIDKFM7rDhO7uajSn7Y86LeZkh9wIs5265Fh1yhCkiPbczDUMsX4P0GGg2qgkIKSBw4DZf6sPDc4xjJq/4/cLnjXo/K0ZYAIoSLqDfe1gmkzMtQlad+1t8Lwv/gOJ4BNRF4a5aEvGF6kbFovFoeFWCQTKlkn6VJtY+BETGKW2RH9efGeMs7JbBbNm+nnpoNsbJ0gdmGlhSbWT8enIm72/P0ThTBJWVcLJ30tUd0UeYD9C49wbJ3RHSxsoUKP9YhHJ+XKNx+8irkJ8LPCkNMQEFE153gEVvU7tCgah9Uq6laYZv9cQE0dWzNt3//Ymls8BzY38Ha4PbrIIJqEuWwnAX6ZgTgzVtXx1AJjkDFG9KFKPhN7NfNMbh7rn5C84a1h5zrIydm+6RcIBC+xTLDEiN7djiquf3PcNtyGLcO8dNN4Uv8iU0Jw8ch3+w0PJO53v5py+IS1V8pwwYaYF2iVPOoziS0tP8MsgYVGwpTZhvz3v8x0ge8r6KJE4zdvoPtCRNr2Oo3sJGYqkt86Hu6agKFiljP5AgJNx7iQD5GQn6J3w=" - secure: "gqyPF3d75JuwZptnQQQKO6rGUILXGO09y9dZhShdX8qq5Mexa2ISk77Y/b0yyAdhJMgEglls5cWlbHkwCAB0i4yL25RE5CtQUe4er+CIKwBIs0M56ghbcOwWAFB/cXeyyWmXDHBVnVUeKm7IJ34txsEclnMzQSR/DInSzsCFMUQok8HEaWZNssMjyRgo6goKGdG5vNWGfLLY7mKGMe/6PpYJD0G8k+Na08aX06ZWph38He8O3imUAngoQrxiSp0UYmnHDkigbV7S2LdZOsj7kMxkiyigzK/P1eygHVbFAhohLroaqS9B4CBK7QeOyup2vxVKqJVzFwOCylD0786CImvaG2ZYMtvJkapvaEE0mdMlyYpHgdIkmHZu28aMW7hXEhxHyBAxKuPcj5eGCGziO+ztCvfYIA9CGs1uA4KLrED7SahvB0oXnt3KTFdRc857cWcpp2NmRKihLzVdgHlmT8zcYaec3zP1VdMoa2bmLHoaZtAwvMTcAG56FcET1p7f9v+uiU88ZeptEjTJfpAWlq34tpwZXNyIQi5IROocSHM+PKTgLAsAMP5klGascr8E0sEzREl7tg8hqEwXKym/sVKyT+HMptA3UZcrZZhm07/cmQ0pUVvbV9QDb0MzU3O2wF7vT3U7R7Fb1u0LxMjblPyEazTp8ldabVRJREwlsDc=" - - secure: "hFcdJSNyKL32geeIW+EbevwyPh4EK/KpaBIB780G4OPGjPUAe2y1VlvdPmljZM7HMb28l5Xf58LLdZdodtXAQbIvWYuP3A+EBxmIlPibb1D6AZqVYzY4ZB9sJGMDcTwzfIYrNZOBI9v34t8qZxHMfUm3XweHGsDwmyc18PmHAgG8m/0rwlIjtVlmEm+fFrvVHRXP1Jz3aX0RmTvrhc9/koZvpqztylIsqy9rlSX2OxoksDx825QfkE+YfbqS/OmAgqtw55r4H385cQJS97Yzc3X2dA8BKfPus7ng+lRxL9sYxwqjvDJzOeBqhf62BircPeymlWc+Hc53gNirW2MG4vHY/zASvZDjg9Hr2sEUODY8u8i7EvfYfX+hNPXZNtWo8fHO5UviCbc16IMrADN497Y54cKvAtyD/2H3aFWg8ei96GpxOaL6W+l5gtlgNC1b9wPE3+pDloLc4TMbvvlSDPKGWgSgqv4haRJ81oIJK+KEvWhbX5Sn3l5QTM33/rn4KUEFqhGNpUxGrvCQOn5sO7A2wnk8JMlrcRZKBpk+wfEzeTEAqZ6Vt7pmceEpcs/NdJCsRjAOmlCdjLVHtrF9zGpBelAMzbIeKLMsTtR3PbpediWHkNwLaMCAEZPIPKeML6TXoPy/nlBpkK20rTbHRHhumFKACB3F3HCWm8v/SIU=" + - secure: "JIhuqaI0i+zvuqqXiQBHpuKr7AQ8jfk6Gbr8Qgiq4yJtdEWXZGxnAT9BmlbjkgT7ABXvLgxf2CIdUOMo1yYfBlxQL/y5+e89jaVpYF3tvNAzYQ1e12VzQRsd/jDb7qvm7tw3rDHEn3dSEot7Q6KbPcL6WzWJINVMCCmOgvq9gKHgE6Y5q5EgZ5rxiXyuO27ndzcbxaor4PIaiSzHO9+AJQ7p2zDLP+kG4nKVTBX0l9VoKiYFhIpIhpbigi3jyLDMDRiWpwTWZC6P8/RXfZg/lc5ADOuM2DM8oXPpZuqOa/g31LWQOSCuEnQ1G16vbLgipSPpgAc7jYWD5cywhG9dLkiKaZDh5x0meLM2RoAgz6eAnQfTTqJ68OM9o9yXjubEedsNpNRAr9/DXMd+fbh10W2vbvL5HCNB3lic3anehhR9le7PLuEKxg654wXt3KM2PZGVWbotIyBK0CvGzqGkppvwT23QdDDqSdkWuGQIhGQ0xBOdYkwebycxP5wwPUmObG+mymQ1Be2BXvmghttsiJdKlt4CVSYOJUMus6kU32G95hdTgKblsX4J1Of2i1nYsjyMKh3k945tqXwQrIsxOOQug0oIkz24zlLaOaQcorWtJ6Y1HPaZKpVIFUEF0y8Uq/O4oB2bOYC6WDUQfpj7nRG6xbi+BeBS84m1ttCEk4g=" # Secure Keys, that need to be set for snapshot builds diff --git a/.travis/release.sh b/.travis/release.sh index 9db720c79d..a3e6606d9a 100644 --- a/.travis/release.sh +++ b/.travis/release.sh @@ -14,7 +14,7 @@ curl -H "Accept: application/json" -X PUT -d "default=windows&default=mac&defaul # Assumes, the release has already been created by travis github releases provider RELEASE_ID=$(curl -s -H "Authorization: token ${GITHUB_OAUTH_TOKEN}" https://api.github.com/repos/pmd/pmd/releases/tags/pmd_releases/${RELEASE_VERSION}|jq ".id") RELEASE_NAME="PMD ${RELEASE_VERSION} ($(date -u +%d-%B-%Y))" -RELEASE_BODY=$(cat src/site/markdown/overview/changelog.md) +RELEASE_BODY=$(tail -n +3 src/site/markdown/overview/changelog.md) # skips the first 2 lines - the heading 'PMD Release Notes' RELEASE_BODY="${RELEASE_BODY//$'\\'/\\\\}" RELEASE_BODY="${RELEASE_BODY//$'\r'/}" RELEASE_BODY="${RELEASE_BODY//$'\n'/\\r\\n}" @@ -26,7 +26,9 @@ cat > release-edit-request.json < .git/info/sparse-checkout + git pull --depth=1 origin master + rsync -a ../target/pmd-doc-${RELEASE_VERSION}/ pmd-${RELEASE_VERSION}/ + git add pmd-${RELEASE_VERSION} + git commit -q -m "Added pmd-${RELEASE_VERSION}" + git rm -qr latest + cp -a pmd-${RELEASE_VERSION} latest + git add latest + git commit -q -m "Copying pmd-${RELEASE_VERSION} to latest" + git push origin master ) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRule.java index 37f5f6ff48..ea86f815fe 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/ApexXPathRule.java @@ -9,11 +9,15 @@ import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.apex.ApexLanguageModule; import net.sourceforge.pmd.lang.apex.ApexParserOptions; import net.sourceforge.pmd.lang.rule.XPathRule; +import net.sourceforge.pmd.renderers.CodeClimateRule; -public class ApexXPathRule extends XPathRule { +public class ApexXPathRule extends XPathRule implements CodeClimateRule { public ApexXPathRule() { super.setLanguage(LanguageRegistry.getLanguage(ApexLanguageModule.NAME)); + definePropertyDescriptor(CODECLIMATE_CATEGORIES); + definePropertyDescriptor(CODECLIMATE_REMEDIATION_MULTIPLIER); + definePropertyDescriptor(CODECLIMATE_BLOCK_HIGHLIGHTING); } @Override diff --git a/pmd-apex/src/main/resources/rulesets/apex/braces.xml b/pmd-apex/src/main/resources/rulesets/apex/braces.xml new file mode 100644 index 0000000000..64a126c35c --- /dev/null +++ b/pmd-apex/src/main/resources/rulesets/apex/braces.xml @@ -0,0 +1,155 @@ + + + + +The Braces ruleset contains rules regarding the use and placement of braces. + + + + +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. + + 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. + + 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. + + 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. + + 3 + + + + + + + + + + + + + diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index 26d6c470cd..768ecd8994 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -1,6 +1,8 @@ Default ruleset used by the Code Climate Engine for Salesforce.com Apex + + 3 @@ -91,6 +93,8 @@ + + 3 @@ -127,6 +131,7 @@ + 3 @@ -163,6 +168,7 @@ + 3 @@ -181,6 +187,7 @@ + 3 @@ -280,6 +287,41 @@ - - + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + \ No newline at end of file diff --git a/pmd-apex/src/main/resources/rulesets/apex/rulesets.properties b/pmd-apex/src/main/resources/rulesets/apex/rulesets.properties index 5ed77f7318..fe0f146565 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/rulesets.properties +++ b/pmd-apex/src/main/resources/rulesets/apex/rulesets.properties @@ -2,4 +2,4 @@ # BSD-style license; for more info see http://pmd.sourceforge.net/license.html # -rulesets.filenames=rulesets/apex/complexity.xml,rulesets/apex/performance.xml,rulesets/apex/style.xml,rulesets/apex/apexunit.xml,rulesets/apex/security.xml +rulesets.filenames=rulesets/apex/complexity.xml,rulesets/apex/performance.xml,rulesets/apex/style.xml,rulesets/apex/apexunit.xml,rulesets/apex/security.xml,rulesets/apex/braces.xml diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/braces/BracesRulesTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/braces/BracesRulesTest.java new file mode 100644 index 0000000000..09cbb1cc89 --- /dev/null +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/braces/BracesRulesTest.java @@ -0,0 +1,20 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule.braces; + +import net.sourceforge.pmd.testframework.SimpleAggregatorTst; + +public class BracesRulesTest extends SimpleAggregatorTst { + + private static final String RULESET = "apex-braces"; + + @Override + public void setUp() { + addRule(RULESET, "ForLoopsMustUseBraces"); + addRule(RULESET, "IfElseStmtsMustUseBraces"); + addRule(RULESET, "IfStmtsMustUseBraces"); + addRule(RULESET, "WhileLoopsMustUseBraces"); + } +} diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/ForLoopsMustUseBraces.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/ForLoopsMustUseBraces.xml new file mode 100644 index 0000000000..8354c4c2b7 --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/ForLoopsMustUseBraces.xml @@ -0,0 +1,88 @@ + + + + + 1 + + + + + 0 + + + + + 1 + + + + + 1 + + + + + 1 + + + + + 1 + + + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfElseStmtsMustUseBraces.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfElseStmtsMustUseBraces.xml new file mode 100644 index 0000000000..707358ff17 --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfElseStmtsMustUseBraces.xml @@ -0,0 +1,125 @@ + + + + + 1 + + + + + 0 + + + + + 2 + + + + + 1 + + + + + 0 + + + + + 1 + + + + + 2 + + + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfStmtsMustUseBraces.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfStmtsMustUseBraces.xml new file mode 100644 index 0000000000..323fdbb950 --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/IfStmtsMustUseBraces.xml @@ -0,0 +1,46 @@ + + + + + 1 + + + + + 0 + + + + + 1 + + + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/WhileLoopsMustUseBraces.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/WhileLoopsMustUseBraces.xml new file mode 100644 index 0000000000..a84ff150be --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/braces/xml/WhileLoopsMustUseBraces.xml @@ -0,0 +1,34 @@ + + + + + 1 + + + + + 0 + + + diff --git a/pmd-core/src/main/resources/rulesets/releases/560.xml b/pmd-core/src/main/resources/rulesets/releases/560.xml new file mode 100644 index 0000000000..bb459e8df4 --- /dev/null +++ b/pmd-core/src/main/resources/rulesets/releases/560.xml @@ -0,0 +1,17 @@ + + + + +This ruleset contains links to rules that are new in PMD v5.6.0 + + + + + + + + + diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java index 7cfd88e2b0..a42b3b6ac0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTClassOrInterfaceBody.java @@ -15,9 +15,17 @@ public class ASTClassOrInterfaceBody extends AbstractJavaNode { } /** - * Accept the visitor. * + * Accept the visitor. */ public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + public boolean isAnonymousInnerClass() { + return jjtGetParent() instanceof ASTAllocationExpression; + } + + public boolean isEnumChild() { + return jjtGetParent() instanceof ASTEnumConstant; + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java index bcd66c3760..ed9c6cf73f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java @@ -29,7 +29,7 @@ public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements D @Override public boolean isPublic() { - if (isInterfaceMember()) { + if (isAnnotationMember() || isInterfaceMember()) { return true; } return super.isPublic(); @@ -41,7 +41,7 @@ public class ASTFieldDeclaration extends AbstractJavaAccessTypeNode implements D @Override public boolean isStatic() { - if (isInterfaceMember()) { + if (isAnnotationMember() || isInterfaceMember()) { return true; } return super.isStatic(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorMethodGenerationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorMethodGenerationRule.java index 43a86d19c9..b982a91784 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorMethodGenerationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/design/AccessorMethodGenerationRule.java @@ -7,10 +7,7 @@ package net.sourceforge.pmd.lang.java.rule.design; import java.util.List; import java.util.Map; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode; @@ -60,13 +57,10 @@ public class AccessorMethodGenerationRule extends AbstractJavaRule { } for (final NameOccurrence no : occurrences) { - Node n = no.getLocation(); - while (n != null && !(n instanceof ASTClassOrInterfaceDeclaration) && !(n instanceof ASTEnumDeclaration)) { - n = n.jjtGetParent(); - } + ClassScope usedAtScope = no.getLocation().getScope().getEnclosingScope(ClassScope.class); // Are we within the same class that defines the field / method? - if (!n.getImage().equals(classScope.getClassName())) { + if (!classScope.equals(usedAtScope)) { addViolation(data, no.getLocation()); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java index 1797ae62f8..7d3d570022 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinder.java @@ -12,7 +12,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTCatchStatement; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBodyDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; @@ -135,7 +135,7 @@ public class ScopeAndDeclarationFinder extends JavaParserVisitorAdapter { ClassNameDeclaration classNameDeclaration = new ClassNameDeclaration(node); s.addDeclaration(classNameDeclaration); - if (node instanceof ASTClassOrInterfaceBodyDeclaration) { + if (node instanceof ASTClassOrInterfaceBody) { addScope(new ClassScope(classNameDeclaration), node); } else { addScope(new ClassScope(node.getImage(), classNameDeclaration), node); @@ -195,7 +195,7 @@ public class ScopeAndDeclarationFinder extends JavaParserVisitorAdapter { } @Override - public Object visit(ASTClassOrInterfaceBodyDeclaration node, Object data) { + public Object visit(ASTClassOrInterfaceBody node, Object data) { if (node.isAnonymousInnerClass() || node.isEnumChild()) { createClassScope(node); cont(node); diff --git a/pmd-java/src/main/resources/rulesets/java/design.xml b/pmd-java/src/main/resources/rulesets/java/design.xml index 9b9b5ce96a..f8bd52d7d4 100644 --- a/pmd-java/src/main/resources/rulesets/java/design.xml +++ b/pmd-java/src/main/resources/rulesets/java/design.xml @@ -292,7 +292,6 @@ in each object at runtime. diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java index 7119e5a6f2..09f57978fc 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/symboltable/ScopeAndDeclarationFinderTest.java @@ -10,9 +10,12 @@ import java.util.Set; import org.junit.Assert; import org.junit.Test; +import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.java.JavaLanguageModule; +import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; +import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator; import net.sourceforge.pmd.lang.symboltable.NameDeclaration; public class ScopeAndDeclarationFinderTest extends STBBaseTst { @@ -44,4 +47,28 @@ public class ScopeAndDeclarationFinderTest extends STBBaseTst { Assert.assertEquals(1, scope.getVariableDeclarations().get(decl).size()); } } + + @Test + public void testAnnonInnerClassScoping() { + String source = "public class Foo {" + PMD.EOL + + " public static final Creator CREATOR = new Creator() {" + PMD.EOL + + " @Override public Foo createFromParcel(Parcel source) {" + PMD.EOL + + " return new Foo();" + PMD.EOL + + " }" + PMD.EOL + + " @Override public Foo[] newArray(int size) {" + PMD.EOL + + " return new Foo[size];" + PMD.EOL + + " }" + PMD.EOL + + " };" + PMD.EOL + + "}" + PMD.EOL; + parseCode(source, LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("1.6")); + + ClassScope cs = (ClassScope) acu.getFirstDescendantOfType(ASTClassOrInterfaceDeclaration.class).getScope(); + Assert.assertEquals(1, cs.getClassDeclarations().size()); // There should be 1 anonymous class + + List methods = acu.findDescendantsOfType(ASTMethodDeclarator.class); + Assert.assertEquals(2, methods.size()); + ClassScope scope1 = methods.get(0).getScope().getEnclosingScope(ClassScope.class); + ClassScope scope2 = methods.get(1).getScope().getEnclosingScope(ClassScope.class); + Assert.assertSame(scope1, scope2); + } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml index 97c3e6cf7f..558bf751f7 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/AccessorMethodGeneration.xml @@ -163,6 +163,33 @@ public class Foo { /* package */ void outerPackage() { } +} + ]]> + + + + 0 + CREATOR = new Creator() { + @Override + public Foo createFromParcel(Parcel source) { + return new Foo(source.readString(), + getBooleanForInt(source.readInt()), + source.readLong()); + } + + @Override + public Foo[] newArray(int size) { + return new Foo[size]; + } + + private boolean getBooleanForInt(int value) { + return value == 1; + } + }; } ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/FinalFieldCouldBeStatic.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/FinalFieldCouldBeStatic.xml index d61ff0a8e0..f7b3bd0fde 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/FinalFieldCouldBeStatic.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/FinalFieldCouldBeStatic.xml @@ -90,6 +90,15 @@ public class FinalFieldCouldBeStaticTest { interface Test { byte[] bar(); +} + ]]> + + + #275 - False positive in @interface + 0 + diff --git a/pmd-visualforce/src/main/resources/rulesets/vf/security.xml b/pmd-visualforce/src/main/resources/rulesets/vf/security.xml index 6a4bf5e7e7..437b159017 100644 --- a/pmd-visualforce/src/main/resources/rulesets/vf/security.xml +++ b/pmd-visualforce/src/main/resources/rulesets/vf/security.xml @@ -6,8 +6,9 @@ Rules concerning basic VF guidelines. - diff --git a/pom.xml b/pom.xml index ceb5e95050..4fb3b03b9f 100644 --- a/pom.xml +++ b/pom.xml @@ -447,6 +447,9 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.apache.maven.plugins maven-javadoc-plugin ${javadoc.plugin.version} + + true + org.apache.maven.plugins @@ -466,12 +469,12 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code net.sourceforge.pmd pmd-core - 5.5.2 + 5.5.4 net.sourceforge.pmd pmd-java - 5.5.2 + 5.5.4 diff --git a/src/site/markdown/customizing/pmd-release-process.md b/src/site/markdown/customizing/pmd-release-process.md index c687bcef1f..c2ee60e77f 100644 --- a/src/site/markdown/customizing/pmd-release-process.md +++ b/src/site/markdown/customizing/pmd-release-process.md @@ -7,6 +7,13 @@ This page describes the current status of the release process. +Since versions 5.4.5 / 5.5.4 there is an automated release process using [travis-ci](https://travis-ci.org) +in place. However, there are still a few steps, that need manual examination. + +Note: You can find a small shell script in the root of the repo: `do-release.sh`. This script guides you +through the release process. + + ## Preparations Make sure code is up to date and everything is committed and pushed with git: @@ -15,207 +22,171 @@ Make sure code is up to date and everything is committed and pushed with git: $ git pull $ git status -**Checklist for release preparation:** - -* Ensure all the new rules are listed in a the proper file: - `pmd-core/src/main/resources/rulesets/releases/.xml` file. -* Update version/release info in **src/site/markdown/changelog.md**. -* Update **../pmd.github.io/latest/index.html** of our website, to redirect to the new version -* Update **../pmd.github.io/index.html** to mention the new release - $ mvn clean install +### The Release Notes -Unzip and test manually (just to be on the safe side of the road): +At a very minimum, the current date must be noted in the release notes. Also, the version +must be adjusted. E.g. by removing "-SNAPSHOT". + +You can find the release notes here: `src/site/markdown/overview/changelog.md`. + +The release notes usual mention any new rules that have been added since the last release. +Please double check the file `pmd-core/src/main/resources/rulesets/releases/.xml`, so +that all new rules are listed. + +Check in all (version) changes to branch master or any other branch, from which the release takes place: + + $ git commit -a -m "Prepare pmd release " + $ git push + + +### The Homepage + +The github repo `pmd.github.io` hosts the homepage for [https://pmd.github.io](https://pmd.github.io). +The `index.html` page needes to be updated to display the new release. The new release is mentioned + +* on the start page +* in the announcements +* and in the previous releases section - cd pmd-dist/target; unzip pmd-bin-.zip; cd pmd-bin- - ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f xml -R rulesets/java/unusedcode.xml - ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f xml -R java-unusedcode - ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f html -R rulesets/java/unusedcode.xml - cd ..; cd ../.. Check in all (version) changes to branch master: $ git commit -a -m "Prepare pmd release " - -## Release Branch - -Let's have maven create a release branch for us (note - this is of course not -needed if you are already on a release/maintenance branch). Maven will automatically -increase the version in branch master. - - $ mvn release:branch -DbranchName=pmd/.x - -In case you create a alpha/preview release and you want to stay with the current -version in master, use these additional properties: - - $ mvn -DupdateBranchVersions=true -DupdateWorkingCopyVersions=false ... - -Note: The property pushChanges is set to false, so that we can manually -push all changes done during the release at the end, when we are sure, -that everything is fine. - -## Create a release - -Now checkout the created branch. - - $ git checkout pmd/.x - -Now let maven create a release tag. + $ git push - $ mvn release:clean - $ mvn release:prepare -Note: For the tag/label name we currently use this naming pattern: -pmd_releases/<major-version>.<minor-version>.<micro-version> +## Creating the release -The next command will checkout PMD from the tag just created and will build -and deploy it to sonatype OSS repositories: +The release is created using the **maven-release-plugin**. This plugin changes the version by basically +removing the "-SNAPSHOT" suffix, builds the changed project locally, commits the version change, creates +a new tag from this commit, changes the version of the project to the next snapshot, commits this change +and pushes everything. - $ mvn release:perform +`RELEASE_VERSION` is the version of the release. It is reused for the tag. `DEVELOPMENT_VERSION` is the +next snapshot version after the release. -### Push your local changes - -If everything is fine, you can push your local changes. - - $ git push origin master - $ git push origin pmd/.x - $ git push origin tag pmd_releases/ - -### Rollback - -Note: If you see a bug and fix it, you can rollback the release -(see the [maven release plugin documentation](http://maven.apache.org/plugins/maven-release-plugin/examples/rollback-release.html)): - - $ mvn release:rollback - -You probably need to delete the release tag manually using the following command (and then -start again with release:clean release:prepare): - - $ git tag -d pmd_releases/ - -## Publish maven artifacts - -Finally, in order to publish the release to Maven central, -you need to release PMD via Sonatype Nexus: - -* Login to -* Go to Staging Repositories page -* Select a staging repository -* Click the close button -* Now you can download the artifacts again and verify they are working. -* Once you are sure they are working, click "Release" and the artifacts are - eventually available through - [maven central](http://repo.maven.apache.org/maven2/net/sourceforge/pmd/pmd/). - -## Create and publish the site / documentation - -You can reuse the cleanly checked out local repository from maven-release-plugin. - - $ cd target/checkout/ - $ mvn site site:stage - -* Before you upload the zip files, unzip and test once (just to be on the safe side of the road): - - $ cd pmd-dist/target; unzip pmd-bin-.zip; cd pmd-bin- - $ ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f xml -R rulesets/java/unusedcode.xml - $ ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f xml -R java-unusedcode - $ ./bin/run.sh pmd -d ../../../pmd-java/src/main/java -language java -f html -R rulesets/java/unusedcode.xml - $ cd ..; cd ../.. - -* While the site will be deployed to github, it's still usefull, to have it downloadable at once: - - $ cd target - $ mv staging pmd-doc- - $ zip -r pmd-doc-.zip pmd-doc-/ - $ cd .. - -* Add the site to the pmd.github.io repo: - - $ rsync -avhP target/pmd-doc-/ ../../../pmd.github.io/pmd-/ - $ (cd ../../../pmd.github.io; git add pmd-; git commit -m "Added pmd-") - -* Upload the zip-files to sourceforge's file section: - - $ rsync -avhP pmd-dist/target/pmd-*-.zip target/pmd-doc-.zip your_sf_login@web.sourceforge.net:/home/frs/project/pmd/pmd// - $ rsync -avhP src/site/markdown/overview/changelog.md your_sf_login@web.sourceforge.net:/home/frs/project/pmd/pmd//ReadMe.md - -* Verify the MD5 sums on [Files](https://sourceforge.net/projects/pmd/files/pmd/) and locally: - - $ md5sum pmd-dist/target/pmd-*-.zip target/pmd-doc-.zip - -* Go to [Files](https://sourceforge.net/projects/pmd/files/pmd/), to folder "pmd/<version>", - and make the new binary pmd zip file the default download for all platforms. - -## Push the repos - -In case of releasing from master: - - $ git push origin master; git push origin tag pmd_releases/ - -In case of releasing from a release branch: - - $ git push origin pmd/.x; git push origin tag pmd_releases/ - -## Create a new release on github - -Go to - -* Select the just pushed tag: "pmd_releases/<version>" -* Set the title: "PMD <version> (DD-MMMM-YYYY)" -* Copy/Paste the changelog.md file -* Upload the 3 zip files (pmd-<version>-{src,bin,doc}.zip). -* Publish the release - -## Submit a news on SF - -* Submit news to SF on the [PMD Project News](https://sourceforge.net/p/pmd/news/) page. You can use - the following template: - - PMD released - - * minor version with lots of bug fixes - * Changelog: https://pmd.github.io/pmd-/overview/changelog.html - * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F - * Fixed Bugs: https://sourceforge.net/p/pmd/bugs/milestone/PMD-/ - * Documentation: https://pmd.github.io/pmd-/ + mvn -B release:clean release:prepare \ + -Dtag=pmd_releases/${RELEASE_VERSION} \ + -DreleaseVersion=${RELEASE_VERSION} \ + -DdevelopmentVersion=${DEVELOPMENT_VERSION} -## Prepare the next version +Once the maven plugin has pushed the tag, travis-ci will start and build a new version from this tag. Since +it is a tag build and a released version build, travis-ci will do a couple of additional stuff: -### Create new milestone +* Deploy and release the build to maven central, so that it can be downloaded from + . This is done automatically, if + all unit tests pass on travis-ci. The plugin [nexus-staging-maven-plugin](https://github.com/sonatype/nexus-maven-plugins/tree/master/staging/maven-plugin) is used for that. +* Upload the new binaries to github releases under . It also uploads + the release notes. +* Upload the new binaries additionally to sourceforge, so that they can be downloaded from + , including the release notes. The new binaries are + selected as the new default downloads for PMD. +* Add the documentation of the new release to a subfolder on , also make + this folder available as `latest`. -Under close the milestone "PMD-<version>" -and create a new milestone for the next version (PMD-<version+1>). -### Update changelog +## After the release -* Move version/releaseinfo from **src/site/markdown/overview/changelog.md** to **src/site/markdown/overview/changelog-old.md**. +The release on travis currently takes about 30 minutes. Once this is done, you can spread the news: + +### Submit a news on SF + +Submit news to SF on the [PMD Project News](https://sourceforge.net/p/pmd/news/) page. You can use +the following template: + + PMD released + + * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F + * Documentation: https://pmd.github.io/pmd-/ + + And Copy-Paste the release notes + +### Write an email to the mailing list + + To: PMD Developers List + Subject: [ANNOUNCE] PMD released + + + * Downloads: https://github.com/pmd/pmd/releases/tag/pmd_releases%2F + * Documentation: https://pmd.github.io/pmd-/ + + And Copy-Paste the release notes + + +## Prepare the next release + +### Prepare the new release notes + +* Move version/release info from **src/site/markdown/overview/changelog.md** to **src/site/markdown/overview/changelog-old.md**. * Update version/release info in **src/site/markdown/overview/changelog.md**. Use the following template: - # Changelog - - ## ????? - ${DEVELOPMENT_VERSION} - - **New Supported Languages:** - - **Feature Request and Improvements:** - - **New/Modified/Deprecated Rules:** - - **Pull Requests:** - - **Bugfixes:** - - **API Changes:** -* Update pmd-java8/pom.xml - the version is probably wrong. - Set it to the parent's=next development version. -* If you released from a release-branch, now merge the branch back into master. -* Commit and push + # PMD Release Notes + + ## ????? - ${DEVELOPMENT_VERSION} + + The PMD team is pleased to announce PMD ${DEVELOPMENT_VERSION%-SNAPSHOT}. + + This is a bug fixing release. + + ### Table Of Contents + + * [New and noteworthy](#New_and_noteworthy) + * [Fixed Issues](#Fixed_Issues) + * [API Changes](#API_Changes) + * [External Contributions](#External_Contributions) + + ### New and noteworthy + + ### Fixed Issues + + ### API Changes + + ### External Contributions - $ git commit -m "Prepare next development version" - $ git push origin master +Commit and push + + $ git commit -m "Prepare next development version" + $ git push origin master +### Close / Create new milestones + +Manage the milestones under . +Maybe there are some milestones on sourceforge, too: . + + + +## Branches + +### Merging + +If the release was done on a maintenance branch, such as `pmd/5.4.x`, then this branch should be +merge into the next "higher" branches, such as `pmd/5.5.x` and `master`. + +This ensures, that all fixes done on the maintenance branch, finally end up in the other branches. +In theory, the fixes should already be there, but you never now. + + +### Multiple releases + +If releases from multiple branches are being done, the order matters. You should start from the "oldes" branch, +e.g. `pmd/5.4.x`, release from there. Then merge (see above) into the next branch, e.g. `pmd/5.5.x` and release +from there. Then merge into the `master` branch and release from there. This way, the last release done, becomes +automatically the latest release on and on sourceforge. + + +### (Optional) Create a new release branch + +At some point, it might be time for a new maintenance branch. Such a branch is usually created from +the `master` branch. Here are the steps: + +* Create a new branch: `git branch pmd/5.6.x master` +* Update the version in both the new branch and master, e.g. `mvn versions:set -Dversion=5.6.0-SNAPSHOT` + and `mvn versions:set -Dversion=5.7.0-SNAPSHOT`. +* Update the release notes on both the new branch and master + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 2a15715676..d25604235c 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -5,7 +5,7 @@ The PMD team is pleased to announce PMD 5.6.0. The most significant changes are on analysis performance, support for Salesforce's Visualforce language -a whole new **Apex Security Rule Set**. +a whole new **Apex Security Rule Set** and the new **Braces Rule Set for Apex**. We have added initial support for **incremental analysis**. The experimental feature allows PMD to cache analysis results between executions to speed up the analysis for all @@ -32,12 +32,13 @@ making it over 500X faster, and `PreserveStackTrace` which is now 7X faster. * [Incremental Analysis](#Incremental_Analysis) * [Visualforce Support](#Visualforce_support) * [Apex Security Rule Set](#Apex_Security_Rule_Set) + * [Apex Braces Rule Set](#Apex_Braces_Rule_Set) * [New Rules](#New_Rules) * [Modified Rules](#Modified_Rules) * [CPD Suppression](#CPD_Suppression) -* [Fixed Issues](#Fixed_Issues) -* [API Changes](#API_Changes) -* [External Contributions](#External_Contributions) +* [Fixed Issues](#Fixed_Issues) +* [API Changes](#API_Changes) +* [External Contributions](#External_Contributions) ### New and noteworthy @@ -229,6 +230,84 @@ attacks if unescaped. Makes sure that all values obtained from URL parameters are properly escaped / sanitized to avoid XSS attacks. +#### Apex Braces Rule Set + +The Braces Rule Set has been added and serves the same purpose as the Braces Rule Set from Java: +It checks the use and placement of braces around if-statements, for-loops and so on. + +##### IfStmtsMustUseBraces + +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. + +For instance, the following code shows the different. PMD would report on the not recommended approach: + +``` +if (foo) // not recommended + x++; + +if (foo) { // preferred approach + x++; +} +``` + +##### WhileLoopsMustUseBraces + +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. + +For instance, the following code shows the different. PMD would report on the not recommended approach: + +``` +while (true) // not recommended + x++; + +while (true) { // preferred approach + x++; +} +``` + +##### IfElseStmtsMustUseBraces + +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. + +For instance, the following code shows the different. PMD would report on the not recommended approach: + +``` +// this is not recommended +if (foo) + x = x+1; + else + x = x-1; + +// preferred approach +if (foo) { + x = x+1; +} else { + x = x-1; +} +``` + +##### ForLoopsMustUseBraces + +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. + +For instance, the following code shows the different. PMD would report on the not recommended approach: + +``` +for (int i = 0; i < 42; i++) // not recommended + foo(); + +for (int i = 0; i < 42; i++) { // preferred approach + foo(); +} +``` #### New Rules @@ -347,6 +426,8 @@ For example: * [#216](https://github.com/pmd/pmd/issues/216): \[java] \[doc] NonThreadSafeSingleton: Be more explicit as to why double checked locking is not recommended * [#219](https://github.com/pmd/pmd/issues/219): \[java] UnnecessaryLocalBeforeReturn: ClassCastException in switch case with local variable returned * [#240](https://github.com/pmd/pmd/issues/240): \[java] UnnecessaryLocalBeforeReturn: Enhance by checking usages + * [#274](https://github.com/pmd/pmd/issues/274): \[java] AccessorMethodGeneration: Method inside static inner class incorrectly reported + * [#275](https://github.com/pmd/pmd/issues/275): \[java] FinalFieldCouldBeStatic: Constant in @interface incorrectly reported as "could be made static" * java-imports * [#1546](https://sourceforge.net/p/pmd/bugs/1546/): \[java] UnnecessaryFullyQualifiedNameRule doesn't take into consideration conflict resolution * [#1547](https://sourceforge.net/p/pmd/bugs/1547/): \[java] UnusedImportRule - False Positive for only usage in Javadoc - {@link ClassName#CONSTANT} @@ -425,4 +506,5 @@ For example: * [#268](https://github.com/pmd/pmd/pull/268): \[apex] Support safe escaping via String method * [#273](https://github.com/pmd/pmd/pull/273): \[apex] Shade jackson on apex * [#280](https://github.com/pmd/pmd/pull/280): \[apex] Support for Aggregate Result in CRUD rules +* [#281](https://github.com/pmd/pmd/pull/281): \[apex] Add Braces Rule Set