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