diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 6dd6dde4cb..bfc40a3102 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1,4 +1,9 @@ /** + * Provide a better fix for CastExpression, getting rid of most hacks. + * Bug #257 + * + * Juan Martin Sotuyo Dodero 02/2017 + *==================================================================== * Allow local classes to carry more than one annotation. * Bug #208 * @@ -1558,7 +1563,7 @@ void ReferenceType(): void ClassOrInterfaceType(): { - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); Token t; } { @@ -1789,9 +1794,13 @@ void UnaryExpressionNotPlusMinus() #UnaryExpressionNotPlusMinus((jjtn000.getImag {} { ( "~" {jjtThis.setImage("~");} | "!" {jjtThis.setImage("!");} ) UnaryExpression() -| LOOKAHEAD( { getToken(1).kind == LPAREN && getToken(2).kind == IDENTIFIER && getToken(3).kind == RPAREN && getToken(4).kind == PLUS } ) PostfixExpression() -| LOOKAHEAD( CastExpression() ) CastExpression() -| LOOKAHEAD("(" Type() ")" "(") CastExpression() +/* + * This is really ugly... we are repeting the CastExpression lookahead and full expression... + * If we don't the lookahead within CastExpression is ignored, and it simply looks for the expression, + * meaning we can't be explicit as to what can be casted depending on the cast type (primitive or otherwhise) +*/ +| LOOKAHEAD("(" (Annotation())* PrimitiveType() ")") CastExpression() +| LOOKAHEAD("(" (Annotation())* Type() ( "&" ReferenceType() )* ")" UnaryExpressionNotPlusMinus()) CastExpression() | PostfixExpression() } @@ -1801,12 +1810,13 @@ void PostfixExpression() #PostfixExpression((jjtn000.getImage() != null)): PrimaryExpression() [ "++" {jjtThis.setImage("++");} | "--" {jjtThis.setImage("--");} ] } -void CastExpression() #CastExpression(>1): +void CastExpression() : {} { - LOOKAHEAD("(" (Annotation())* Type() ")") "(" (Annotation() {checkForBadTypeAnnotations();})* Type() ")" UnaryExpression() -| LOOKAHEAD("(" (Annotation())* Type() "&") "(" (Annotation() {checkForBadTypeAnnotations();})* Type() ( "&" {checkForBadIntersectionTypesInCasts(); jjtThis.setIntersectionTypes(true);} ReferenceType() )+ ")" UnaryExpressionNotPlusMinus() -| "(" (Annotation() {checkForBadTypeAnnotations();})* Type() ")" UnaryExpressionNotPlusMinus() + LOOKAHEAD( + "(" (Annotation())* PrimitiveType() ")" + ) "(" (Annotation() {checkForBadTypeAnnotations();})* Type() ")" UnaryExpression() +| "(" (Annotation() {checkForBadTypeAnnotations();})* Type() ( "&" {checkForBadIntersectionTypesInCasts(); jjtThis.setIntersectionTypes(true);} ReferenceType() )* ")" UnaryExpressionNotPlusMinus() } void PrimaryExpression() : @@ -2010,12 +2020,9 @@ void StatementExpression() : | PreDecrementExpression() | - LOOKAHEAD( PrimaryExpression() ("++" | "--") ) PostfixExpression() + LOOKAHEAD( PrimaryExpression() AssignmentOperator() ) PrimaryExpression() AssignmentOperator() Expression() | - PrimaryExpression() - [ - AssignmentOperator() Expression() - ] + PostfixExpression() } void SwitchStatement() : diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InsufficientStringBufferDeclarationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InsufficientStringBufferDeclarationRule.java index 08ada69c8c..79ff8c9c37 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InsufficientStringBufferDeclarationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/strings/InsufficientStringBufferDeclarationRule.java @@ -26,7 +26,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; -import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; @@ -204,7 +203,7 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRule { // but only if we are not inside a cast expression Node parentNode = literal.jjtGetParent().jjtGetParent().jjtGetParent(); if (parentNode instanceof ASTCastExpression - && parentNode.getFirstChildOfType(ASTType.class).getType() == char.class) { + && ((ASTCastExpression) parentNode).getType() == char.class) { anticipatedLength += 1; } else { // e.g. 0xdeadbeef -> will be converted to a diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedLocalVariableRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedLocalVariableRule.java index 38f0c9225e..c8a791f2e2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedLocalVariableRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/unusedcode/UnusedLocalVariableRule.java @@ -15,6 +15,10 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence; public class UnusedLocalVariableRule extends AbstractJavaRule { + public UnusedLocalVariableRule() { + addRuleChainVisit(ASTLocalVariableDeclaration.class); + } + public Object visit(ASTLocalVariableDeclaration decl, Object data) { for (int i = 0; i < decl.jjtGetNumChildren(); i++) { if (!(decl.jjtGetChild(i) instanceof ASTVariableDeclarator)) { @@ -34,9 +38,7 @@ public class UnusedLocalVariableRule extends AbstractJavaRule { private boolean actuallyUsed(List usages) { for (NameOccurrence occ : usages) { JavaNameOccurrence jocc = (JavaNameOccurrence) occ; - if (jocc.isOnLeftHandSide()) { - continue; - } else { + if (!jocc.isOnLeftHandSide()) { return true; } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java index 1057a107f3..b2e90f2f4d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ParserCornersTest.java @@ -157,6 +157,20 @@ public class ParserCornersTest extends ParserTst { String c = IOUtils.toString(this.getClass().getResourceAsStream("GitHubBug208.java")); parseJava15(c); } + + @Test + public void testGitHubBug257NonExistingCast() throws Exception { + String code = "public class Test {" + PMD.EOL + + " public static void main(String[] args) {" + PMD.EOL + + " double a = 4.0;" + PMD.EOL + + " double b = 2.0;" + PMD.EOL + + " double result = Math.sqrt((a) - b);" + PMD.EOL + + " System.out.println(result);" + PMD.EOL + + " }" + PMD.EOL + + "}"; + ASTCompilationUnit compilationUnit = parseJava15(code); + assertEquals("A cast was found when none expected", 0, compilationUnit.findDescendantsOfType(ASTCastExpression.class).size()); + } /** * This triggered bug #1484 UnusedLocalVariable - false positive - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedLocalVariable.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedLocalVariable.xml index 9f0d702ec6..6281eb38cf 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedLocalVariable.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/unusedcode/xml/UnusedLocalVariable.xml @@ -368,6 +368,21 @@ public class Test { System.out.println(list.size() + " (" + (notEmpty) + " not empty)"); } +} + ]]> + + + + #257 UnusedLocalVariable - false positive - parenthesis + 0 + diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 75f3932a01..b57daf8852 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -345,6 +345,7 @@ For example: * [#246](https://github.com/pmd/pmd/issues/246): \[java] UnusedModifier doesn't check annotations * [#247](https://github.com/pmd/pmd/issues/247): \[java] UnusedModifier doesn't check annotations inner classes * [#248](https://github.com/pmd/pmd/issues/248): \[java] UnusedModifier doesn't check static keyword on nested enum declaration + * [#257](https://github.com/pmd/pmd/issues/257): \[java] UnusedLocalVariable false positive * XML * [#1518](https://sourceforge.net/p/pmd/bugs/1518/): \[xml] Error while processing xml file with ".webapp" in the file or directory name * psql