From de8f5b372ae551c279505ea5426f8f421b2b931c Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 23 Feb 2019 21:38:31 -0800 Subject: [PATCH 01/99] apex rules for test method and assert statements --- docs/pages/pmd/rules/apex.md | 4 +- docs/pages/pmd/rules/apex/bestpractices.md | 80 ++++++++++++++++++- .../ApexUnitTestAssertStatementRule.java | 65 +++++++++++++++ ...tMethodShouldHaveIsTestAnnotationRule.java | 78 ++++++++++++++++++ .../resources/category/apex/bestpractices.xml | 50 ++++++++++++ .../main/resources/rulesets/apex/ruleset.xml | 18 +++++ .../ApexUnitTestAssertStatementTest.java | 11 +++ ...tMethodShouldHaveIsTestAnnotationTest.java | 11 +++ .../xml/ApexUnitTestAssertStatement.xml | 38 +++++++++ ...itTestMethodShouldHaveIsTestAnnotation.xml | 25 ++++++ 10 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java create mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java create mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java create mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationTest.java create mode 100644 pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml create mode 100644 pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml diff --git a/docs/pages/pmd/rules/apex.md b/docs/pages/pmd/rules/apex.md index 1f59b133e4..ff62b88ef4 100644 --- a/docs/pages/pmd/rules/apex.md +++ b/docs/pages/pmd/rules/apex.md @@ -11,7 +11,9 @@ folder: pmd/rules {% include callout.html content="Rules which enforce generally accepted best practices." %} +* [ApexUnitTestAssertStatement](pmd_rules_apex_bestpractices.html#apexunittestassertstatement): Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. * [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts): Apex unit tests should include at least one assertion. This makes the tests more robust, and usi... +* [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation): Apex test methods should have @isTest annotation either in the same line or in previous line. * [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue): Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database... * [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... * [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... @@ -120,7 +122,7 @@ folder: pmd/rules It contains the following rules: - [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto), [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation), [ApexCSRF](pmd_rules_apex_security.html#apexcsrf), [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods), [ApexDoc](pmd_rules_apex_documentation.html#apexdoc), [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint), [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect), [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations), [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection), [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred), [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts), [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue), [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse), [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam), [AvoidDeeplyNestedIfStmts](pmd_rules_apex_design.html#avoiddeeplynestedifstmts), [AvoidDirectAccessTriggerMap](pmd_rules_apex_errorprone.html#avoiddirectaccesstriggermap), [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops), [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier), [AvoidHardcodingId](pmd_rules_apex_errorprone.html#avoidhardcodingid), [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger), [AvoidNonExistentAnnotations](pmd_rules_apex_errorprone.html#avoidnonexistentannotations), [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops), [AvoidSoslInLoops](pmd_rules_apex_performance.html#avoidsoslinloops), [ClassNamingConventions](pmd_rules_apex_codestyle.html#classnamingconventions), [CyclomaticComplexity](pmd_rules_apex_design.html#cyclomaticcomplexity), [EmptyCatchBlock](pmd_rules_apex_errorprone.html#emptycatchblock), [EmptyIfStmt](pmd_rules_apex_errorprone.html#emptyifstmt), [EmptyStatementBlock](pmd_rules_apex_errorprone.html#emptystatementblock), [EmptyTryOrFinallyBlock](pmd_rules_apex_errorprone.html#emptytryorfinallyblock), [EmptyWhileStmt](pmd_rules_apex_errorprone.html#emptywhilestmt), [ExcessiveClassLength](pmd_rules_apex_design.html#excessiveclasslength), [ExcessiveParameterList](pmd_rules_apex_design.html#excessiveparameterlist), [ExcessivePublicCount](pmd_rules_apex_design.html#excessivepubliccount), [ForLoopsMustUseBraces](pmd_rules_apex_codestyle.html#forloopsmustusebraces), [IfElseStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifelsestmtsmustusebraces), [IfStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifstmtsmustusebraces), [MethodNamingConventions](pmd_rules_apex_codestyle.html#methodnamingconventions), [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_errorprone.html#methodwithsamenameasenclosingclass), [NcssConstructorCount](pmd_rules_apex_design.html#ncssconstructorcount), [NcssMethodCount](pmd_rules_apex_design.html#ncssmethodcount), [NcssTypeCount](pmd_rules_apex_design.html#ncsstypecount), [OneDeclarationPerLine](pmd_rules_apex_codestyle.html#onedeclarationperline), [StdCyclomaticComplexity](pmd_rules_apex_design.html#stdcyclomaticcomplexity), [TooManyFields](pmd_rules_apex_design.html#toomanyfields), [VariableNamingConventions](pmd_rules_apex_codestyle.html#variablenamingconventions), [WhileLoopsMustUseBraces](pmd_rules_apex_codestyle.html#whileloopsmustusebraces) + [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto), [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation), [ApexCSRF](pmd_rules_apex_security.html#apexcsrf), [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods), [ApexDoc](pmd_rules_apex_documentation.html#apexdoc), [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint), [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect), [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations), [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection), [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred), [ApexUnitTestAssertStatement](pmd_rules_apex_bestpractices.html#apexunittestassertstatement), [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts), [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation), [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue), [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse), [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam), [AvoidDeeplyNestedIfStmts](pmd_rules_apex_design.html#avoiddeeplynestedifstmts), [AvoidDirectAccessTriggerMap](pmd_rules_apex_errorprone.html#avoiddirectaccesstriggermap), [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops), [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier), [AvoidHardcodingId](pmd_rules_apex_errorprone.html#avoidhardcodingid), [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger), [AvoidNonExistentAnnotations](pmd_rules_apex_errorprone.html#avoidnonexistentannotations), [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops), [AvoidSoslInLoops](pmd_rules_apex_performance.html#avoidsoslinloops), [ClassNamingConventions](pmd_rules_apex_codestyle.html#classnamingconventions), [CyclomaticComplexity](pmd_rules_apex_design.html#cyclomaticcomplexity), [EmptyCatchBlock](pmd_rules_apex_errorprone.html#emptycatchblock), [EmptyIfStmt](pmd_rules_apex_errorprone.html#emptyifstmt), [EmptyStatementBlock](pmd_rules_apex_errorprone.html#emptystatementblock), [EmptyTryOrFinallyBlock](pmd_rules_apex_errorprone.html#emptytryorfinallyblock), [EmptyWhileStmt](pmd_rules_apex_errorprone.html#emptywhilestmt), [ExcessiveClassLength](pmd_rules_apex_design.html#excessiveclasslength), [ExcessiveParameterList](pmd_rules_apex_design.html#excessiveparameterlist), [ExcessivePublicCount](pmd_rules_apex_design.html#excessivepubliccount), [ForLoopsMustUseBraces](pmd_rules_apex_codestyle.html#forloopsmustusebraces), [IfElseStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifelsestmtsmustusebraces), [IfStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifstmtsmustusebraces), [MethodNamingConventions](pmd_rules_apex_codestyle.html#methodnamingconventions), [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_errorprone.html#methodwithsamenameasenclosingclass), [NcssConstructorCount](pmd_rules_apex_design.html#ncssconstructorcount), [NcssMethodCount](pmd_rules_apex_design.html#ncssmethodcount), [NcssTypeCount](pmd_rules_apex_design.html#ncsstypecount), [OneDeclarationPerLine](pmd_rules_apex_codestyle.html#onedeclarationperline), [StdCyclomaticComplexity](pmd_rules_apex_design.html#stdcyclomaticcomplexity), [TooManyFields](pmd_rules_apex_design.html#toomanyfields), [VariableNamingConventions](pmd_rules_apex_codestyle.html#variablenamingconventions), [WhileLoopsMustUseBraces](pmd_rules_apex_codestyle.html#whileloopsmustusebraces) * Empty Code (`rulesets/apex/empty.xml`): diff --git a/docs/pages/pmd/rules/apex/bestpractices.md b/docs/pages/pmd/rules/apex/bestpractices.md index 82e42195f4..80fb834f1e 100644 --- a/docs/pages/pmd/rules/apex/bestpractices.md +++ b/docs/pages/pmd/rules/apex/bestpractices.md @@ -5,10 +5,48 @@ permalink: pmd_rules_apex_bestpractices.html folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/category/apex/bestpractices.xml -keywords: Best Practices, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue, AvoidGlobalModifier, AvoidLogicInTrigger +keywords: Best Practices, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue, AvoidGlobalModifier, AvoidLogicInTrigger, ApexUnitTestAssertStatement, ApexUnitTestMethodShouldHaveIsTestAnnotation language: Apex --- +## ApexUnitTestAssertStatement + +**Since:** PMD 6.12.0 + +**Priority:** Medium (3) + +Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. + +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestAssertStatementRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java) + +**Example(s):** + +``` java +@isTest +public class Foo { + @isTest + static void methodATest() { + System.assertNotEquals('123', o.StageName); // not good + System.assertEquals('123', o.StageName, o); // good + System.assert(1==1); // not good + System.assert(1==1, 2); // good + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| +|cc\_block\_highlighting|false|Code Climate Block Highlighting|no| + +**Use this rule by referencing it:** +``` xml + +``` + ## ApexUnitTestClassShouldHaveAsserts **Since:** PMD 5.5.1 @@ -47,6 +85,46 @@ public class Foo { ``` +## ApexUnitTestMethodShouldHaveIsTestAnnotation + +**Since:** PMD 6.12.0 + +**Priority:** Medium (3) + +Apex test methods should have @isTest annotation either in the same line or in previous line. + +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestMethodShouldHaveIsTestAnnotationRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java) + +**Example(s):** + +``` java +@isTest +private class ATest { + @isTest + static void methodATest() { + } + static void methodBTest() { + } + @isTest static void methodCTest() { + } + private void fetchData() { + } +} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| +|cc\_block\_highlighting|false|Code Climate Block Highlighting|no| + +**Use this rule by referencing it:** +``` xml + +``` + ## ApexUnitTestShouldNotUseSeeAllDataTrue **Since:** PMD 5.5.1 diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java new file mode 100644 index 0000000000..2b690748a8 --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java @@ -0,0 +1,65 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule.bestpractices; + +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; +import net.sourceforge.pmd.lang.apex.ast.ApexNode; +import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; + +/** + * Apex unit tests should have System.assert methods in them + * + * @author sudhansu + */ +public class ApexUnitTestAssertStatementRule extends AbstractApexUnitTestRule { + + private static final Set ASSERT_METHODS = new HashSet<>(); + private static final String ASSERT = "system.assert"; + private static final String ASSERT_EQUALS = "system.assertequals"; + private static final String ASSERT_NOT_EQUALS = "system.assertnotequals"; + + static { + ASSERT_METHODS.add(ASSERT); + ASSERT_METHODS.add(ASSERT_EQUALS); + ASSERT_METHODS.add(ASSERT_NOT_EQUALS); + } + + @Override + public Object visit(ASTMethodCallExpression node, Object data) { + if (!ASSERT_METHODS.contains(node.getFullMethodName().toLowerCase(Locale.ROOT))) { + return data; + } + + return checkForAssertStatement(node, data); + } + + protected Object checkForAssertStatement(ApexNode node, Object data) { + // if System.assert has 1 argument, throw error + // if System.assertEquals/System.assertNotEquals has only 2 arguments, throw error + ASTMethodCallExpression assertMethodCall = (ASTMethodCallExpression) node; + if (assertMethodCall == null) { + return data; + } + if (ASSERT.equalsIgnoreCase(assertMethodCall.getFullMethodName()) + && assertMethodCall.jjtGetNumChildren() == 2) { + addViolationWithMessage(data, node, + "''{0}'' should have 2 parameters.", + new Object[] { ASSERT }); + } else if ((ASSERT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName()) + || ASSERT_NOT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName())) + && assertMethodCall.jjtGetNumChildren() == 3) { + Object obj = ASSERT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName()) + ? ASSERT_EQUALS : ASSERT_NOT_EQUALS; + addViolationWithMessage(data, node, + "''{0}'' should have 3 parameters.", + new Object[] { obj }); + } + return data; + } +} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java new file mode 100644 index 0000000000..f5965a60e3 --- /dev/null +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java @@ -0,0 +1,78 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule.bestpractices; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; +import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; +import net.sourceforge.pmd.lang.apex.ast.ApexNode; +import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; + +import apex.jorje.semantic.ast.modifier.Annotation; +import apex.jorje.semantic.ast.modifier.ModifierOrAnnotation; +import apex.jorje.semantic.symbol.type.AnnotationTypeInfos; +import apex.jorje.semantic.symbol.type.ModifierOrAnnotationTypeInfo; +import apex.jorje.semantic.symbol.type.TypeInfoEquivalence; +import apex.jorje.services.Version; + +public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractApexUnitTestRule { + private static final String TEST = "test"; + + @Override + public Object visit(final ASTUserClass node, final Object data) { + // test methods should have @isTest annotation. + final Version classApiVersion = node.getNode().getDefiningType().getCodeUnitDetails().getVersion(); + + if (!isTestMethodOrClass(node) && classApiVersion.isGreaterThan(Version.V174)) { + return data; + } + + checkForIsTestAnnotation(node, data); + return super.visit(node, data); + } + + private Object checkForIsTestAnnotation(final ApexNode node, final Object data) { + final List methods = node.findDescendantsOfType(ASTMethod.class); + final List testMethods = new ArrayList<>(); + for (ASTMethod method : methods) { + final Version classApiVersion = method.getNode().getDefiningType().getCodeUnitDetails().getVersion(); + if (!isTestMethodOrClass(method) && classApiVersion.isGreaterThan(Version.V174) + && !method.getImage().toLowerCase(Locale.ROOT).contains(TEST)) { + continue; + } + testMethods.add(method); + } + Map methodLocMap = new HashMap<>(); + for (ASTMethod testMethod : testMethods) { + methodLocMap.put(testMethod.getNode().getLoc().getLine(), testMethod); + } + List modifierList = node.findDescendantsOfType(ASTModifierNode.class); + final Map modifierLocMap = new HashMap<>(); + for (ASTModifierNode modifier : modifierList) { + for (final ModifierOrAnnotationTypeInfo modifierOrAnnotationTypeInfo : modifier.getNode().getModifiers().all()) { + ModifierOrAnnotation modifierOrAnnotation = modifier.getNode().getModifiers().get(modifierOrAnnotationTypeInfo); + if (modifierOrAnnotation instanceof Annotation && TypeInfoEquivalence + .isEquivalent(modifierOrAnnotationTypeInfo, AnnotationTypeInfos.IS_TEST)) { + modifierLocMap.put(modifierOrAnnotation.getLoc().getLine(), modifierOrAnnotation); + } + } + } + for (Map.Entry entry : methodLocMap.entrySet()) { + if (entry != null && modifierLocMap.get(entry.getKey()) == null + && modifierLocMap.get(entry.getKey() - 1) == null) { + addViolationWithMessage(data, node, + "''{0}'' method should have @isTest annotation.", + new Object[] { entry.getValue().getImage() }); + } + } + return data; + } +} diff --git a/pmd-apex/src/main/resources/category/apex/bestpractices.xml b/pmd-apex/src/main/resources/category/apex/bestpractices.xml index 1ac782d8b1..bdea213275 100644 --- a/pmd-apex/src/main/resources/category/apex/bestpractices.xml +++ b/pmd-apex/src/main/resources/category/apex/bestpractices.xml @@ -106,6 +106,56 @@ trigger Accounts on Account (before insert, before update, before delete, after } } } +]]> + + + + + Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. + + 3 + + + + + + + Apex test methods should have @isTest annotation either in the same line or in previous line. + + 3 + + diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index 993f33a772..c49d32854a 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -233,6 +233,24 @@ + + 3 + + + + + + + + + 3 + + + + + + + diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java new file mode 100644 index 0000000000..1ceb9c97df --- /dev/null +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule.bestpractices; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class ApexUnitTestAssertStatementTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationTest.java new file mode 100644 index 0000000000..b753e8fb8a --- /dev/null +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.rule.bestpractices; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class ApexUnitTestMethodShouldHaveIsTestAnnotationTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml new file mode 100644 index 0000000000..3caa373a0b --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml @@ -0,0 +1,38 @@ + + + + + Problematic apex unit test assert statements - assert should have 2/3 params + 2 + + + + + [apex] assert should have 2 param and assertEquals should have 3 param. + 0 + + + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml new file mode 100644 index 0000000000..f32c75ef5b --- /dev/null +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml @@ -0,0 +1,25 @@ + + + + + Problematic apex unit test methods - test methods should have @isTest annotation. + 1 + + + From f5b315db4d9f17bdc335d8e7bcc08da911e9d16c Mon Sep 17 00:00:00 2001 From: Matias Fraga Date: Sun, 24 Feb 2019 17:18:56 -0300 Subject: [PATCH 02/99] Add CPD documentation --- .../adding_new_cpd_language.md | 51 +++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md index 0cc1127ca4..f42bfdf34d 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md @@ -8,16 +8,49 @@ permalink: pmd_devdocs_major_adding_new_cpd_language.html author: Romain PELISSE --- -If you wish CPD to parse a unsupported language, you can easily develop a new parser for CPD. All you need to is implements the following interface: +First of all, thanks for the contribution! + +Happily for you, to add CPD support for a new language is now easier than ever! +> **Pro Tip**: If you wish to add a new language, there are more than 50 languages you could easily add with just an [Antlr grammar](https://github.com/antlr/grammars-v4). + +All you need to do is: +- Create a new module for your language, you can take [GO as an example](https://github.com/pmd/pmd/tree/master/pmd-go) +- Take the grammar from [Antlr git project](https://github.com/antlr/grammars-v4) +- Implement your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class +```java +public class GoLanguage extends AbstractLanguage { + + public GoLanguage() { + super("Go", "go", new GoTokenizer(), ".go"); + } +} +``` +> **Pro Tip**: Yes, keep looking at Go! +- Implement your [Tokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java) +```java +public class GoTokenizer extends AntlrTokenizer { + + @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) { + CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode); + return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName()); + } +} +``` + +And that's it! + +Oh.. please don't forget to add some test, you can again.. look at GO implementation ;) -* net.sourceforge.pmd.cpd.Language -* net.sourceforge.pmd.cpd.Tokenizer +# Bonus -Do not forget to the follow the proper naming convention, as the CPD parser factory use this convention: +If you read this far, I'm keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that) +If that's your case , you came to the right place! All you need to do is implement your own [AntlrTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java) + +And by now, I know where you are going to look... + -* Language Name + "Language" -* Tokenizer Name + "Tokenizer" +**WRONG** -For instance, if you develop a python parser, you should have two classes named PythonLanguage and PythonTokenizer. - -To test your parser, just package it in a jar and add your jar to the classpath. + +Why do you want GO to solve all your problems? +You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) From c322b9d0c12fd9f95eeceb5f1e5b1611474a8911 Mon Sep 17 00:00:00 2001 From: Matias Fraga Date: Mon, 25 Feb 2019 14:53:11 -0300 Subject: [PATCH 03/99] Add steps and non-antlr doc --- .../adding_new_cpd_language.md | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md index f42bfdf34d..ec248d075c 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md @@ -8,49 +8,62 @@ permalink: pmd_devdocs_major_adding_new_cpd_language.html author: Romain PELISSE --- -First of all, thanks for the contribution! - -Happily for you, to add CPD support for a new language is now easier than ever! -> **Pro Tip**: If you wish to add a new language, there are more than 50 languages you could easily add with just an [Antlr grammar](https://github.com/antlr/grammars-v4). - -All you need to do is: -- Create a new module for your language, you can take [GO as an example](https://github.com/pmd/pmd/tree/master/pmd-go) -- Take the grammar from [Antlr git project](https://github.com/antlr/grammars-v4) -- Implement your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class -```java -public class GoLanguage extends AbstractLanguage { - - public GoLanguage() { - super("Go", "go", new GoTokenizer(), ".go"); - } -} -``` -> **Pro Tip**: Yes, keep looking at Go! -- Implement your [Tokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java) -```java -public class GoTokenizer extends AntlrTokenizer { - - @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) { - CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode); - return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName()); - } -} -``` - -And that's it! - -Oh.. please don't forget to add some test, you can again.. look at GO implementation ;) +First of all, thanks for the contribution! + +Happily for you, to add CPD support for a new language is now easier than ever! +> **Pro Tip**: If you wish to add a new language, there are more than 50 languages you could easily add with just an [Antlr grammar](https://github.com/antlr/grammars-v4). -# Bonus -If you read this far, I'm keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that) -If that's your case , you came to the right place! All you need to do is implement your own [AntlrTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java) - -And by now, I know where you are going to look... + All you need to do is follow this few steps: + +1. Create a new module for your language, you can take [GO as an example](https://github.com/pmd/pmd/tree/master/pmd-go) +2. Create a Tokenizer + +- For Antlr grammars you can take the grammar from [here](https://github.com/antlr/grammars-v4) and extend [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java) taking Go as an example + +```java + public class GoTokenizer extends AntlrTokenizer { + + @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) { + CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode); + return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName()); + } + } +``` -**WRONG** + +- For any other scenario you can use [AnyTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java) +3. Create your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class +```java +public class GoLanguage extends AbstractLanguage { + + public GoLanguage() { + super("Go", "go", new GoTokenizer(), ".go"); + } +} +``` + + +> **Pro Tip**: Yes, keep looking at Go! + + **You are almost there!** + +4. Please don't forget to add some test, you can again.. look at Go implementation ;) -Why do you want GO to solve all your problems? -You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) +If you read this far, I'm keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that) +If that's your case , you came to the right place! + +5. You can add your custom properties using a Token filter + +- For Antlr grammars all you need to do is implement your own [AntlrTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java) + + And by now, I know where you are going to look... + + **WRONG** + + Why do you want GO to solve all your problems? + You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) + +- For non-Antlr grammars you can use [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) directly or take a peek to [Java's mbngjht8 token filter](https://github.com/pmd/pmd/blob/91e3f699f5b741b4cbc9b0cf07da91211c7a20b6/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaTokenizer.java) From 833ab3f221a0ffe0f5d27a7e509fd1c92c78e3cf Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 2 Mar 2019 20:31:41 -0800 Subject: [PATCH 04/99] review feedback implemented on new apex rules --- docs/pages/pmd/rules/apex.md | 5 ++--- docs/pages/pmd/rules/apex/bestpractices.md | 16 ++++++++------ .../ApexUnitTestAssertStatementRule.java | 4 ++++ ...tMethodShouldHaveIsTestAnnotationRule.java | 6 ++++- .../resources/category/apex/bestpractices.xml | 18 ++++++++------- .../xml/ApexUnitTestAssertStatement.xml | 11 +++++----- ...itTestMethodShouldHaveIsTestAnnotation.xml | 22 +++++++++++++++++++ 7 files changed, 58 insertions(+), 24 deletions(-) diff --git a/docs/pages/pmd/rules/apex.md b/docs/pages/pmd/rules/apex.md index ff62b88ef4..bf1a646680 100644 --- a/docs/pages/pmd/rules/apex.md +++ b/docs/pages/pmd/rules/apex.md @@ -11,9 +11,8 @@ folder: pmd/rules {% include callout.html content="Rules which enforce generally accepted best practices." %} -* [ApexUnitTestAssertStatement](pmd_rules_apex_bestpractices.html#apexunittestassertstatement): Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. * [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts): Apex unit tests should include at least one assertion. This makes the tests more robust, and usi... -* [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation): Apex test methods should have @isTest annotation either in the same line or in previous line. +* [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation): Apex test methods should have @isTest annotation. As testMethod keyword is deprecated,... * [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue): Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database... * [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... * [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... @@ -122,7 +121,7 @@ folder: pmd/rules It contains the following rules: - [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto), [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation), [ApexCSRF](pmd_rules_apex_security.html#apexcsrf), [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods), [ApexDoc](pmd_rules_apex_documentation.html#apexdoc), [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint), [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect), [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations), [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection), [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred), [ApexUnitTestAssertStatement](pmd_rules_apex_bestpractices.html#apexunittestassertstatement), [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts), [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation), [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue), [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse), [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam), [AvoidDeeplyNestedIfStmts](pmd_rules_apex_design.html#avoiddeeplynestedifstmts), [AvoidDirectAccessTriggerMap](pmd_rules_apex_errorprone.html#avoiddirectaccesstriggermap), [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops), [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier), [AvoidHardcodingId](pmd_rules_apex_errorprone.html#avoidhardcodingid), [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger), [AvoidNonExistentAnnotations](pmd_rules_apex_errorprone.html#avoidnonexistentannotations), [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops), [AvoidSoslInLoops](pmd_rules_apex_performance.html#avoidsoslinloops), [ClassNamingConventions](pmd_rules_apex_codestyle.html#classnamingconventions), [CyclomaticComplexity](pmd_rules_apex_design.html#cyclomaticcomplexity), [EmptyCatchBlock](pmd_rules_apex_errorprone.html#emptycatchblock), [EmptyIfStmt](pmd_rules_apex_errorprone.html#emptyifstmt), [EmptyStatementBlock](pmd_rules_apex_errorprone.html#emptystatementblock), [EmptyTryOrFinallyBlock](pmd_rules_apex_errorprone.html#emptytryorfinallyblock), [EmptyWhileStmt](pmd_rules_apex_errorprone.html#emptywhilestmt), [ExcessiveClassLength](pmd_rules_apex_design.html#excessiveclasslength), [ExcessiveParameterList](pmd_rules_apex_design.html#excessiveparameterlist), [ExcessivePublicCount](pmd_rules_apex_design.html#excessivepubliccount), [ForLoopsMustUseBraces](pmd_rules_apex_codestyle.html#forloopsmustusebraces), [IfElseStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifelsestmtsmustusebraces), [IfStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifstmtsmustusebraces), [MethodNamingConventions](pmd_rules_apex_codestyle.html#methodnamingconventions), [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_errorprone.html#methodwithsamenameasenclosingclass), [NcssConstructorCount](pmd_rules_apex_design.html#ncssconstructorcount), [NcssMethodCount](pmd_rules_apex_design.html#ncssmethodcount), [NcssTypeCount](pmd_rules_apex_design.html#ncsstypecount), [OneDeclarationPerLine](pmd_rules_apex_codestyle.html#onedeclarationperline), [StdCyclomaticComplexity](pmd_rules_apex_design.html#stdcyclomaticcomplexity), [TooManyFields](pmd_rules_apex_design.html#toomanyfields), [VariableNamingConventions](pmd_rules_apex_codestyle.html#variablenamingconventions), [WhileLoopsMustUseBraces](pmd_rules_apex_codestyle.html#whileloopsmustusebraces) + [ApexBadCrypto](pmd_rules_apex_security.html#apexbadcrypto), [ApexCRUDViolation](pmd_rules_apex_security.html#apexcrudviolation), [ApexCSRF](pmd_rules_apex_security.html#apexcsrf), [ApexDangerousMethods](pmd_rules_apex_security.html#apexdangerousmethods), [ApexDoc](pmd_rules_apex_documentation.html#apexdoc), [ApexInsecureEndpoint](pmd_rules_apex_security.html#apexinsecureendpoint), [ApexOpenRedirect](pmd_rules_apex_security.html#apexopenredirect), [ApexSharingViolations](pmd_rules_apex_security.html#apexsharingviolations), [ApexSOQLInjection](pmd_rules_apex_security.html#apexsoqlinjection), [ApexSuggestUsingNamedCred](pmd_rules_apex_security.html#apexsuggestusingnamedcred), [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts), [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue), [ApexXSSFromEscapeFalse](pmd_rules_apex_security.html#apexxssfromescapefalse), [ApexXSSFromURLParam](pmd_rules_apex_security.html#apexxssfromurlparam), [AvoidDeeplyNestedIfStmts](pmd_rules_apex_design.html#avoiddeeplynestedifstmts), [AvoidDirectAccessTriggerMap](pmd_rules_apex_errorprone.html#avoiddirectaccesstriggermap), [AvoidDmlStatementsInLoops](pmd_rules_apex_performance.html#avoiddmlstatementsinloops), [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier), [AvoidHardcodingId](pmd_rules_apex_errorprone.html#avoidhardcodingid), [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger), [AvoidNonExistentAnnotations](pmd_rules_apex_errorprone.html#avoidnonexistentannotations), [AvoidSoqlInLoops](pmd_rules_apex_performance.html#avoidsoqlinloops), [AvoidSoslInLoops](pmd_rules_apex_performance.html#avoidsoslinloops), [ClassNamingConventions](pmd_rules_apex_codestyle.html#classnamingconventions), [CyclomaticComplexity](pmd_rules_apex_design.html#cyclomaticcomplexity), [EmptyCatchBlock](pmd_rules_apex_errorprone.html#emptycatchblock), [EmptyIfStmt](pmd_rules_apex_errorprone.html#emptyifstmt), [EmptyStatementBlock](pmd_rules_apex_errorprone.html#emptystatementblock), [EmptyTryOrFinallyBlock](pmd_rules_apex_errorprone.html#emptytryorfinallyblock), [EmptyWhileStmt](pmd_rules_apex_errorprone.html#emptywhilestmt), [ExcessiveClassLength](pmd_rules_apex_design.html#excessiveclasslength), [ExcessiveParameterList](pmd_rules_apex_design.html#excessiveparameterlist), [ExcessivePublicCount](pmd_rules_apex_design.html#excessivepubliccount), [ForLoopsMustUseBraces](pmd_rules_apex_codestyle.html#forloopsmustusebraces), [IfElseStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifelsestmtsmustusebraces), [IfStmtsMustUseBraces](pmd_rules_apex_codestyle.html#ifstmtsmustusebraces), [MethodNamingConventions](pmd_rules_apex_codestyle.html#methodnamingconventions), [MethodWithSameNameAsEnclosingClass](pmd_rules_apex_errorprone.html#methodwithsamenameasenclosingclass), [NcssConstructorCount](pmd_rules_apex_design.html#ncssconstructorcount), [NcssMethodCount](pmd_rules_apex_design.html#ncssmethodcount), [NcssTypeCount](pmd_rules_apex_design.html#ncsstypecount), [OneDeclarationPerLine](pmd_rules_apex_codestyle.html#onedeclarationperline), [StdCyclomaticComplexity](pmd_rules_apex_design.html#stdcyclomaticcomplexity), [TooManyFields](pmd_rules_apex_design.html#toomanyfields), [VariableNamingConventions](pmd_rules_apex_codestyle.html#variablenamingconventions), [WhileLoopsMustUseBraces](pmd_rules_apex_codestyle.html#whileloopsmustusebraces) * Empty Code (`rulesets/apex/empty.xml`): diff --git a/docs/pages/pmd/rules/apex/bestpractices.md b/docs/pages/pmd/rules/apex/bestpractices.md index 80fb834f1e..d3d684aed8 100644 --- a/docs/pages/pmd/rules/apex/bestpractices.md +++ b/docs/pages/pmd/rules/apex/bestpractices.md @@ -11,11 +11,12 @@ language: Apex ## ApexUnitTestAssertStatement -**Since:** PMD 6.12.0 +**Since:** PMD 6.13.0 **Priority:** Medium (3) -Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. +The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. +Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestAssertStatementRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java) @@ -27,9 +28,9 @@ public class Foo { @isTest static void methodATest() { System.assertNotEquals('123', o.StageName); // not good - System.assertEquals('123', o.StageName, o); // good - System.assert(1==1); // not good - System.assert(1==1, 2); // good + System.assertEquals('123', o.StageName, 'Opportunity stageName is wrong.'); // good + System.assert(o.isClosed); // not good + System.assert(o.isClosed, 'Opportunity is not closed.'); // good } } ``` @@ -87,11 +88,12 @@ public class Foo { ## ApexUnitTestMethodShouldHaveIsTestAnnotation -**Since:** PMD 6.12.0 +**Since:** PMD 6.13.0 **Priority:** Medium (3) -Apex test methods should have @isTest annotation either in the same line or in previous line. +Apex test methods should have @isTest annotation. +As testMethod keyword is deprecated, Salesforce advices to use @isTest annotation for test class/methods. **This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestMethodShouldHaveIsTestAnnotationRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java index 2b690748a8..35ff462122 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java @@ -30,6 +30,10 @@ public class ApexUnitTestAssertStatementRule extends AbstractApexUnitTestRule { ASSERT_METHODS.add(ASSERT_NOT_EQUALS); } + public ApexUnitTestAssertStatementRule() { + addRuleChainVisit(ASTMethodCallExpression.class); + } + @Override public Object visit(ASTMethodCallExpression node, Object data) { if (!ASSERT_METHODS.contains(node.getFullMethodName().toLowerCase(Locale.ROOT))) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java index f5965a60e3..6d8ca1f082 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java @@ -26,6 +26,10 @@ import apex.jorje.services.Version; public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractApexUnitTestRule { private static final String TEST = "test"; + public ApexUnitTestMethodShouldHaveIsTestAnnotationRule() { + addRuleChainVisit(ASTUserClass.class); + } + @Override public Object visit(final ASTUserClass node, final Object data) { // test methods should have @isTest annotation. @@ -36,7 +40,7 @@ public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractAp } checkForIsTestAnnotation(node, data); - return super.visit(node, data); + return data; } private Object checkForIsTestAnnotation(final ApexNode node, final Object data) { diff --git a/pmd-apex/src/main/resources/category/apex/bestpractices.xml b/pmd-apex/src/main/resources/category/apex/bestpractices.xml index bdea213275..55a77e5189 100644 --- a/pmd-apex/src/main/resources/category/apex/bestpractices.xml +++ b/pmd-apex/src/main/resources/category/apex/bestpractices.xml @@ -110,12 +110,13 @@ trigger Accounts on Account (before insert, before update, before delete, after - Apex test assert should have 2 params and assertEquals/assertNotEquals should have 3 params. + The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. + Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. 3 @@ -125,21 +126,22 @@ public class Foo { @isTest static void methodATest() { System.assertNotEquals('123', o.StageName); // not good - System.assertEquals('123', o.StageName, o); // good - System.assert(1==1); // not good - System.assert(1==1, 2); // good + System.assertEquals('123', o.StageName, 'Opportunity stageName is wrong.'); // good + System.assert(o.isClosed); // not good + System.assert(o.isClosed, 'Opportunity is not closed.'); // good } } ]]> - Apex test methods should have @isTest annotation either in the same line or in previous line. + Apex test methods should have @isTest annotation. + As testMethod keyword is deprecated, Salesforce advices to use @isTest annotation for test class/methods. 3 diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml index 3caa373a0b..dba55d1863 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml @@ -7,15 +7,16 @@ Problematic apex unit test assert statements - assert should have 2/3 params 2 + 5,7 @@ -29,8 +30,8 @@ public class Foo { public class Foo { @isTest static void methodATest() { - System.assertEquals('123', o.StageName, o); // good - System.assert(1==1, 2); // good + System.assertEquals('Test opportunity', o.Name, 'Opportunity Name' + o.Name + 'is wrong.'); // good + System.assert(o.isClosed, 'Opportunity is not closed.'); // good } } ]]> diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml index f32c75ef5b..a0ef640db7 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml @@ -19,6 +19,28 @@ private class ATest { } private void fetchData() { } +} + ]]> + + + Test methods should have @isTest annotation. + 0 + From 6b50437df31a5d73698302841539458d6ebe0512 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 3 Mar 2019 11:52:08 +0100 Subject: [PATCH 05/99] Upgrade surefire and junit test engine Also fix test in pmd-apex --- .../rule/codestyle/xml/MethodNamingConventions.xml | 6 +++--- pom.xml | 14 ++------------ 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codestyle/xml/MethodNamingConventions.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codestyle/xml/MethodNamingConventions.xml index fcda99cba6..0a1798e969 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codestyle/xml/MethodNamingConventions.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codestyle/xml/MethodNamingConventions.xml @@ -68,8 +68,8 @@ public class Foo { #1573 method names should not contain underscores, but skip test methods 1 - 0 true + 0 #1573 method names should not contain underscores, but skip test methods 2 - 0 true + 0 #1573 method names should not contain underscores, but skip test methods 3 - 1 false + 1 5.0 - 2.22.0 + 2.22.1 3.0.0 3.11.0 1.10.1 @@ -436,21 +436,11 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code ${project.basedir}/src/test/kotlin - - - - - - org.junit.platform - junit-platform-surefire-provider - 1.2.0 - - org.junit.vintage junit-vintage-engine - 5.3.0-M1 + 5.4.0 From b126bf94d2ccf42850d5b465e6fbc5be7ad38604 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 9 Mar 2019 16:21:11 +0100 Subject: [PATCH 06/99] [doc] Generate property override examples in rule doc Refs #1712 --- .../pmd/docs/RuleDocGenerator.java | 58 +++++++++++++------ pmd-doc/src/test/resources/expected/sample.md | 53 ++++++++++++++++- 2 files changed, 91 insertions(+), 20 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 3c5fdb049e..a30b5cfa2c 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 @@ -449,22 +449,7 @@ public class RuleDocGenerator { description = description.substring(DEPRECATED_RULE_PROPERTY_MARKER.length()); } - String defaultValue = ""; - if (propertyDescriptor.defaultValue() != null) { - if (propertyDescriptor.isMultiValue()) { - @SuppressWarnings("unchecked") // multi valued properties are using a List - MultiValuePropertyDescriptor> multiPropertyDescriptor = (MultiValuePropertyDescriptor>) propertyDescriptor; - defaultValue = multiPropertyDescriptor.asDelimitedString(multiPropertyDescriptor.defaultValue()); - - // surround the delimiter with spaces, so that the browser can wrap - // the value nicely - defaultValue = defaultValue.replaceAll(Pattern.quote( - String.valueOf(multiPropertyDescriptor.multiValueDelimiter())), - " " + multiPropertyDescriptor.multiValueDelimiter() + " "); - } else { - defaultValue = String.valueOf(propertyDescriptor.defaultValue()); - } - } + String defaultValue = determineDefaultValueAsString(propertyDescriptor); String multiValued = "no"; if (propertyDescriptor.isMultiValue()) { @@ -483,11 +468,30 @@ public class RuleDocGenerator { lines.add(""); } - lines.add("**Use this rule by referencing it:**"); + if (properties.isEmpty()) { + lines.add("**Use this rule by referencing it:**"); + } else { + lines.add("**Use this rule with the default properties by just referencing it:**"); + } lines.add("``` xml"); lines.add(""); lines.add("```"); lines.add(""); + + if (!properties.isEmpty()) { + lines.add("**Use this rule and customize it:**"); + lines.add("``` xml"); + lines.add(""); + lines.add(" "); + for (PropertyDescriptor propertyDescriptor : properties) { + String defaultValue = determineDefaultValueAsString(propertyDescriptor); + lines.add(" "); + } + lines.add(" "); + lines.add(""); + lines.add("```"); + lines.add(""); + } } writer.write(path, lines); @@ -496,6 +500,26 @@ public class RuleDocGenerator { } } + private String determineDefaultValueAsString(PropertyDescriptor propertyDescriptor) { + String defaultValue = ""; + if (propertyDescriptor.defaultValue() != null) { + if (propertyDescriptor.isMultiValue()) { + @SuppressWarnings("unchecked") // multi valued properties are using a List + MultiValuePropertyDescriptor> multiPropertyDescriptor = (MultiValuePropertyDescriptor>) propertyDescriptor; + defaultValue = multiPropertyDescriptor.asDelimitedString(multiPropertyDescriptor.defaultValue()); + + // surround the delimiter with spaces, so that the browser can wrap + // the value nicely + defaultValue = defaultValue.replaceAll(Pattern.quote( + String.valueOf(multiPropertyDescriptor.multiValueDelimiter())), + " " + multiPropertyDescriptor.multiValueDelimiter() + " "); + } else { + defaultValue = String.valueOf(propertyDescriptor.defaultValue()); + } + } + return defaultValue; + } + private static String stripIndentation(String description) { if (description == null || description.isEmpty()) { return ""; diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index b5c5d9a145..eb55f991d0 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -76,11 +76,29 @@ public class JumbledIncrementerRule1 { |sampleRegexProperty6|\\b|The property is of type regex|no| |sampleRegexProperty7|\\n|The property is of type regex|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + + +``` + ## MovedRule Deprecated @@ -223,11 +241,29 @@ public class JumbledIncrementerRule1 { |sampleRegexProperty6|\\b|The property is of type regex|no| |sampleRegexProperty7|\\n|The property is of type regex|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + + +``` + ## XSSInDocumentation **Since:** PMD 0.1 @@ -296,7 +332,18 @@ public class Bar { |XSSpropertyTest <script>alert('XSS');</script>|<script>alert('XSS');</script>|<script>alert('XSS');</script>|no| |escapingNeeded|this is escaped: \||You should be able to use \| in the description|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` + +**Use this rule and customize it:** +``` xml + + + + + + + +``` From 054b4003fd544c62b9dfcb7045ba47ca64b45e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Mar 2019 16:39:37 +0100 Subject: [PATCH 07/99] Filter out deprecated properties Also: * Suppress space padding for xml default values * Fetch default value from the rule --- .../pmd/lang/rule/stat/StatisticalRule.java | 6 ++- .../pmd/docs/RuleDocGenerator.java | 37 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/stat/StatisticalRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/stat/StatisticalRule.java index 1bb01ec055..2796454383 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/stat/StatisticalRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/stat/StatisticalRule.java @@ -29,13 +29,15 @@ public interface StatisticalRule extends Rule { /** @deprecated Not useful, will not be replaced. */ @Deprecated - DoubleProperty SIGMA_DESCRIPTOR = new DoubleProperty("sigma", "Sigma value", -10000000d, 1000000d, null, 1.0f); + DoubleProperty SIGMA_DESCRIPTOR = new DoubleProperty("sigma", "deprecated! Sigma value", -10000000d, 1000000d, null, + 1.0f); // TODO we should have one such property descriptor pro rule, and *not* share it, to allow setting specific defaults DoubleProperty MINIMUM_DESCRIPTOR = new DoubleProperty("minimum", "Minimum reporting threshold", -10000000d, 1000000000d, null, 2.0f); /** @deprecated Not useful, will not be replaced. */ @Deprecated - IntegerProperty TOP_SCORE_DESCRIPTOR = new IntegerProperty("topscore", "Top score value", 1, 100, null, 3.0f); + IntegerProperty TOP_SCORE_DESCRIPTOR = new IntegerProperty("topscore", "deprecated! Top score value", 1, 100, + null, 3.0f); void addDataPoint(DataPoint point); 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 a30b5cfa2c..acf13282e6 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 @@ -442,14 +442,12 @@ public class RuleDocGenerator { lines.add("|----|-------------|-----------|-----------|"); for (PropertyDescriptor propertyDescriptor : properties) { String description = propertyDescriptor.description(); - boolean isDeprecated = false; - if (description != null && description.toLowerCase(Locale.ROOT) - .startsWith(DEPRECATED_RULE_PROPERTY_MARKER)) { - isDeprecated = true; + final boolean isDeprecated = isDeprecated(propertyDescriptor); + if (isDeprecated) { description = description.substring(DEPRECATED_RULE_PROPERTY_MARKER.length()); } - String defaultValue = determineDefaultValueAsString(propertyDescriptor); + String defaultValue = determineDefaultValueAsString(propertyDescriptor, rule, true); String multiValued = "no"; if (propertyDescriptor.isMultiValue()) { @@ -478,14 +476,17 @@ public class RuleDocGenerator { lines.add("```"); lines.add(""); - if (!properties.isEmpty()) { + if (properties.stream().anyMatch(it -> !isDeprecated(it))) { lines.add("**Use this rule and customize it:**"); lines.add("``` xml"); lines.add(""); lines.add(" "); for (PropertyDescriptor propertyDescriptor : properties) { - String defaultValue = determineDefaultValueAsString(propertyDescriptor); - lines.add(" "); + if (!isDeprecated(propertyDescriptor)) { + String defaultValue = determineDefaultValueAsString(propertyDescriptor, rule, false); + lines.add(" "); + } } lines.add(" "); lines.add(""); @@ -500,21 +501,29 @@ public class RuleDocGenerator { } } - private String determineDefaultValueAsString(PropertyDescriptor propertyDescriptor) { + private static boolean isDeprecated(PropertyDescriptor propertyDescriptor) { + return propertyDescriptor.description() != null + && propertyDescriptor.description().toLowerCase(Locale.ROOT).startsWith(DEPRECATED_RULE_PROPERTY_MARKER); + } + + private String determineDefaultValueAsString(PropertyDescriptor propertyDescriptor, Rule rule, boolean pad) { String defaultValue = ""; - if (propertyDescriptor.defaultValue() != null) { - if (propertyDescriptor.isMultiValue()) { + Object realDefaultValue = rule.getProperty(propertyDescriptor); + @SuppressWarnings("unchecked") // just force it, we know it's the right type + PropertyDescriptor captured = (PropertyDescriptor) propertyDescriptor; + + if (realDefaultValue != null) { + defaultValue = captured.asDelimitedString(realDefaultValue); + + if (pad && propertyDescriptor.isMultiValue()) { @SuppressWarnings("unchecked") // multi valued properties are using a List MultiValuePropertyDescriptor> multiPropertyDescriptor = (MultiValuePropertyDescriptor>) propertyDescriptor; - defaultValue = multiPropertyDescriptor.asDelimitedString(multiPropertyDescriptor.defaultValue()); // surround the delimiter with spaces, so that the browser can wrap // the value nicely defaultValue = defaultValue.replaceAll(Pattern.quote( String.valueOf(multiPropertyDescriptor.multiValueDelimiter())), " " + multiPropertyDescriptor.multiValueDelimiter() + " "); - } else { - defaultValue = String.valueOf(propertyDescriptor.defaultValue()); } } return defaultValue; From a755c83eef56ed5562060af38917e827f9001031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Mar 2019 17:03:20 +0100 Subject: [PATCH 08/99] Fix bug with maven incremental compil --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 70aa28fe81..24128ee154 100644 --- a/pom.xml +++ b/pom.xml @@ -367,6 +367,9 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code maven-compiler-plugin 3.7.0 + + + false ${java.version} From c71646475d45b3cd349e67e6791fd14b60f2bded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 10 Mar 2019 17:21:28 +0100 Subject: [PATCH 09/99] Fix tests --- pmd-doc/src/test/resources/expected/sample.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index eb55f991d0..866bb6815c 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -86,8 +86,7 @@ public class JumbledIncrementerRule1 { - - + @@ -251,8 +250,7 @@ public class JumbledIncrementerRule1 { - - + From 002ecb7783b50f1872a7dda5c9cd1c98ab7ee7d3 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 10 Mar 2019 19:32:20 +0100 Subject: [PATCH 10/99] Fix test dependencies with junit5/kotlin/junit4 combination When using kotlin test, which brings in the JUnit5 platform, additionally the junit-vintage-engine needs to be added to the test classpath, so that surefire will execute all tests (junit5/kotlin test + junit4 tests). --- pmd-java/pom.xml | 7 +++- pmd-lang-test/pom.xml | 23 +++++++------ pmd-test/pom.xml | 2 ++ pom.xml | 80 +++++++++++++++++++++++++------------------ 4 files changed, 67 insertions(+), 45 deletions(-) diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 455112048a..9b58bdbbaf 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -128,7 +128,6 @@ - net.sourceforge.pmd pmd-lang-test @@ -149,6 +148,12 @@ junit test + + org.junit.vintage + junit-vintage-engine + test + + com.github.stefanbirkner system-rules diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 5fbbf6e5f9..86d1bf1b13 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -43,42 +43,43 @@ - - - junit - junit - - net.sourceforge.pmd pmd-core + + + junit + junit + compile + + org.jetbrains.kotlin kotlin-stdlib - ${kotlin.version} compile org.jetbrains.kotlin kotlin-stdlib-jdk8 - ${kotlin.version} compile org.jetbrains.kotlin kotlin-test-junit - ${kotlin.version} compile io.kotlintest kotlintest-runner-junit5 - 3.1.8 compile @@ -86,7 +87,7 @@ net.sourceforge.pmd pmd-java - 6.9.0 + 6.12.0 test diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index 42542d6a1e..81e1ec7bb3 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -15,6 +15,8 @@ junit junit + + compile net.sourceforge.pmd diff --git a/pom.xml b/pom.xml index 878e85f3f3..e6c056fe62 100644 --- a/pom.xml +++ b/pom.xml @@ -432,17 +432,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code once alphabetical - ${project.basedir}/src/test/java - ${project.basedir}/src/test/kotlin - - - - org.junit.vintage - junit-vintage-engine - 5.4.0 - - org.codehaus.mojo @@ -816,11 +806,6 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code pmd-core ${project.version} - - net.sourceforge.pmd - pmd-test - ${project.version} - net.sourceforge.saxon saxon @@ -837,21 +822,6 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code rhino 1.7.7.2 - - junit - junit - 4.12 - - - org.hamcrest - hamcrest-library - 1.3 - - - pl.pragmatists - JUnitParams - 1.1.1 - net.java.dev.javacc javacc @@ -905,7 +875,12 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code - + + net.sourceforge.pmd + pmd-test + ${project.version} + test + net.sourceforge.pmd @@ -914,8 +889,48 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code test - + + junit + junit + 4.12 + test + + + org.hamcrest + hamcrest-library + 1.3 + test + + + pl.pragmatists + JUnitParams + 1.1.1 + test + + + + org.junit.jupiter + junit-jupiter-api + 5.4.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.4.0 + test + + + + + org.junit.vintage + junit-vintage-engine + 5.4.0 + test + + + org.jetbrains.kotlin kotlin-stdlib @@ -943,7 +958,6 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code 3.1.8 test - From 6680d020ae90b59e910b80ac21f5cdf7c1e9200f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Mon, 11 Mar 2019 22:30:49 +0100 Subject: [PATCH 11/99] Add copyright notices on pmd-lang-test --- .../net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt | 4 ++++ .../net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt | 4 ++++ .../kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt index 4b41aa7bce..99ed28c236 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt @@ -1,3 +1,7 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.lang.ast.test import com.github.oowekyala.treeutils.TreeLikeAdapter diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt index 7dccd38790..c8e9ebaff7 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodeExtensions.kt @@ -1,3 +1,7 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.lang.ast.test import net.sourceforge.pmd.lang.ast.Node diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt index ceeae52c66..bd18c52b06 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/TestUtils.kt @@ -1,3 +1,7 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + package net.sourceforge.pmd.lang.ast.test import io.kotlintest.should From e590f29da8e00b7561b2335a95243bb8d7057ad6 Mon Sep 17 00:00:00 2001 From: Rishabh Jain Date: Mon, 11 Mar 2019 22:11:24 -0400 Subject: [PATCH 12/99] issue-1701 fix bug to suppress false positive in useTryWithResources when close method have multiple arguments --- docs/pages/pmd/rules/java/bestpractices.md | 2 +- .../resources/category/java/bestpractices.xml | 2 +- .../bestpractices/xml/UseTryWithResources.xml | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/pages/pmd/rules/java/bestpractices.md b/docs/pages/pmd/rules/java/bestpractices.md index dba2d0ac36..59830977a8 100644 --- a/docs/pages/pmd/rules/java/bestpractices.md +++ b/docs/pages/pmd/rules/java/bestpractices.md @@ -1657,7 +1657,7 @@ preserved. ][ pmd-java:typeIs('java.lang.AutoCloseable') or - ../../PrimarySuffix/Arguments[@ArgumentCount = 1]//PrimaryPrefix[pmd-java:typeIs('java.lang.AutoCloseable')] + ../../PrimarySuffix/Arguments//PrimaryPrefix[pmd-java:typeIs('java.lang.AutoCloseable')] ]] ``` diff --git a/pmd-java/src/main/resources/category/java/bestpractices.xml b/pmd-java/src/main/resources/category/java/bestpractices.xml index 24fc4666fc..e21b075d6e 100644 --- a/pmd-java/src/main/resources/category/java/bestpractices.xml +++ b/pmd-java/src/main/resources/category/java/bestpractices.xml @@ -1546,7 +1546,7 @@ preserved. ][ pmd-java:typeIs('java.lang.AutoCloseable') or - ../../PrimarySuffix/Arguments[@ArgumentCount = 1]//PrimaryPrefix[pmd-java:typeIs('java.lang.AutoCloseable')] + ../../PrimarySuffix/Arguments//PrimaryPrefix[pmd-java:typeIs('java.lang.AutoCloseable')] ]] ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseTryWithResources.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseTryWithResources.xml index 5761d11723..d692e69737 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseTryWithResources.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UseTryWithResources.xml @@ -189,4 +189,28 @@ public class TryWithResources { } ]]> + + Custom close methods with multiple arguments + myClose2,myClose + 1 + 6 + + From 96a022156a5ef43e30197b88755dc52bee48313d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 12 Mar 2019 22:05:00 +0100 Subject: [PATCH 13/99] Update release notes, fixes #1701, refs #1717 --- docs/pages/release_notes.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 134ac18eb4..046b8a78ce 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -39,6 +39,9 @@ Any feedback would be greatly appreciated. ### Fixed Issues +* java-bestpractices + * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods + ### API Changes #### Deprecated API @@ -55,6 +58,7 @@ Any feedback would be greatly appreciated. * [#1704](https://github.com/pmd/pmd/pull/1704): \[java] Added AvoidUncheckedExceptionsInSignatures Rule - [Bhanu Prakash Pamidi](https://github.com/pamidi99) * [#1706](https://github.com/pmd/pmd/pull/1706): \[java] Add DetachedTestCase rule - [David Burström](https://github.com/davidburstromspotify) +* [#1717](https://github.com/pmd/pmd/pull/1717): \[java] Fix false positive in useTryWithResources when using a custom close method with multiple arguments - [Rishabh Jain](https://github.com/jainrish) {% endtocmaker %} From 83990cf0072c5cef7f64aff1cbb7c3e47d2a9482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Fraga?= Date: Tue, 12 Mar 2019 22:34:35 -0300 Subject: [PATCH 14/99] Update review changes --- .../major_contributions/adding_new_cpd_language.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md index ec248d075c..dc6d118feb 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md @@ -3,9 +3,9 @@ title: How to add a new CPD language short_title: Add a new CPD language tags: [devdocs, extending] summary: How to add a new CPD language -last_updated: July 3, 2016 +last_updated: March 20, 2019 permalink: pmd_devdocs_major_adding_new_cpd_language.html -author: Romain PELISSE +author: Matías Fraga --- First of all, thanks for the contribution! @@ -33,6 +33,9 @@ Happily for you, to add CPD support for a new language is now easier than ever! ``` +- For JavaCC grammars you should subclass [JavaCCTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/JavaCCTokenizer.java) wich has many examples you could follow, you should also take the [Python implementation](https://github.com/pmd/pmd/blob/master/pmd-python/src/main/java/net/sourceforge/pmd/cpd/PythonTokenizer.java) as reference + + - For any other scenario you can use [AnyTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java) 3. Create your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class @@ -66,4 +69,4 @@ If that's your case , you came to the right place! Why do you want GO to solve all your problems? You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) -- For non-Antlr grammars you can use [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) directly or take a peek to [Java's mbngjht8 token filter](https://github.com/pmd/pmd/blob/91e3f699f5b741b4cbc9b0cf07da91211c7a20b6/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaTokenizer.java) +- For non-Antlr grammars you can use [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) directly or take a peek to [Java's token filter](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaTokenizer.java) From 6bb8f095a2cc471c29bbaf69d3419c5ed71ef6d3 Mon Sep 17 00:00:00 2001 From: "Felix W. Dekker" Date: Fri, 15 Mar 2019 16:31:49 +0100 Subject: [PATCH 15/99] Correct property override example Fixes #1721. --- docs/pages/pmd/userdocs/configuring_rules.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/pages/pmd/userdocs/configuring_rules.md b/docs/pages/pmd/userdocs/configuring_rules.md index 8db986cf1c..f055c2d205 100644 --- a/docs/pages/pmd/userdocs/configuring_rules.md +++ b/docs/pages/pmd/userdocs/configuring_rules.md @@ -41,7 +41,9 @@ Properties make it easy to customise the behaviour of a rule directly from the x ```xml - 150 + + 150 + ``` From 6cade31996dcea64b99d4201187591e5b9161d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Fri, 15 Mar 2019 13:14:44 -0300 Subject: [PATCH 16/99] Update changelog, refs #1724 --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 05fc717cfb..a7f700fafa 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -49,6 +49,8 @@ The designer will still be shipped with PMD's binaries. ### Fixed Issues +* doc + * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods @@ -70,6 +72,7 @@ The designer will still be shipped with PMD's binaries. * [#1706](https://github.com/pmd/pmd/pull/1706): \[java] Add DetachedTestCase rule - [David Burström](https://github.com/davidburstromspotify) * [#1709](https://github.com/pmd/pmd/pull/1709): \[java] Detect while loops with literal booleans conditions - [David Burström](https://github.com/davidburstromspotify) * [#1717](https://github.com/pmd/pmd/pull/1717): \[java] Fix false positive in useTryWithResources when using a custom close method with multiple arguments - [Rishabh Jain](https://github.com/jainrish) +* [#1724](https://github.com/pmd/pmd/pull/1724): \[doc] Correct property override example - [Felix W. Dekker](https://github.com/FWDekker) {% endtocmaker %} From 8949019da6f30da205dfefe346488dd7e1c347d7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 15 Mar 2019 15:29:16 +0100 Subject: [PATCH 17/99] [java] Add Java12 support --- pmd-java/etc/grammar/Java.jjt | 74 +++++++++++++++++-- .../pmd/lang/java/JavaLanguageModule.java | 3 +- .../lang/java/ast/ASTSwitchExpression.java | 21 ++++++ .../lang/java/ast/ASTSwitchLabeledRule.java | 21 ++++++ .../java/ast/JavaParserDecoratedVisitor.java | 12 +++ .../java/ast/JavaParserVisitorAdapter.java | 10 +++ .../java/ast/JavaParserVisitorDecorator.java | 10 +++ .../pmd/lang/java/rule/AbstractJavaRule.java | 10 +++ .../pmd/lang/java/ast/Java12Test.java | 63 ++++++++++++++++ .../java12/MultipleCaseLabels.java | 21 ++++++ .../java12/SwitchExpressions.java | 31 ++++++++ .../jdkversiontests/java12/SwitchRules.java | 20 +++++ 12 files changed, 287 insertions(+), 9 deletions(-) create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/MultipleCaseLabels.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index b84165ca98..deb8d1b79a 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -378,6 +378,21 @@ public class JavaParser { throwParseException("With JDK 10, 'var' is a restricted local variable type and cannot be used for type declarations!"); } } + private void checkForMultipleCaseLabels() { + if (jdkVersion < 12) { + throwParseException("Multiple case labels in switch statements are only supported with Java 12"); + } + } + private void checkForSwitchRules() { + if (jdkVersion < 12) { + throwParseException("Switch rules in switch statements are only supported with Java 12"); + } + } + private void checkForSwitchExpression() { + if (jdkVersion < 12) { + throwParseException("Switch expressions are only supported with Java 12"); + } + } // This is a semantic LOOKAHEAD to determine if we're dealing with an assert // Note that this can't be replaced with a syntactic lookahead @@ -2006,10 +2021,14 @@ void Expression() : // https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27 {} { + LOOKAHEAD((|LambdaParameters()) "->" ) LambdaExpression() + | + ( ConditionalExpression() [ LOOKAHEAD(2) AssignmentOperator() Expression() ] + ) } void AssignmentOperator() : @@ -2140,13 +2159,14 @@ void UnaryExpressionNotPlusMinus() #UnaryExpressionNotPlusMinus((jjtn000.getImag { ( "~" {jjtThis.setImage("~");} | "!" {jjtThis.setImage("!");} ) UnaryExpression() /* - * This is really ugly... we are repeting the CastExpression lookahead and full expression... + * This is really ugly... we are repeating 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() +| SwitchExpression() } void PostfixExpression() #PostfixExpression((jjtn000.getImage() != null)): @@ -2164,6 +2184,13 @@ void CastExpression() : | "(" (TypeAnnotation())* Type() ( "&" {checkForBadIntersectionTypesInCasts(); jjtThis.setIntersectionTypes(true);} ReferenceType() )* ")" UnaryExpressionNotPlusMinus() } +void SwitchExpression() : +{} +{ + {checkForSwitchExpression();} + "switch" "(" Expression() ")" "{" SwitchBlock() "}" +} + void PrimaryExpression() : {} { @@ -2191,9 +2218,9 @@ void PrimaryPrefix() : Literal() | LOOKAHEAD(2) "this" {jjtThis.setUsesThisModifier();} | "super" {jjtThis.setUsesSuperModifier();} -| LOOKAHEAD( "->" ) LambdaExpression() -| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression() -| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression() +//| LOOKAHEAD( "->" ) LambdaExpression() +//| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression() +//| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression() | LOOKAHEAD(3) "(" Expression() ")" | AllocationExpression() | LOOKAHEAD( ResultType() "." "class" ) ResultType() "." "class" @@ -2415,20 +2442,51 @@ void StatementExpression() : PostfixExpression() } -void SwitchStatement() : +void SwitchStatement(): {} { "switch" "(" Expression() ")" "{" - ( SwitchLabel() ( BlockStatement() )* )* + SwitchBlock() "}" } +void SwitchBlock() #void : +{} +{ +( + SwitchLabel() + ( + "->" ( Expression() ";" | Block() | ThrowStatement() ) + | + ":" (SwitchLabel() ":")* ( BlockStatement() )* + ) +)* +/* + LOOKAHEAD(SwitchLabel() "->") SwitchLabeledRule() ( SwitchLabeledRule() )* + | + ( SwitchLabeledStatementGroup() )* +*/ +} + +void SwitchLabeledStatementGroup() #void: +{} +{ + SwitchLabel() ":" (SwitchLabel() ":")* ( BlockStatement() )* +} + void SwitchLabel() : {} { - "case" Expression() ":" + "case" ConditionalExpression() ({checkForMultipleCaseLabels();} "," ConditionalExpression())* | - "default" {jjtThis.setDefault();} ":" + "default" {jjtThis.setDefault();} +} + +void SwitchLabeledRule(): +{} +{ + {checkForSwitchRules();} + SwitchLabel() "->" ( Expression() ";" | Block() | ThrowStatement() ) } void IfStatement() : diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java index f5fb17220a..a62593e92c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/JavaLanguageModule.java @@ -25,7 +25,8 @@ public class JavaLanguageModule extends BaseLanguageModule { addVersion("1.8", new JavaLanguageHandler(8), false); addVersion("9", new JavaLanguageHandler(9), false); addVersion("10", new JavaLanguageHandler(10), false); - addVersion("11", new JavaLanguageHandler(11), true); + addVersion("11", new JavaLanguageHandler(11), false); + addVersion("12", new JavaLanguageHandler(12), true); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java new file mode 100644 index 0000000000..ece1206cf6 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java @@ -0,0 +1,21 @@ +/* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */ +/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package net.sourceforge.pmd.lang.java.ast; + +public +class ASTSwitchExpression extends AbstractJavaNode { + ASTSwitchExpression(int id) { + super(id); + } + + ASTSwitchExpression(JavaParser p, int id) { + super(p, id); + } + + + /** Accept the visitor. **/ + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } +} +/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java new file mode 100644 index 0000000000..b2058d2651 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java @@ -0,0 +1,21 @@ +/* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */ +/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ +package net.sourceforge.pmd.lang.java.ast; + +public +class ASTSwitchLabeledRule extends AbstractJavaNode { + ASTSwitchLabeledRule(int id) { + super(id); + } + + ASTSwitchLabeledRule(JavaParser p, int id) { + super(p, id); + } + + + /** Accept the visitor. **/ + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } +} +/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index d13a5e1ff8..1d76676124 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -868,4 +868,16 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor { visitor.visit(node, data); return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTSwitchLabeledRule node, Object data) { + visitor.visit(node, data); + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchExpression node, Object data) { + visitor.visit(node, data); + return visit((JavaNode) node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java index 210b09c0b4..721c0893c0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java @@ -600,4 +600,14 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor { public Object visit(ASTModuleName node, Object data) { return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTSwitchLabeledRule node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchExpression node, Object data) { + return visit((JavaNode) node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java index d9968afdbf..b25a36ae35 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java @@ -730,4 +730,14 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor public Object visit(ASTModuleName node, Object data) { return visitor.visit(node, data); } + + @Override + public Object visit(ASTSwitchLabeledRule node, Object data) { + return visitor.visit(node, data); + } + + @Override + public Object visit(ASTSwitchExpression node, Object data) { + return visitor.visit(node, data); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java index 0e17201d7a..f22a9c13b8 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java @@ -674,4 +674,14 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse public Object visit(ASTModuleName node, Object data) { return visit((JavaNode) node, data); } + + @Override + public Object visit(ASTSwitchLabeledRule node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchExpression node, Object data) { + return visit((JavaNode) node, data); + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java new file mode 100644 index 0000000000..fbff30b786 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -0,0 +1,63 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.lang.java.ParserTstUtil; + +public class Java12Test { + private static String loadSource(String name) { + try { + return IOUtils.toString(Java10Test.class.getResourceAsStream("jdkversiontests/java12/" + name), + StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Test(expected = ParseException.class) + public void testMultipleCaseLabelsJava11() { + ParserTstUtil.parseAndTypeResolveJava("11", loadSource("MultipleCaseLabels.java")); + } + + @Test + public void testMultipleCaseLabels() { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", + loadSource("MultipleCaseLabels.java")); + Assert.assertNotNull(compilationUnit); + } + + @Test(expected = ParseException.class) + public void testSwitchRulesJava11() { + ParserTstUtil.parseAndTypeResolveJava("11", loadSource("SwitchRules.java")); + } + + @Test + public void testSwitchRules() { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", + loadSource("SwitchRules.java")); + Assert.assertNotNull(compilationUnit); + } + + @Test(expected = ParseException.class) + public void testSwitchExpressionsJava11() { + ParserTstUtil.parseAndTypeResolveJava("11", loadSource("SwitchExpressions.java")); + } + + @Test + public void testSwitchExpressions() { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", + loadSource("SwitchExpressions.java")); + Assert.assertNotNull(compilationUnit); + } + +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/MultipleCaseLabels.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/MultipleCaseLabels.java new file mode 100644 index 0000000000..38b3b30a7c --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/MultipleCaseLabels.java @@ -0,0 +1,21 @@ +public class MultipleCaseLabels { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + + public static void main(String[] args) { + int day = THURSDAY; + + switch (day) { + case MONDAY, FRIDAY, SUNDAY: System.out.println(" 6"); break; + case TUESDAY : System.out.println(" 7"); break; + case THURSDAY, SATURDAY : System.out.println(" 8"); break; + case WEDNESDAY : System.out.println(" 9"); break; + } + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java new file mode 100644 index 0000000000..ba66110c18 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java @@ -0,0 +1,31 @@ +public class SwitchExpressions { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + + public static void main(String[] args) { + int day = FRIDAY; + + int numLetters = switch (day) { + case MONDAY, FRIDAY, SUNDAY -> 6; + case TUESDAY -> 7; + case THURSDAY, SATURDAY -> 8; + case WEDNESDAY -> 9; + default -> { + int k = day * 2; + int result = f(k); + break result; + } + }; + System.out.printf("NumLetters: %d%n", numLetters); + } + + private static int f(int k) { + return k*3; + } +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java new file mode 100644 index 0000000000..52bb00cb33 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java @@ -0,0 +1,20 @@ +public class SwitchRules { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + public static void main(String[] args) { + int day = WEDNESDAY; + + switch (day) { + case MONDAY, FRIDAY, SUNDAY -> System.out.println(" 6"); + case TUESDAY -> System.out.println(" 7"); + case THURSDAY, SATURDAY -> System.out.println(" 8"); + case WEDNESDAY -> System.out.println(" 9"); + } + } +} From 65cac51445f8160876705a18d00c84d70c3aa7be Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 15 Mar 2019 20:51:53 +0100 Subject: [PATCH 18/99] [java] Add Java12 support --- pmd-java/etc/grammar/Java.jjt | 76 ++++++++++++------- .../lang/java/ast/ASTSwitchExpression.java | 29 +++---- .../lang/java/ast/ASTSwitchLabeledRule.java | 29 +++---- .../pmd/LanguageVersionDiscovererTest.java | 6 +- .../pmd/lang/java/ast/Java12Test.java | 27 +++++++ .../jdkversiontests/java12/SwitchRules.java | 3 +- 6 files changed, 114 insertions(+), 56 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index deb8d1b79a..62c2b77929 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -383,6 +383,15 @@ public class JavaParser { throwParseException("Multiple case labels in switch statements are only supported with Java 12"); } } + /** + * Keeps track during tree construction, whether we are currently building a switch label. + * A switch label must not contain a LambdaExpression. + * Unfortunately, we have added LambdaExpression as part of PrimaryPrefix, which is wrong. + * To keep compatibility, this flag is used, whether a LambdaExpression should be parsed + * in PrimaryPrefix. + * See also comment at #Expression(). + */ + private boolean inSwitchLabel = false; private void checkForSwitchRules() { if (jdkVersion < 12) { throwParseException("Switch rules in switch statements are only supported with Java 12"); @@ -424,6 +433,26 @@ public class JavaParser { return getToken(1).kind == IDENTIFIER && getToken(1).image.equals(keyword); } + /** + * Semantic lookahead needed to distinguish between switch rules + * and switch statement. Using the syntactic lookahead for SwitchLabel() + * does not work, during lookahead the javacode is not executed, so + * that "->" is already consumed as a LambdaExpression, when it is actually + * part of the switch rule. See also #inSwitchLabel. + */ + private boolean switchLabeledRuleLookahead(int maxTokens) { + int pos = 0; + + while (pos < maxTokens) { + Token token = getToken(pos); + pos++; + + if (token.kind == COLON) return false; + if (token.kind == LAMBDA) return true; + } + return false; + } + public Map getSuppressMap() { return token_source.getSuppressMap(); } @@ -2019,16 +2048,15 @@ void Expression() : // separated from the AssignmentExpression production. Their use is restricted // to method and constructor argument, cast operand, and the RHS of assignments. // https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27 + // + // To prevent LambdaExpressions in switch labels, the field #inSwitchLabel is used + // as a workaround. {} { - LOOKAHEAD((|LambdaParameters()) "->" ) LambdaExpression() - | - ( ConditionalExpression() [ LOOKAHEAD(2) AssignmentOperator() Expression() ] - ) } void AssignmentOperator() : @@ -2188,7 +2216,7 @@ void SwitchExpression() : {} { {checkForSwitchExpression();} - "switch" "(" Expression() ")" "{" SwitchBlock() "}" + "switch" "(" Expression() ")" SwitchBlock() } void PrimaryExpression() : @@ -2218,9 +2246,9 @@ void PrimaryPrefix() : Literal() | LOOKAHEAD(2) "this" {jjtThis.setUsesThisModifier();} | "super" {jjtThis.setUsesSuperModifier();} -//| LOOKAHEAD( "->" ) LambdaExpression() -//| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression() -//| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression() +| LOOKAHEAD( "->", {!inSwitchLabel} ) LambdaExpression() +| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->", {!inSwitchLabel} ) LambdaExpression() +| LOOKAHEAD( FormalParameters() "->", {!inSwitchLabel} ) LambdaExpression() | LOOKAHEAD(3) "(" Expression() ")" | AllocationExpression() | LOOKAHEAD( ResultType() "." "class" ) ResultType() "." "class" @@ -2445,41 +2473,37 @@ void StatementExpression() : void SwitchStatement(): {} { - "switch" "(" Expression() ")" "{" - SwitchBlock() - "}" + "switch" "(" Expression() ")" SwitchBlock() } void SwitchBlock() #void : {} { -( - SwitchLabel() - ( - "->" ( Expression() ";" | Block() | ThrowStatement() ) - | - ":" (SwitchLabel() ":")* ( BlockStatement() )* - ) -)* -/* - LOOKAHEAD(SwitchLabel() "->") SwitchLabeledRule() ( SwitchLabeledRule() )* - | - ( SwitchLabeledStatementGroup() )* -*/ + "{" + ( + LOOKAHEAD( { switchLabeledRuleLookahead(10) } ) ( SwitchLabeledRule() )+ + | + (LOOKAHEAD(3) SwitchLabeledStatementGroup() )* (SwitchLabel() ":")* + ) + "}" } void SwitchLabeledStatementGroup() #void: {} { - SwitchLabel() ":" (SwitchLabel() ":")* ( BlockStatement() )* + (SwitchLabel() ":")+ ( BlockStatement() )+ } void SwitchLabel() : {} { - "case" ConditionalExpression() ({checkForMultipleCaseLabels();} "," ConditionalExpression())* +{ inSwitchLabel = true; } +( + "case" ( ConditionalExpression() #Expression ) ({checkForMultipleCaseLabels();} "," ( ConditionalExpression() #Expression ) )* | "default" {jjtThis.setDefault();} +) +{ inSwitchLabel = false; } } void SwitchLabeledRule(): diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java index ece1206cf6..4b02eaf9dc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java @@ -1,21 +1,24 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + /* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */ /* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ + package net.sourceforge.pmd.lang.java.ast; -public -class ASTSwitchExpression extends AbstractJavaNode { - ASTSwitchExpression(int id) { - super(id); - } +public class ASTSwitchExpression extends AbstractJavaNode { + ASTSwitchExpression(int id) { + super(id); + } - ASTSwitchExpression(JavaParser p, int id) { - super(p, id); - } + ASTSwitchExpression(JavaParser p, int id) { + super(p, id); + } - - /** Accept the visitor. **/ - public Object jjtAccept(JavaParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } } /* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java index b2058d2651..eed26a4f06 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java @@ -1,21 +1,24 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + /* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */ /* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ + package net.sourceforge.pmd.lang.java.ast; -public -class ASTSwitchLabeledRule extends AbstractJavaNode { - ASTSwitchLabeledRule(int id) { - super(id); - } +public class ASTSwitchLabeledRule extends AbstractJavaNode { + ASTSwitchLabeledRule(int id) { + super(id); + } - ASTSwitchLabeledRule(JavaParser p, int id) { - super(p, id); - } + ASTSwitchLabeledRule(JavaParser p, int id) { + super(p, id); + } - - /** Accept the visitor. **/ - public Object jjtAccept(JavaParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } } /* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java index f2972b1407..f17c8e9693 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/LanguageVersionDiscovererTest.java @@ -26,8 +26,8 @@ public class LanguageVersionDiscovererTest { File javaFile = new File("/path/to/MyClass.java"); LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(javaFile); - assertEquals("LanguageVersion must be Java 11 !", - LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), languageVersion); + assertEquals("LanguageVersion must be Java 12 !", + LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("12"), languageVersion); } /** @@ -48,7 +48,7 @@ public class LanguageVersionDiscovererTest { public void testLanguageVersionDiscoverer() { PMDConfiguration configuration = new PMDConfiguration(); LanguageVersionDiscoverer languageVersionDiscoverer = configuration.getLanguageVersionDiscoverer(); - assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), + assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("12"), languageVersionDiscoverer .getDefaultLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME))); configuration diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index fbff30b786..b18bc5d0a7 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -34,6 +34,11 @@ public class Java12Test { ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", loadSource("MultipleCaseLabels.java")); Assert.assertNotNull(compilationUnit); + ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); + Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression); + Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabel); + ASTSwitchLabel switchLabel = switchStatement.getFirstChildOfType(ASTSwitchLabel.class); + Assert.assertEquals(3, switchLabel.findChildrenOfType(ASTExpression.class).size()); } @Test(expected = ParseException.class) @@ -46,6 +51,23 @@ public class Java12Test { ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", loadSource("SwitchRules.java")); Assert.assertNotNull(compilationUnit); + ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); + Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression); + Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabeledRule); + ASTSwitchLabeledRule switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(1); + Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTExpression); + + switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(4); + Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTBlock); + + switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(5); + Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTThrowStatement); } @Test(expected = ParseException.class) @@ -58,6 +80,11 @@ public class Java12Test { ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", loadSource("SwitchExpressions.java")); Assert.assertNotNull(compilationUnit); + + ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class); + Assert.assertEquals(6, switchExpression.jjtGetNumChildren()); + Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); + Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size()); } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java index 52bb00cb33..54e2e76d03 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchRules.java @@ -14,7 +14,8 @@ public class SwitchRules { case MONDAY, FRIDAY, SUNDAY -> System.out.println(" 6"); case TUESDAY -> System.out.println(" 7"); case THURSDAY, SATURDAY -> System.out.println(" 8"); - case WEDNESDAY -> System.out.println(" 9"); + case WEDNESDAY -> { System.out.println(" 9"); } + default -> throw new IllegalArgumentException(); } } } From 2db0ab21cf34f38627cbd74bdb937f07ae3dfc33 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 15 Mar 2019 20:55:53 +0100 Subject: [PATCH 19/99] [java] Update asm to 7.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 040a0a0dbc..fd1e74009b 100644 --- a/pom.xml +++ b/pom.xml @@ -823,7 +823,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code org.ow2.asm asm - 7.0 + 7.1 net.sourceforge.pmd From 335d1384246af74108b3ec9d499d8ad8e05d7630 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 15 Mar 2019 21:05:21 +0100 Subject: [PATCH 20/99] Introduce env variable PMD_JAVA_OPTS That way, additional java options can be set for executing PMD --- pmd-dist/src/main/resources/scripts/bgastviewer.bat | 2 +- pmd-dist/src/main/resources/scripts/cpd.bat | 2 +- pmd-dist/src/main/resources/scripts/cpdgui.bat | 2 +- pmd-dist/src/main/resources/scripts/designer.bat | 2 +- pmd-dist/src/main/resources/scripts/designerold.bat | 2 +- pmd-dist/src/main/resources/scripts/pmd.bat | 2 +- pmd-dist/src/main/resources/scripts/run.sh | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pmd-dist/src/main/resources/scripts/bgastviewer.bat b/pmd-dist/src/main/resources/scripts/bgastviewer.bat index 4b3cca4706..56f460db48 100644 --- a/pmd-dist/src/main/resources/scripts/bgastviewer.bat +++ b/pmd-dist/src/main/resources/scripts/bgastviewer.bat @@ -3,4 +3,4 @@ set TOPDIR=%~dp0.. set OPTS= set MAIN_CLASS=net.sourceforge.pmd.util.viewer.Viewer -java -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/cpd.bat b/pmd-dist/src/main/resources/scripts/cpd.bat index 5e51778d24..dbdda1876a 100644 --- a/pmd-dist/src/main/resources/scripts/cpd.bat +++ b/pmd-dist/src/main/resources/scripts/cpd.bat @@ -3,4 +3,4 @@ set TOPDIR=%~dp0.. set OPTS= set MAIN_CLASS=net.sourceforge.pmd.cpd.CPD -java -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/cpdgui.bat b/pmd-dist/src/main/resources/scripts/cpdgui.bat index bd8a735c68..38ce3ffba5 100755 --- a/pmd-dist/src/main/resources/scripts/cpdgui.bat +++ b/pmd-dist/src/main/resources/scripts/cpdgui.bat @@ -3,4 +3,4 @@ set TOPDIR=%~dp0.. set OPTS= set MAIN_CLASS=net.sourceforge.pmd.cpd.GUI -java -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/designer.bat b/pmd-dist/src/main/resources/scripts/designer.bat index 60a4fecc63..b33e9af195 100644 --- a/pmd-dist/src/main/resources/scripts/designer.bat +++ b/pmd-dist/src/main/resources/scripts/designer.bat @@ -48,4 +48,4 @@ if %_needjfxlib% EQU 1 ( ) -java %jreopts% -classpath "%classpath%" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% %jreopts% -classpath "%classpath%" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/designerold.bat b/pmd-dist/src/main/resources/scripts/designerold.bat index 2135370459..d41f262202 100644 --- a/pmd-dist/src/main/resources/scripts/designerold.bat +++ b/pmd-dist/src/main/resources/scripts/designerold.bat @@ -3,4 +3,4 @@ set TOPDIR=%~dp0.. set OPTS= set MAIN_CLASS=net.sourceforge.pmd.util.designer.Designer -java -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/pmd.bat b/pmd-dist/src/main/resources/scripts/pmd.bat index bb9b1d739e..0a5d79e129 100755 --- a/pmd-dist/src/main/resources/scripts/pmd.bat +++ b/pmd-dist/src/main/resources/scripts/pmd.bat @@ -3,4 +3,4 @@ set TOPDIR=%~dp0.. set OPTS= set MAIN_CLASS=net.sourceforge.pmd.PMD -java -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* +java %PMD_JAVA_OPTS% -classpath "%TOPDIR%\lib\*" %OPTS% %MAIN_CLASS% %* diff --git a/pmd-dist/src/main/resources/scripts/run.sh b/pmd-dist/src/main/resources/scripts/run.sh index 79e4ef609e..3a6636a8a1 100755 --- a/pmd-dist/src/main/resources/scripts/run.sh +++ b/pmd-dist/src/main/resources/scripts/run.sh @@ -215,4 +215,4 @@ cygwin_paths java_heapsize_settings -java ${HEAPSIZE} $(jre_specific_vm_options) -cp "${classpath}" "${CLASSNAME}" "$@" +java ${HEAPSIZE} ${PMD_JAVA_OPTS} $(jre_specific_vm_options) -cp "${classpath}" "${CLASSNAME}" "$@" From f5bc7031f59465088360a32f42f93f6378650189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 16 Mar 2019 07:15:03 +0100 Subject: [PATCH 21/99] Add structure tests --- .../pmd/lang/java/ast/KotlinTestingDsl.kt | 2 +- .../lang/java/ast/SwitchExpressionTests.kt | 246 ++++++++++++++++++ 2 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt index 388f2372f8..5f6ca05c1f 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/KotlinTestingDsl.kt @@ -11,7 +11,7 @@ import io.kotlintest.should as kotlintestShould * Represents the different Java language versions. */ enum class JavaVersion : Comparable { - J1_3, J1_4, J1_5, J1_6, J1_7, J1_8, J9, J10, J11; + J1_3, J1_4, J1_5, J1_6, J1_7, J1_8, J9, J10, J11, J12; /** Name suitable for use with e.g. [ParserTstUtil.parseAndTypeResolveJava] */ val pmdName: String = name.removePrefix("J").replace('_', '.') diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt new file mode 100644 index 0000000000..be4036cd79 --- /dev/null +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt @@ -0,0 +1,246 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast + +import io.kotlintest.shouldBe + +/** + * @author Clément Fournier + */ +class ASTSwitchExpressionTests : ParserTestSpec({ + + + parserTest("Simple switch expressions") { + + + """ + switch (day) { + case FRIDAY, SUNDAY -> 6; + case WEDNESDAY -> 9; + default -> { + int k = day * 2; + int result = f(k); + break result; + } + } + """.trimIndent() should matchExpr { + + child { + + child { + + child { + + child { + it.image shouldBe "day" + } + } + } + } + + child { + + child { + it.isDefault shouldBe false + + child { + + child { + + child { + + child { + it.image shouldBe "FRIDAY" + } + } + } + } + + child { + it.isStandAlonePrimitive shouldBe false + + child { + + child { + + child { + it.image shouldBe "SUNDAY" + } + } + } + } + } + + child(ignoreChildren = true) {} + + } + + child { + + child { + it.isDefault shouldBe false + + child { + it.isStandAlonePrimitive shouldBe false + + child { + + child { + + child { + it.nameDeclaration shouldBe null + } + } + } + } + } + + child(ignoreChildren = true) {} + } + + child { + + child { + it.isDefault shouldBe true + } + + child { + + child(ignoreChildren = true) {} + child(ignoreChildren = true) {} + + child { + child { + child {} + } + } + } + } + } + } + + + parserTest("Switch statement with non-fallthrough labels") { + + """ + switch (day) { + case THURSDAY, SATURDAY -> System.out.println(" 8"); + case WEDNESDAY -> System.out.println(" 9"); + } + """.trimIndent() should matchStmt { + it.isExhaustiveEnumSwitch shouldBe false + + it.testedExpression shouldBe child { + child { + child { + child { + it.image shouldBe "day" + } + } + } + } + + child { + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + child(ignoreChildren = true) {} + } + + child(ignoreChildren = true) {} + } + + child { + + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + } + + child(ignoreChildren = true) {} + } + } + + } + + parserTest("Fallthrough switch statement") { + + """ + switch (day) { + case TUESDAY : System.out.println(" 7"); break; + case THURSDAY, SATURDAY : System.out.println(" 8"); break; + default : break; + } + """.trimIndent() should matchStmt { + it.isExhaustiveEnumSwitch shouldBe false + + it.testedExpression shouldBe child { + child { + child { + child { + it.image shouldBe "day" + } + } + } + } + + + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + } + + child { + child { + child { + child(ignoreChildren = true) {} + } + } + } + + child { + child { + child {} + } + } + + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + child(ignoreChildren = true) {} + } + + child { + child { + child { + child(ignoreChildren = true) {} + } + } + } + + child { + child { + child {} + } + } + + child { + it.isDefault shouldBe true + } + + child { + child { + child {} + } + } + } + } + + +}) From 2793c3e0292d8012fd09d0e63c13c724942d4d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sat, 16 Mar 2019 07:53:02 +0100 Subject: [PATCH 22/99] Remove arbitrary lookahead --- pmd-java/etc/grammar/Java.jjt | 54 +++--- .../lang/java/ast/SwitchExpressionTests.kt | 156 ++++++++++++++++++ 2 files changed, 175 insertions(+), 35 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 62c2b77929..8b1eaa979d 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -403,6 +403,8 @@ public class JavaParser { } } + private boolean inFallthroughSwitchCase = false; + // This is a semantic LOOKAHEAD to determine if we're dealing with an assert // Note that this can't be replaced with a syntactic lookahead // since "assert" isn't a string literal token @@ -433,26 +435,6 @@ public class JavaParser { return getToken(1).kind == IDENTIFIER && getToken(1).image.equals(keyword); } - /** - * Semantic lookahead needed to distinguish between switch rules - * and switch statement. Using the syntactic lookahead for SwitchLabel() - * does not work, during lookahead the javacode is not executed, so - * that "->" is already consumed as a LambdaExpression, when it is actually - * part of the switch rule. See also #inSwitchLabel. - */ - private boolean switchLabeledRuleLookahead(int maxTokens) { - int pos = 0; - - while (pos < maxTokens) { - Token token = getToken(pos); - pos++; - - if (token.kind == COLON) return false; - if (token.kind == LAMBDA) return true; - } - return false; - } - public Map getSuppressMap() { return token_source.getSuppressMap(); } @@ -2480,18 +2462,9 @@ void SwitchBlock() #void : {} { "{" - ( - LOOKAHEAD( { switchLabeledRuleLookahead(10) } ) ( SwitchLabeledRule() )+ - | - (LOOKAHEAD(3) SwitchLabeledStatementGroup() )* (SwitchLabel() ":")* - ) - "}" -} -void SwitchLabeledStatementGroup() #void: -{} -{ - (SwitchLabel() ":")+ ( BlockStatement() )+ + (SwitchLabeledRule())* + "}" } void SwitchLabel() : @@ -2506,11 +2479,22 @@ void SwitchLabel() : { inSwitchLabel = false; } } -void SwitchLabeledRule(): -{} +// only pushed if it's not a fallthrough, for compatibility +void SwitchLabeledRule() #SwitchLabeledRule(!inFallthroughSwitchCase): { - {checkForSwitchRules();} - SwitchLabel() "->" ( Expression() ";" | Block() | ThrowStatement() ) + boolean prevFallthrough = inFallthroughSwitchCase; + inFallthroughSwitchCase = false; +} +{ + SwitchLabel() + ( "->" {checkForSwitchRules();} | ":" {inFallthroughSwitchCase = true;}) + (LOOKAHEAD({inFallthroughSwitchCase}) + ( BlockStatement() )* + | ( Expression() ";" | Block () | ThrowStatement() ) + ) + { + inFallthroughSwitchCase = prevFallthrough; // restore + } } void IfStatement() : diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt index be4036cd79..52380ac11b 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt @@ -122,6 +122,162 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } + parserTest("Nested switch expressions") { + + + """ + switch (day) { + case FRIDAY -> 6; + case WEDNESDAY -> switch (foo) { + case 2 -> 5; + default -> 3; + }; + default -> 3; + } + """.trimIndent() should matchExpr { + + child { + + child { + + child { + + child { + it.image shouldBe "day" + } + } + } + } + + child { + + child { + it.isDefault shouldBe false + + child { + child { + child { + child { + it.image shouldBe "FRIDAY" + } + } + } + } + + } + + child(ignoreChildren = true) {} + + } + + child { + + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + } + + child { + + + child { + child(ignoreChildren = true) {} + + child { + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + } + child(ignoreChildren = true) {} + + } + child { + child { + it.isDefault shouldBe true + } + child(ignoreChildren = true) {} + } + } + + } + } + + child { + + child { + it.isDefault shouldBe true + } + + child(ignoreChildren = true) {} + } + } + } + + + parserTest("Non-fallthrough nested in fallthrough") { + + + """ + switch (day) { + case FRIDAY: foo(); break; + case WEDNESDAY : switch (foo) { + case 2 -> 5; + default -> 3; + } + default : bar(); + } + """.trimIndent() should matchStmt { + it.isExhaustiveEnumSwitch shouldBe false + + it.testedExpression shouldBe child(ignoreChildren = true) {} + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + + } + child { + child { + child(ignoreChildren = true) {} + } + } + child { + child { + child {} + } + } + child { + it.isDefault shouldBe false + + child(ignoreChildren = true) {} + + } + child { + child { + child { + + it.testedExpression shouldBe child(ignoreChildren = true) {} + + child(ignoreChildren = true) {} + child(ignoreChildren = true) {} + + } + } + } + child { + it.isDefault shouldBe true + } + child { + child { + child(ignoreChildren = true) {} + } + } + } + } + + parserTest("Switch statement with non-fallthrough labels") { """ From ca0975b68f09a0a6b305825e24def9d3cf281292 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 09:22:51 +0100 Subject: [PATCH 23/99] Add additional tests * Parse problem with switch fallthrough * Verify type of switch expression --- .../pmd/lang/java/ast/ASTSwitchExpression.java | 2 +- .../net/sourceforge/pmd/lang/java/ast/Java12Test.java | 2 ++ .../pmd/lang/java/ast/ParserCornersTest.java | 8 ++++++++ .../pmd/lang/java/ast/SwitchWithFallthrough.java | 11 +++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.java diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java index 4b02eaf9dc..ea929b3aa6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchExpression.java @@ -7,7 +7,7 @@ package net.sourceforge.pmd.lang.java.ast; -public class ASTSwitchExpression extends AbstractJavaNode { +public class ASTSwitchExpression extends AbstractJavaTypeNode { ASTSwitchExpression(int id) { super(id); } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index b18bc5d0a7..5757e9b2aa 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -85,6 +85,8 @@ public class Java12Test { Assert.assertEquals(6, switchExpression.jjtGetNumChildren()); Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size()); + + Assert.assertEquals(Integer.TYPE, switchExpression.getType()); } } 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 a74222b92c..936babbb12 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 @@ -274,6 +274,14 @@ public class ParserCornersTest { Assert.assertTrue("Test setup wrong - variable 'someVarNameSameAsMethodReference' not found anymore!", foundVariable); } + @Test + public void testSwitchWithFallthrough() throws Exception { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("11", readAsString("SwitchWithFallthrough.java")); + Assert.assertNotNull(compilationUnit); + ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); + Assert.assertEquals(2, switchStatement.findChildrenOfType(ASTSwitchLabel.class).size()); + } + private String readAsString(String resource) { try (InputStream in = ParserCornersTest.class.getResourceAsStream(resource)) { return IOUtils.toString(in, StandardCharsets.UTF_8); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.java new file mode 100644 index 0000000000..0e3b07a5da --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchWithFallthrough.java @@ -0,0 +1,11 @@ +public class SwitchWithFallthrough { + + // only fall through, no block statements. + public void myMethod() { + int a = 1; + switch (a) { + case 1: + default: + } + } +} \ No newline at end of file From 607b4d1e6cdbbedd03925d54dc1f330b2a763ba2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 09:59:03 +0100 Subject: [PATCH 24/99] [java] ASTLiteral should only try to parse the value, if it makes sense This avoids number format exceptions when trying to parse a String as a double. --- .../pmd/lang/java/ast/ASTLiteral.java | 26 ++++++++++++++----- .../pmd/lang/java/ast/ASTLiteralTest.java | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java index 2a18732390..84931aa4d5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTLiteral.java @@ -147,22 +147,34 @@ public class ASTLiteral extends AbstractJavaTypeNode { } public int getValueAsInt() { - // the downcast allows to parse 0x80000000+ numbers as negative instead of a NumberFormatException - return (int) getValueAsLong(); + if (isInt) { + // the downcast allows to parse 0x80000000+ numbers as negative instead of a NumberFormatException + return (int) getValueAsLong(); + } + return 0; } public long getValueAsLong() { - // Using BigInteger to allow parsing 0x8000000000000000+ numbers as negative instead of a NumberFormatException - BigInteger bigInt = new BigInteger(stripIntValue(), getIntBase()); - return bigInt.longValue(); + if (isInt) { + // Using BigInteger to allow parsing 0x8000000000000000+ numbers as negative instead of a NumberFormatException + BigInteger bigInt = new BigInteger(stripIntValue(), getIntBase()); + return bigInt.longValue(); + } + return 0L; } public float getValueAsFloat() { - return Float.parseFloat(stripFloatValue()); + if (isFloat) { + return Float.parseFloat(stripFloatValue()); + } + return Float.NaN; } public double getValueAsDouble() { - return Double.parseDouble(stripFloatValue()); + if (isFloat) { + return Double.parseDouble(stripFloatValue()); + } + return Double.NaN; } public void setCharLiteral() { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ASTLiteralTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ASTLiteralTest.java index eb99628175..81e1c93f20 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ASTLiteralTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/ASTLiteralTest.java @@ -92,7 +92,7 @@ public class ASTLiteralTest { @Test public void testFloatValueParsingNegative() { ASTLiteral literal = new ASTLiteral(1); - literal.setIntLiteral(); + literal.setFloatLiteral(); literal.setImage("-3_456.123_456"); literal.testingOnlySetBeginColumn(1); literal.testingOnlySetEndColumn(7); From 6658dc3383a15bdddcdafc199761c9a9158198b5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 10:35:05 +0100 Subject: [PATCH 25/99] Support type resolution for SwitchExpressions --- .../typeresolution/ClassTypeResolver.java | 43 +++++++++++++++++++ .../pmd/lang/java/ast/Java12Test.java | 3 ++ .../java12/SwitchExpressions.java | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 7f3c9fb322..16dab79549 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -31,7 +31,10 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTArgumentList; import net.sourceforge.pmd.lang.java.ast.ASTArguments; import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits; +import net.sourceforge.pmd.lang.java.ast.ASTBlock; +import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement; import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral; +import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.java.ast.ASTCastExpression; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType; @@ -72,6 +75,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTResource; import net.sourceforge.pmd.lang.java.ast.ASTShiftExpression; import net.sourceforge.pmd.lang.java.ast.ASTSingleMemberAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabeledRule; import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTTypeArgument; import net.sourceforge.pmd.lang.java.ast.ASTTypeArguments; @@ -1174,6 +1179,44 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { return data; } + @Override + public Object visit(ASTSwitchExpression node, Object data) { + super.visit(node, data); + + JavaTypeDefinition type = null; + // first try to determine the type based on the first expression/break of a switch rule + List rules = node.findChildrenOfType(ASTSwitchLabeledRule.class); + for (ASTSwitchLabeledRule rule : rules) { + Node body = rule.jjtGetChild(1); // second child is either Expression, Block, ThrowStatement + if (body instanceof ASTExpression) { + type = ((ASTExpression) body).getTypeDefinition(); + break; + } else if (body instanceof ASTBlock) { + List breaks = body.findDescendantsOfType(ASTBreakStatement.class); + if (!breaks.isEmpty()) { + //TODO: check for break statements + //type = breaks.get(0).getExpression().getType(); + //break; + } + } + } + if (type == null) { + // now check the labels and their expressions, breaks + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + Node child = node.jjtGetChild(i); + if (child instanceof ASTBlockStatement) { + List breakStatement = child.findDescendantsOfType(ASTBreakStatement.class); + //TODO: check for break statements + //type = breakStatement.getExpression().getType(); + //break; + } + } + } + + node.setTypeDefinition(type); + return data; + } + @Override public Object visit(ASTFormalParameter node, Object data) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index 5757e9b2aa..601692e3f8 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -86,6 +86,9 @@ public class Java12Test { Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size()); + ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); + ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); + Assert.assertEquals(Integer.TYPE, localVarDecl.getType()); Assert.assertEquals(Integer.TYPE, switchExpression.getType()); } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java index ba66110c18..04b47b20ae 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressions.java @@ -11,7 +11,7 @@ public class SwitchExpressions { public static void main(String[] args) { int day = FRIDAY; - int numLetters = switch (day) { + var numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; From d7aa1b17421e0927cdafa0da17389eca09925d88 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 10:47:12 +0100 Subject: [PATCH 26/99] Support Expression in break statements --- pmd-java/etc/grammar/Java.jjt | 8 ++++- .../typeresolution/ClassTypeResolver.java | 22 ++++++++----- .../pmd/lang/java/ast/Java12Test.java | 17 ++++++++++ .../java12/SwitchExpressionsBreak.java | 31 +++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 8b1eaa979d..82bd933701 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -405,6 +405,12 @@ public class JavaParser { private boolean inFallthroughSwitchCase = false; + private void checkForBreakExpression() { + if (jdkVersion < 12) { + throwParseException("Expressions in break statements are only supported with Java 12"); + } + } + // This is a semantic LOOKAHEAD to determine if we're dealing with an assert // Note that this can't be replaced with a syntactic lookahead // since "assert" isn't a string literal token @@ -2560,7 +2566,7 @@ void ForUpdate() : void BreakStatement() : {Token t;} { - "break" [ t= {jjtThis.setImage(t.image);} ] ";" + "break" [ LOOKAHEAD(1) t= {jjtThis.setImage(t.image);} | Expression() {checkForBreakExpression();} ] ";" } void ContinueStatement() : diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 16dab79549..4883668d0a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -1194,21 +1194,27 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { } else if (body instanceof ASTBlock) { List breaks = body.findDescendantsOfType(ASTBreakStatement.class); if (!breaks.isEmpty()) { - //TODO: check for break statements - //type = breaks.get(0).getExpression().getType(); - //break; + ASTExpression expression = breaks.get(0).getFirstChildOfType(ASTExpression.class); + if (expression != null) { + type = expression.getTypeDefinition(); + break; + } } } } if (type == null) { - // now check the labels and their expressions, breaks + // now check the labels and their expressions of break statements for (int i = 0; i < node.jjtGetNumChildren(); i++) { Node child = node.jjtGetChild(i); if (child instanceof ASTBlockStatement) { - List breakStatement = child.findDescendantsOfType(ASTBreakStatement.class); - //TODO: check for break statements - //type = breakStatement.getExpression().getType(); - //break; + List breaks = child.findDescendantsOfType(ASTBreakStatement.class); + if (!breaks.isEmpty()) { + ASTExpression expression = breaks.get(0).getFirstChildOfType(ASTExpression.class); + if (expression != null) { + type = expression.getTypeDefinition(); + break; + } + } } } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index 601692e3f8..d75aff5737 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -92,4 +92,21 @@ public class Java12Test { Assert.assertEquals(Integer.TYPE, switchExpression.getType()); } + @Test + public void testSwitchExpressionsBreak() { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12", + loadSource("SwitchExpressionsBreak.java")); + Assert.assertNotNull(compilationUnit); + + ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class); + Assert.assertEquals(11, switchExpression.jjtGetNumChildren()); + Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); + Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabel.class).size()); + + ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); + ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); + Assert.assertEquals(Integer.TYPE, localVarDecl.getType()); + Assert.assertEquals(Integer.TYPE, switchExpression.getType()); + } + } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java new file mode 100644 index 0000000000..b25b54ed05 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java @@ -0,0 +1,31 @@ +public class SwitchExpressionsBreak { + private static final int MONDAY = 1; + private static final int TUESDAY = 2; + private static final int WEDNESDAY = 3; + private static final int THURSDAY = 4; + private static final int FRIDAY = 5; + private static final int SATURDAY = 6; + private static final int SUNDAY = 7; + + + public static void main(String[] args) { + int day = FRIDAY; + + var numLetters = switch (day) { + case MONDAY, FRIDAY, SUNDAY: break 6; + case TUESDAY : break 7; + case THURSDAY, SATURDAY : break 8; + case WEDNESDAY : break 9; + default : { + int k = day * 2; + int result = f(k); + break result; + } + }; + System.out.printf("NumLetters: %d%n", numLetters); + } + + private static int f(int k) { + return k*3; + } +} From e36e01c09313da8c5653e2312f29192d2d0f3abd Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 11:39:35 +0100 Subject: [PATCH 27/99] [doc] Mention PMD_JAVA_OPTS --- docs/pages/pmd/userdocs/cli_reference.md | 10 ++++++++++ docs/pages/pmd/userdocs/cpd.md | 10 +++++++--- docs/pages/release_notes.md | 8 ++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/pages/pmd/userdocs/cli_reference.md b/docs/pages/pmd/userdocs/cli_reference.md index f1e380e6f5..68909b97a1 100644 --- a/docs/pages/pmd/userdocs/cli_reference.md +++ b/docs/pages/pmd/userdocs/cli_reference.md @@ -150,6 +150,16 @@ The tool comes with a rather extensive help text, simply running with `-help`! %} +## Additional Java Runtime Options + +PMD is executed via a Java runtime. In some cases, you might need to set additional runtime options, e.g. +if you want to analyze a project, that uses one of OpenJDK's [Preview Language Features](http://openjdk.java.net/jeps/12). + +Just set the environment variable `PMD_JAVA_OPTS` before executing PMD, e.g. + + export PMD_JAVA_OPTS="--enable-preview" + ./run.sh pmd -d ../../../src/main/java/ -f text -R rulesets/java/quickstart.xml + ## Exit Status Please note that if PMD detects any violations, it will exit with status 4 (since 5.3). diff --git a/docs/pages/pmd/userdocs/cpd.md b/docs/pages/pmd/userdocs/cpd.md index ee3e842ea1..8545fd4fbb 100644 --- a/docs/pages/pmd/userdocs/cpd.md +++ b/docs/pages/pmd/userdocs/cpd.md @@ -178,11 +178,15 @@ The default format is a text report, and there's also a `csv` report. Note that CPD is pretty memory-hungry; you may need to give Java more memory to run it, like this: - $ export HEAPSIZE=512m + $ export PMD_JAVA_OPTS=-Xmx512m $ ./run.sh cpd --minimum-tokens 100 --files /usr/local/java/src/java -In order to change the heap size under Windows, you'll need to edit the batch file `cpd.bat` set the "OPTS" -variable to `-Xmx512m`. +In order to change the heap size under Windows, you'll need to edit the batch file `cpd.bat` or +set the environment variable `PMD_JAVA_OPTS` prior to starting CPD: + + C:\ > cd C:\pmd-bin-{{site.pmd.version}}\bin + C:\...\bin > set PMD_JAVA_OPTS=-Xmx512m + C:\...\bin > .\cpd.bat --minimum-tokens 100 --files c:\temp\src If you specify a source directory but don't want to scan the sub-directories, you can use the non-recursive option: diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index a7f700fafa..967c6f1a61 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -56,6 +56,14 @@ The designer will still be shipped with PMD's binaries. ### API Changes +#### Command Line Interface + +The start scripts `run.sh`, `pmd.bat` and `cpd.bat` support the new environment variable `PMD_JAVA_OPTS`. +This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. `PMD_JAVA_OPTS=-Xmx512m`) +or enable preview language features (e.g. `PMD_JAVA_OPTS=--enable-preview`). + +The previously available variables such as `OPTS` or `HEAPSIZE` are deprecated and will be removed with PMD 7.0.0. + #### Deprecated API * {% jdoc core::renderers.CodeClimateRule %} is deprecated in 7.0.0 because it was unused for 2 years and From 3061a6d8c5377b45d43f14ece45df154c4e747bd Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 11:45:32 +0100 Subject: [PATCH 28/99] Update release notes, fixes #1537 --- docs/pages/release_notes.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 967c6f1a61..94495d1f6e 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,18 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy +#### Java 12 Support + +This release of PMD brings support for Java 12. PMD can parse the new [Switch Expressions](http://openjdk.java.net/jeps/325) +and resolve the type of such an expression. + +Note: The Switch Expressions are a preview language feature of OpenJDK 12 and are not enabled by default. In order to +analyze a project with PMD that uses these language features, you'll need to enable it via the new environment +variable `PMD_JAVA_OPTS`: + + export PMD_JAVA_OPTS=--enable-preview + ./run.sh pmd ... + #### Quickstart Ruleset for Apex PMD provides now a quickstart ruleset for Salesforce.com Apex, which you can use as a base ruleset to @@ -51,6 +63,8 @@ The designer will still be shipped with PMD's binaries. * doc * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example +* java + * [#1537](https://github.com/pmd/pmd/issues/1537): \[java] Java 12 support * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods From 220467ca18bfab79b0fe8b627bcbc587dcc0261d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 12:55:03 +0100 Subject: [PATCH 29/99] [java] Update quickstart ruleset - UnsynchronizedStaticDateFormatter is deprecated Add unit tests Add missing rules --- pmd-apex/pom.xml | 5 + .../pmd/lang/apex/DefaultRulesetTest.java | 16 ++- .../resources/rulesets/java/quickstart.xml | 122 ++++++++---------- .../pmd/lang/java/QuickstartRulesetTest.java | 31 +++++ 4 files changed, 104 insertions(+), 70 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index aee31e3989..83f1e28be6 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -73,6 +73,11 @@ junit test + + com.github.stefanbirkner + system-rules + test + net.sourceforge.pmd pmd-test diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java index 6f227c691c..9646085c85 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/DefaultRulesetTest.java @@ -4,26 +4,32 @@ package net.sourceforge.pmd.lang.apex; -import static org.junit.Assert.assertNotNull; - +import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.SystemErrRule; +import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.util.ResourceLoader; public class DefaultRulesetTest { + @Rule + public final SystemErrRule systemErrRule = new SystemErrRule().enableLog().muteForSuccessfulTests(); - private RuleSetFactory factory = new RuleSetFactory(); + private RuleSetFactory factory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, false); @Test public void loadDefaultRuleset() throws Exception { RuleSet ruleset = factory.createRuleSet("rulesets/apex/ruleset.xml"); - assertNotNull(ruleset); + Assert.assertNotNull(ruleset); } @Test public void loadQuickstartRuleset() throws Exception { RuleSet ruleset = factory.createRuleSet("rulesets/apex/quickstart.xml"); - assertNotNull(ruleset); + Assert.assertNotNull(ruleset); + Assert.assertTrue(systemErrRule.getLog().isEmpty()); } } diff --git a/pmd-java/src/main/resources/rulesets/java/quickstart.xml b/pmd-java/src/main/resources/rulesets/java/quickstart.xml index f2cf5c60b0..a3e1aff5aa 100644 --- a/pmd-java/src/main/resources/rulesets/java/quickstart.xml +++ b/pmd-java/src/main/resources/rulesets/java/quickstart.xml @@ -10,6 +10,7 @@ + @@ -17,6 +18,7 @@ + @@ -29,64 +31,56 @@ - - - - - - - - - - + + - - - - - - - - - + + + + + - - - - - - - + + + + + + + + + + + @@ -94,27 +88,19 @@ - - - - - - - - + - @@ -123,9 +109,11 @@ + + @@ -133,11 +121,13 @@ + - + + - + @@ -149,18 +139,18 @@ - - + + + + + + - - - - @@ -171,12 +161,15 @@ + + + @@ -214,40 +207,21 @@ + - - - - - - - - - - - - - - - - - - - - - + @@ -288,6 +262,20 @@ + + + + + + + + + + + + + + @@ -295,10 +283,11 @@ - + + @@ -330,4 +319,7 @@ + + + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java new file mode 100644 index 0000000000..8a08cd179e --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -0,0 +1,31 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.SystemErrRule; + +import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleSetFactory; +import net.sourceforge.pmd.RuleSetNotFoundException; +import net.sourceforge.pmd.util.ResourceLoader; + +public class QuickstartRulesetTest { + + @Rule + public final SystemErrRule systemErrRule = new SystemErrRule().enableLog(); + + @Test + public void noDeprecations() throws RuleSetNotFoundException { + RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, false); + RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); + Assert.assertFalse(quickstart.getRules().isEmpty()); + + Assert.assertTrue(systemErrRule.getLog().isEmpty()); + } +} From 1479840f6f67cc8631be52a036fed3e4f1542a3b Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 16 Mar 2019 19:16:19 +0100 Subject: [PATCH 30/99] [apex] Expose more information on the nodes Like variable names, type names, apex version --- .../lang/apex/ast/ASTCatchBlockStatement.java | 11 +++++++ .../pmd/lang/apex/ast/ASTField.java | 9 ++++- .../lang/apex/ast/ASTFieldDeclaration.java | 12 +++++++ .../pmd/lang/apex/ast/ASTFormalComment.java | 5 +++ .../lang/apex/ast/ASTLiteralExpression.java | 5 +++ .../pmd/lang/apex/ast/ASTModifierNode.java | 33 +++++++++++++++++++ .../pmd/lang/apex/ast/ASTProperty.java | 7 ++++ .../lang/apex/ast/ASTReferenceExpression.java | 8 +++++ .../lang/apex/ast/ASTVariableDeclaration.java | 4 +++ .../lang/apex/ast/ASTVariableExpression.java | 8 +++++ .../pmd/lang/apex/ast/ApexRootNode.java | 4 +++ .../MethodNamingConventionsRule.java | 2 +- 12 files changed, 106 insertions(+), 2 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java index 14f4929dee..217f803fd8 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java @@ -16,4 +16,15 @@ public class ASTCatchBlockStatement extends AbstractApexNode implements CanSuppressWarn @Override public String getImage() { - return node.getFieldInfo().getName(); + if (node.getFieldInfo() != null) { + return node.getFieldInfo().getName(); + } + return null; } @Override @@ -35,4 +38,8 @@ public class ASTField extends AbstractApexNode implements CanSuppressWarn } return false; } + + public String getTypeRef() { + return String.valueOf(node.getTypeRef()); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java index 9b84e46512..5c382e3574 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java @@ -16,4 +16,16 @@ public class ASTFieldDeclaration extends AbstractApexNode { public Object jjtAccept(ApexParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + @Override + public String getImage() { + if (node.getFieldInfo() != null) { + return node.getFieldInfo().getName(); + } + ASTVariableExpression variable = getFirstChildOfType(ASTVariableExpression.class); + if (variable != null) { + return variable.getImage(); + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java index a59df839e1..97360e3fb5 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFormalComment.java @@ -17,6 +17,11 @@ public class ASTFormalComment extends AbstractApexNodeBase { return visitor.visit(this, data); } + @Override + public String getImage() { + return token; + } + public String getToken() { return token; } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java index 35b04e7d37..42bf52ef62 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java @@ -24,4 +24,9 @@ public class ASTLiteralExpression extends AbstractApexNode { public LiteralType getLiteralType() { return node.getLiteralType(); } + + @Override + public String getImage() { + return String.valueOf(node.getLiteral()); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java index 811cd33f66..ed9465d9b1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.apex.ast; import apex.jorje.semantic.ast.modifier.ModifierNode; +import apex.jorje.semantic.symbol.type.ModifierTypeInfos; public class ASTModifierNode extends AbstractApexNode implements AccessNode { @@ -56,4 +57,36 @@ public class ASTModifierNode extends AbstractApexNode implements A public boolean isTransient() { return (node.getModifiers().getJavaModifiers() & TRANSIENT) == TRANSIENT; } + + public boolean isTest() { + return node.getModifiers().isTest(); + } + + public boolean isTestOrTestSetup() { + return node.getModifiers().isTestOrTestSetup(); + } + + public boolean isWithSharing() { + return node.getModifiers().has(ModifierTypeInfos.WITH_SHARING); + } + + public boolean isWithoutSharing() { + return node.getModifiers().has(ModifierTypeInfos.WITHOUT_SHARING); + } + + public boolean isInheritedSharing() { + return node.getModifiers().has(ModifierTypeInfos.INHERITED_SHARING); + } + + public boolean isWebService() { + return node.getModifiers().has(ModifierTypeInfos.WEB_SERVICE); + } + + public boolean isGlobal() { + return node.getModifiers().has(ModifierTypeInfos.GLOBAL); + } + + public boolean hasOverride() { + return node.getModifiers().has(ModifierTypeInfos.OVERRIDE); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java index a0bec8ba90..d847356a9a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java @@ -16,4 +16,11 @@ public class ASTProperty extends AbstractApexNode { public Object jjtAccept(ApexParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + public String getTypeName() { + if (node.getFieldInfo() != null) { + return node.getFieldInfo().getType().getApexName(); + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java index ef3db237a3..3d76d4f12e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTReferenceExpression.java @@ -30,4 +30,12 @@ public class ASTReferenceExpression extends AbstractApexNode public Object jjtAccept(ApexParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + @Override + public String getImage() { + if (node.getIdentifier() != null) { + return node.getIdentifier().getValue(); + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java index f5ad61f86e..d706474b34 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java @@ -21,4 +21,8 @@ public abstract class ApexRootNode extends AbstractApexNode Date: Sun, 17 Mar 2019 10:03:10 +0100 Subject: [PATCH 31/99] [java] Rename SwitchLabeledRule -> SwitchBlockGroup The plan is with PMD, that also the switch block statements are grouped together with the switch label, like the switch rules --- pmd-java/etc/grammar/Java.jjt | 19 ++++----- ...eledRule.java => ASTSwitchBlockGroup.java} | 24 ++++++++++-- .../java/ast/JavaParserDecoratedVisitor.java | 2 +- .../java/ast/JavaParserVisitorAdapter.java | 2 +- .../java/ast/JavaParserVisitorDecorator.java | 2 +- .../pmd/lang/java/rule/AbstractJavaRule.java | 2 +- .../typeresolution/ClassTypeResolver.java | 6 +-- .../pmd/lang/java/ast/Java12Test.java | 29 +++++++------- .../lang/java/ast/SwitchExpressionTests.kt | 39 +++++++++++++------ 9 files changed, 80 insertions(+), 45 deletions(-) rename pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/{ASTSwitchLabeledRule.java => ASTSwitchBlockGroup.java} (54%) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 82bd933701..61b3312965 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -403,7 +403,7 @@ public class JavaParser { } } - private boolean inFallthroughSwitchCase = false; + private boolean inSwitchLabeledRuleGroup = true; private void checkForBreakExpression() { if (jdkVersion < 12) { @@ -2469,7 +2469,7 @@ void SwitchBlock() #void : { "{" - (SwitchLabeledRule())* + (SwitchBlockGroup())* "}" } @@ -2485,21 +2485,22 @@ void SwitchLabel() : { inSwitchLabel = false; } } -// only pushed if it's not a fallthrough, for compatibility -void SwitchLabeledRule() #SwitchLabeledRule(!inFallthroughSwitchCase): +// only pushed if it's a new java12 switch label rule group, for compatibility +void SwitchBlockGroup() #SwitchBlockGroup(inSwitchLabeledRuleGroup): { - boolean prevFallthrough = inFallthroughSwitchCase; - inFallthroughSwitchCase = false; + boolean prevInSwitchLabeledRuleGroup = inSwitchLabeledRuleGroup; + inSwitchLabeledRuleGroup = true; } { SwitchLabel() - ( "->" {checkForSwitchRules();} | ":" {inFallthroughSwitchCase = true;}) - (LOOKAHEAD({inFallthroughSwitchCase}) + ( "->" {checkForSwitchRules();} | ":" {inSwitchLabeledRuleGroup = false;}) + (LOOKAHEAD({!inSwitchLabeledRuleGroup}) ( BlockStatement() )* | ( Expression() ";" | Block () | ThrowStatement() ) ) { - inFallthroughSwitchCase = prevFallthrough; // restore + jjtThis.setRule(inSwitchLabeledRuleGroup); + inSwitchLabeledRuleGroup = prevInSwitchLabeledRuleGroup; // restore } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java similarity index 54% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java index eed26a4f06..18c559771d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java @@ -7,12 +7,14 @@ package net.sourceforge.pmd.lang.java.ast; -public class ASTSwitchLabeledRule extends AbstractJavaNode { - ASTSwitchLabeledRule(int id) { +public class ASTSwitchBlockGroup extends AbstractJavaNode { + private boolean rule; + + ASTSwitchBlockGroup(int id) { super(id); } - ASTSwitchLabeledRule(JavaParser p, int id) { + ASTSwitchBlockGroup(JavaParser p, int id) { super(p, id); } @@ -20,5 +22,21 @@ public class ASTSwitchLabeledRule extends AbstractJavaNode { public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + void setRule(boolean rule) { + this.rule = rule; + } + + /** + * Returns true if this group contains a switch label with a rule, such as + * a expression, a block, or a throw statement. + * + *

Since Java12. + * + * @return true if this is a java12 switch labeled rule group + */ + public boolean isRule() { + return rule; + } } /* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index 1d76676124..852f6dbdf9 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -870,7 +870,7 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor { } @Override - public Object visit(ASTSwitchLabeledRule node, Object data) { + public Object visit(ASTSwitchBlockGroup node, Object data) { visitor.visit(node, data); return visit((JavaNode) node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java index 721c0893c0..ef9b9675f6 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java @@ -602,7 +602,7 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor { } @Override - public Object visit(ASTSwitchLabeledRule node, Object data) { + public Object visit(ASTSwitchBlockGroup node, Object data) { return visit((JavaNode) node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java index b25a36ae35..abb2c5dd8d 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java @@ -732,7 +732,7 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor } @Override - public Object visit(ASTSwitchLabeledRule node, Object data) { + public Object visit(ASTSwitchBlockGroup node, Object data) { return visitor.visit(node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java index f22a9c13b8..bd7bbcc5bc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java @@ -676,7 +676,7 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse } @Override - public Object visit(ASTSwitchLabeledRule node, Object data) { + public Object visit(ASTSwitchBlockGroup node, Object data) { return visit((JavaNode) node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index 4883668d0a..f4f5e1ae30 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -75,8 +75,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTResource; import net.sourceforge.pmd.lang.java.ast.ASTShiftExpression; import net.sourceforge.pmd.lang.java.ast.ASTSingleMemberAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchBlockGroup; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; -import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabeledRule; import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTTypeArgument; import net.sourceforge.pmd.lang.java.ast.ASTTypeArguments; @@ -1185,8 +1185,8 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { JavaTypeDefinition type = null; // first try to determine the type based on the first expression/break of a switch rule - List rules = node.findChildrenOfType(ASTSwitchLabeledRule.class); - for (ASTSwitchLabeledRule rule : rules) { + List rules = node.findChildrenOfType(ASTSwitchBlockGroup.class); + for (ASTSwitchBlockGroup rule : rules) { Node body = rule.jjtGetChild(1); // second child is either Expression, Block, ThrowStatement if (body instanceof ASTExpression) { type = ((ASTExpression) body).getTypeDefinition(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index d75aff5737..41775e447f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -53,21 +53,22 @@ public class Java12Test { Assert.assertNotNull(compilationUnit); ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression); - Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabeledRule); - ASTSwitchLabeledRule switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(1); - Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); - Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTExpression); + Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchBlockGroup); + ASTSwitchBlockGroup switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(1); + Assert.assertTrue(switchBlockGroup.isRule()); + Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); + Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTExpression); - switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(4); - Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); - Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTBlock); + switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(4); + Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); + Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTBlock); - switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(5); - Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren()); - Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTThrowStatement); + switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(5); + Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); + Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTThrowStatement); } @Test(expected = ParseException.class) @@ -84,7 +85,7 @@ public class Java12Test { ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class); Assert.assertEquals(6, switchExpression.jjtGetNumChildren()); Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); - Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size()); + Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchBlockGroup.class).size()); ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt index 52380ac11b..e4ace1b14c 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt @@ -40,7 +40,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe false @@ -77,7 +78,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe false @@ -100,7 +102,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe true @@ -149,7 +152,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe false @@ -170,7 +174,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe false @@ -184,7 +189,9 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child { child(ignoreChildren = true) {} - child { + child { + it.isRule shouldBe true + child { it.isDefault shouldBe false @@ -193,7 +200,9 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { + child { + it.isRule shouldBe true + child { it.isDefault shouldBe true } @@ -204,7 +213,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe true @@ -260,8 +270,10 @@ class ASTSwitchExpressionTests : ParserTestSpec({ it.testedExpression shouldBe child(ignoreChildren = true) {} - child(ignoreChildren = true) {} - child(ignoreChildren = true) {} + child(ignoreChildren = true) { + it.isRule shouldBe true + } + child(ignoreChildren = true) {} } } @@ -298,7 +310,9 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { + child { + it.isRule shouldBe true + child { it.isDefault shouldBe false @@ -309,7 +323,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { + child { + it.isRule shouldBe true child { it.isDefault shouldBe false From 65b2990ad1d52283347a92cfac3b9eaac92455ec Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 17 Mar 2019 10:14:00 +0100 Subject: [PATCH 32/99] Fix break statement --- pmd-java/etc/grammar/Java.jjt | 2 +- .../pmd/lang/java/ast/ASTBreakStatement.java | 12 +++++++++--- .../sourceforge/pmd/lang/java/ast/Java12Test.java | 4 ++++ .../java12/SwitchExpressionsBreak.java | 3 ++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 61b3312965..db5f448aa2 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -2567,7 +2567,7 @@ void ForUpdate() : void BreakStatement() : {Token t;} { - "break" [ LOOKAHEAD(1) t= {jjtThis.setImage(t.image);} | Expression() {checkForBreakExpression();} ] ";" + "break" [ LOOKAHEAD( ";") t= {jjtThis.setImage(t.image);} | Expression() {checkForBreakExpression();} ] ";" } void ContinueStatement() : diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTBreakStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTBreakStatement.java index 1076b9a803..59aef78bbf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTBreakStatement.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTBreakStatement.java @@ -14,11 +14,17 @@ public class ASTBreakStatement extends AbstractJavaNode { super(p, id); } - /** - * Accept the visitor. * - */ @Override public Object jjtAccept(JavaParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + @Override + public String getImage() { + String result = super.getImage(); + if (result == null && hasDescendantOfType(ASTName.class)) { + result = getFirstDescendantOfType(ASTName.class).getImage(); + } + return result; + } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index 41775e447f..76f8d5aae2 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -104,6 +104,10 @@ public class Java12Test { Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabel.class).size()); + ASTBreakStatement breakStatement = switchExpression.getFirstDescendantOfType(ASTBreakStatement.class); + Assert.assertEquals("SwitchExpressionsBreak.SIX", breakStatement.getImage()); + Assert.assertTrue(breakStatement.jjtGetChild(0) instanceof ASTExpression); + ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); Assert.assertEquals(Integer.TYPE, localVarDecl.getType()); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java index b25b54ed05..088aa542e4 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java12/SwitchExpressionsBreak.java @@ -7,12 +7,13 @@ public class SwitchExpressionsBreak { private static final int SATURDAY = 6; private static final int SUNDAY = 7; + private static final int SIX = 6; public static void main(String[] args) { int day = FRIDAY; var numLetters = switch (day) { - case MONDAY, FRIDAY, SUNDAY: break 6; + case MONDAY, FRIDAY, SUNDAY: break SwitchExpressionsBreak.SIX; case TUESDAY : break 7; case THURSDAY, SATURDAY : break 8; case WEDNESDAY : break 9; From 4ec78b197069b8dd53eab3819f15fcb7b8511a5f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 17:02:20 +0100 Subject: [PATCH 33/99] [doc] Correct indentation so that the ordered list works, use callouts for the tips (instead of quotes) --- .../adding_new_cpd_language.md | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md index dc6d118feb..40d383c2e6 100644 --- a/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md +++ b/docs/pages/pmd/devdocs/major_contributions/adding_new_cpd_language.md @@ -3,70 +3,68 @@ title: How to add a new CPD language short_title: Add a new CPD language tags: [devdocs, extending] summary: How to add a new CPD language -last_updated: March 20, 2019 +last_updated: March 18, 2019 (6.13.0) permalink: pmd_devdocs_major_adding_new_cpd_language.html author: Matías Fraga --- -First of all, thanks for the contribution! - -Happily for you, to add CPD support for a new language is now easier than ever! -> **Pro Tip**: If you wish to add a new language, there are more than 50 languages you could easily add with just an [Antlr grammar](https://github.com/antlr/grammars-v4). +First of all, thanks for the contribution! +Happily for you, to add CPD support for a new language is now easier than ever! + +{% include callout.html content="**Pro Tip**: If you wish to add a new language, there are more than 50 languages you could easily add with just an [Antlr grammar](https://github.com/antlr/grammars-v4)." type="primary" %} + +All you need to do is follow this few steps: - All you need to do is follow this few steps: - 1. Create a new module for your language, you can take [GO as an example](https://github.com/pmd/pmd/tree/master/pmd-go) 2. Create a Tokenizer - -- For Antlr grammars you can take the grammar from [here](https://github.com/antlr/grammars-v4) and extend [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java) taking Go as an example - - -```java - public class GoTokenizer extends AntlrTokenizer { - @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) { - CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode); - return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName()); + - For Antlr grammars you can take the grammar from [here](https://github.com/antlr/grammars-v4) and extend [AntlrTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AntlrTokenizer.java) taking Go as an example + + + ```java + public class GoTokenizer extends AntlrTokenizer { + + @Override protected AntlrTokenManager getLexerForSource(SourceCode sourceCode) { + CharStream charStream = AntlrTokenizer.getCharStreamFromSourceCode(sourceCode); + return new AntlrTokenManager(new GolangLexer(charStream), sourceCode.getFileName()); + } } - } -``` - - -- For JavaCC grammars you should subclass [JavaCCTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/JavaCCTokenizer.java) wich has many examples you could follow, you should also take the [Python implementation](https://github.com/pmd/pmd/blob/master/pmd-python/src/main/java/net/sourceforge/pmd/cpd/PythonTokenizer.java) as reference - - -- For any other scenario you can use [AnyTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java) - -3. Create your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class -```java -public class GoLanguage extends AbstractLanguage { + ``` - public GoLanguage() { - super("Go", "go", new GoTokenizer(), ".go"); - } -} -``` + - For JavaCC grammars you should subclass [JavaCCTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/internal/JavaCCTokenizer.java) wich has many examples you could follow, you should also take the [Python implementation](https://github.com/pmd/pmd/blob/master/pmd-python/src/main/java/net/sourceforge/pmd/cpd/PythonTokenizer.java) as reference + - For any other scenario you can use [AnyTokenizer](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java) - -> **Pro Tip**: Yes, keep looking at Go! - - **You are almost there!** +3. Create your [Language](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java) class + + ```java + public class GoLanguage extends AbstractLanguage { + + public GoLanguage() { + super("Go", "go", new GoTokenizer(), ".go"); + } + } + ``` + + {% include callout.html content="**Pro Tip**: Yes, keep looking at Go!" type="primary" %} + + **You are almost there!** + +4. Please don't forget to add some test, you can again.. look at Go implementation ;) + + If you read this far, I'm keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that) + If that's your case , you came to the right place! -4. Please don't forget to add some test, you can again.. look at Go implementation ;) - -If you read this far, I'm keen to think you would also love to support some extra CPD configuration (ignore imports or crazy things like that) -If that's your case , you came to the right place! - 5. You can add your custom properties using a Token filter - -- For Antlr grammars all you need to do is implement your own [AntlrTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java) - - And by now, I know where you are going to look... - **WRONG** - - Why do you want GO to solve all your problems? - You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) - -- For non-Antlr grammars you can use [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) directly or take a peek to [Java's token filter](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaTokenizer.java) + - For Antlr grammars all you need to do is implement your own [AntlrTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/AntlrTokenFilter.java) + + And by now, I know where you are going to look... + + **WRONG** + + Why do you want GO to solve all your problems? + + You should take a look to [Kotlin token filter implementation](https://github.com/pmd/pmd/blob/master/pmd-kotlin/src/main/java/net/sourceforge/pmd/cpd/KotlinTokenizer.java) + + - For non-Antlr grammars you can use [BaseTokenFilter](https://github.com/pmd/pmd/blob/master/pmd-core/src/main/java/net/sourceforge/pmd/cpd/token/internal/BaseTokenFilter.java) directly or take a peek to [Java's token filter](https://github.com/pmd/pmd/blob/master/pmd-java/src/main/java/net/sourceforge/pmd/cpd/JavaTokenizer.java) From bba32d0a671302b52b4440329744094f308a02c7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 17:04:02 +0100 Subject: [PATCH 34/99] Update release notes, refs #1697 --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ee410dcd04..2578776083 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -52,6 +52,7 @@ This is a {{ site.pmd.release_type }} release. * [#1644](https://github.com/pmd/pmd/pull/1644): \[apex] Add property to allow apex test methods to contain underscores - [Tom](https://github.com/tomdaly) * [#1645](https://github.com/pmd/pmd/pull/1645): \[java] ConsecutiveLiteralAppends false positive - [Shubham](https://github.com/Shubham-2k17) * [#1646](https://github.com/pmd/pmd/pull/1646): \[java] UseDiamondOperator doesn't work with var - [Shubham](https://github.com/Shubham-2k17) +* [#1697](https://github.com/pmd/pmd/pull/1697): \[doc] Update CPD documentation - [Matías Fraga](https://github.com/matifraga) {% endtocmaker %} From 1876a068e6baa6b4aef9e1bb61947d9a7103c06c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 18:56:13 +0100 Subject: [PATCH 35/99] Upgrade checkstyle to 8.18 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 040a0a0dbc..5c27108f1f 100644 --- a/pom.xml +++ b/pom.xml @@ -505,7 +505,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code com.puppycrawl.tools checkstyle - 8.12 + 8.18 net.sourceforge.pmd From 9f80002250b2e976d3f5e09aa286575b6adb7af4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 8 Mar 2019 15:56:45 +0100 Subject: [PATCH 36/99] [plsql] provide access to source code for querying via regex, e.g. Tab Damage: //Input[matches(@Sourcecode, '\t')] Refs #1716 --- pmd-plsql/etc/grammar/PldocAST.jjt | 6 +++--- .../net/sourceforge/pmd/lang/plsql/PLSQLParser.java | 13 +++++++++++-- .../sourceforge/pmd/lang/plsql/ast/ASTInput.java | 10 ++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 87715b4055..bc70177769 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -135,7 +135,7 @@ public class PLSQLParser { throws ParseException { PLSQLParser parser = new PLSQLParser(System.in); - PLSQLNode node = parser.Input(); + PLSQLNode node = parser.Input(""); String s; s = "qwerty"; @@ -203,7 +203,7 @@ PARSER_END(PLSQLParser) /** * 2006-05-22 - Matthias Hendler - added globalBody() */ -ASTInput Input() : {} +ASTInput Input(String sourcecode) : {} { // SRT 2011-04-17 This syntax breaks the parser when fields of record.attach* are referenced (attachLibrary())* ( @@ -229,7 +229,7 @@ ASTInput Input() : {} ("/")* )* - { return jjtThis ; } + { jjtThis.setSourcecode(sourcecode); return jjtThis ; } } ASTDDLCommand DDLCommand() : diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java index 2ce2ffea8b..f13e642c22 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/PLSQLParser.java @@ -4,10 +4,14 @@ package net.sourceforge.pmd.lang.plsql; +import java.io.IOException; import java.io.Reader; +import java.io.StringReader; import java.util.HashMap; import java.util.Map; +import org.apache.commons.io.IOUtils; + import net.sourceforge.pmd.lang.AbstractParser; import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.TokenManager; @@ -45,8 +49,13 @@ public class PLSQLParser extends AbstractParser { @Override public Node parse(String fileName, Reader source) throws ParseException { - AbstractTokenManager.setFileName(fileName); - return createPLSQLParser(source).Input(); + try { + String sourcecode = IOUtils.toString(source); + AbstractTokenManager.setFileName(fileName); + return createPLSQLParser(new StringReader(sourcecode)).Input(sourcecode); + } catch (IOException e) { + throw new ParseException(e); + } } @Override diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ASTInput.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ASTInput.java index a2e7f11f29..3d2e049693 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ASTInput.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ASTInput.java @@ -9,6 +9,8 @@ package net.sourceforge.pmd.lang.plsql.ast; import net.sourceforge.pmd.lang.ast.RootNode; public class ASTInput extends net.sourceforge.pmd.lang.plsql.ast.AbstractPLSQLNode implements RootNode { + private String sourcecode; + public ASTInput(int id) { super(id); } @@ -22,6 +24,14 @@ public class ASTInput extends net.sourceforge.pmd.lang.plsql.ast.AbstractPLSQLNo public Object jjtAccept(PLSQLParserVisitor visitor, Object data) { return visitor.visit(this, data); } + + void setSourcecode(String sourcecode) { + this.sourcecode = sourcecode; + } + + public String getSourcecode() { + return sourcecode; + } } /* * JavaCC - OriginalChecksum=dce06d3ff338546c4a77f0075b1ed936 (do not edit this From d1414bccb84f73cbf32bfae043c602e5aa1db429 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 11 Mar 2019 17:08:54 +0100 Subject: [PATCH 37/99] [plsql] Add new sample rule AvoidTabCharacter --- .../rule/codestyle/AvoidTabCharacterRule.java | 38 ++++++++++++++++ .../resources/category/plsql/codestyle.xml | 18 ++++++++ .../rule/codestyle/AvoidTabCharacterTest.java | 11 +++++ .../rule/codestyle/xml/AvoidTabCharacter.xml | 43 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/AvoidTabCharacter.xml diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java new file mode 100644 index 0000000000..68c1b7f9de --- /dev/null +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java @@ -0,0 +1,38 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.codestyle; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import net.sourceforge.pmd.lang.plsql.ast.ASTInput; +import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; + +public class AvoidTabCharacterRule extends AbstractPLSQLRule { + + public AvoidTabCharacterRule() { + addRuleChainVisit(ASTInput.class); + } + + @Override + public Object visit(ASTInput node, Object data) { + try (BufferedReader in = new BufferedReader(new StringReader(node.getSourcecode()))) { + String line; + int lineNumber = 0; + while ((line = in.readLine()) != null) { + lineNumber++; + if (line.indexOf('\t') != -1) { + addViolationWithMessage(data, null, "Tab characters are not allowed. Use spaces for intendation", + lineNumber, lineNumber); + break; + } + } + } catch (IOException e) { + throw new RuntimeException("Error while executing rule AvoidTabCharacter", e); + } + return data; + } +} diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml index 719f2c59fe..a906202b02 100644 --- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml +++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml @@ -9,6 +9,24 @@ Rules which enforce a specific coding style. + + +This rule checks, that there are no tab characters (`\t`) in the source file. +It reports only the first occurrence per file. + +Using tab characters for indentation is not recommended, since this requires that every developer +uses the same tab with in their editor. + +This rule is the PMD equivalent of checkstyle's [FileTabCharacter](http://checkstyle.sourceforge.net/config_whitespace.html#FileTabCharacter) check. + + 3 + + + + + + Using tabs - only the first tab character is reported + 1 + 2 + + plsql + + + + No tabs + 0 + + plsql + + \ No newline at end of file From 430bd23a83c58ad7cacf02170ae2b111e03818d6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 12 Mar 2019 16:40:49 +0100 Subject: [PATCH 38/99] [plsql] AvoidTabCharacter: Add property "eachLine" --- .../rule/codestyle/AvoidTabCharacterRule.java | 17 ++++++++++++++-- .../rule/codestyle/xml/AvoidTabCharacter.xml | 20 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java index 68c1b7f9de..bb6359dff2 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java @@ -10,24 +10,37 @@ import java.io.StringReader; import net.sourceforge.pmd.lang.plsql.ast.ASTInput; import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; public class AvoidTabCharacterRule extends AbstractPLSQLRule { + private static final PropertyDescriptor EACH_LINE = PropertyFactory.booleanProperty("eachLine") + .desc("Whether to report each line with a tab character or only the first line") + .defaultValue(false) + .build(); + public AvoidTabCharacterRule() { + definePropertyDescriptor(EACH_LINE); addRuleChainVisit(ASTInput.class); } @Override public Object visit(ASTInput node, Object data) { + boolean eachLine = getProperty(EACH_LINE); + try (BufferedReader in = new BufferedReader(new StringReader(node.getSourcecode()))) { String line; int lineNumber = 0; while ((line = in.readLine()) != null) { lineNumber++; if (line.indexOf('\t') != -1) { - addViolationWithMessage(data, null, "Tab characters are not allowed. Use spaces for intendation", + addViolationWithMessage(data, null, "Tab characters are not allowed. Use spaces for indentation", lineNumber, lineNumber); - break; + + if (!eachLine) { + break; + } } } } catch (IOException e) { diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/AvoidTabCharacter.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/AvoidTabCharacter.xml index 04e2a82508..3bc2fd18f0 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/AvoidTabCharacter.xml +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/AvoidTabCharacter.xml @@ -23,6 +23,26 @@ END; plsql + + Using tabs - all lines are reported + true + 6 + 2,3,4,6,7,8 + + plsql + + No tabs 0 From d12daa8d470f4cde42d5b6b387381edcce3276d8 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 12 Mar 2019 16:54:18 +0100 Subject: [PATCH 39/99] [plsql] New rule LineLength --- .../plsql/rule/codestyle/LineLengthRule.java | 59 ++++++++++++ .../resources/category/plsql/codestyle.xml | 15 +++ .../plsql/rule/codestyle/LineLengthTest.java | 11 +++ .../plsql/rule/codestyle/xml/LineLength.xml | 91 +++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthRule.java create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/LineLength.xml diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthRule.java new file mode 100644 index 0000000000..ecae7ee195 --- /dev/null +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthRule.java @@ -0,0 +1,59 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.codestyle; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import net.sourceforge.pmd.lang.plsql.ast.ASTInput; +import net.sourceforge.pmd.lang.plsql.rule.AbstractPLSQLRule; +import net.sourceforge.pmd.properties.PropertyDescriptor; +import net.sourceforge.pmd.properties.PropertyFactory; +import net.sourceforge.pmd.properties.constraints.NumericConstraints; + +public class LineLengthRule extends AbstractPLSQLRule { + + private static final PropertyDescriptor MAX_LINE_LENGTH = PropertyFactory.intProperty("maxLineLength") + .desc("The maximum allowed line length") + .defaultValue(80) + .require(NumericConstraints.inRange(10, 200)) + .build(); + private static final PropertyDescriptor EACH_LINE = PropertyFactory.booleanProperty("eachLine") + .desc("Whether to report each line that is longer only the first line") + .defaultValue(false) + .build(); + + public LineLengthRule() { + definePropertyDescriptor(MAX_LINE_LENGTH); + definePropertyDescriptor(EACH_LINE); + addRuleChainVisit(ASTInput.class); + } + + @Override + public Object visit(ASTInput node, Object data) { + boolean eachLine = getProperty(EACH_LINE); + int maxLineLength = getProperty(MAX_LINE_LENGTH); + + try (BufferedReader in = new BufferedReader(new StringReader(node.getSourcecode()))) { + String line; + int lineNumber = 0; + while ((line = in.readLine()) != null) { + lineNumber++; + if (line.length() > maxLineLength) { + addViolationWithMessage(data, null, "The line is too long. Only " + maxLineLength + " characters are allowed.", + lineNumber, lineNumber); + + if (!eachLine) { + break; + } + } + } + } catch (IOException e) { + throw new RuntimeException("Error while executing rule LineLengthRule", e); + } + return data; + } +} diff --git a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml index a906202b02..62a22d0a4c 100644 --- a/pmd-plsql/src/main/resources/category/plsql/codestyle.xml +++ b/pmd-plsql/src/main/resources/category/plsql/codestyle.xml @@ -195,4 +195,19 @@ END; ]]> + + + +This rule checks for long lines. Please note that comments are not ignored. + +This rule is the PMD equivalent of checkstyle's [LineLength](http://checkstyle.sourceforge.net/config_sizes.html#LineLength) check. + + 3 + + diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthTest.java new file mode 100644 index 0000000000..d668eefb53 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.codestyle; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class LineLengthTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/LineLength.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/LineLength.xml new file mode 100644 index 0000000000..a0ced2fafe --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/codestyle/xml/LineLength.xml @@ -0,0 +1,91 @@ + + + + + All lines are fine - default line length + 0 + + plsql + + + + One line is too long + 30 + 1 + 5 + + The line is too long. Only 30 characters are allowed. + + + plsql + + + + Multiple lines are too long - only first is reported + 30 + 1 + 2 + + The line is too long. Only 30 characters are allowed. + + + plsql + + + + Multiple lines are too long - report all + 30 + true + 7 + 2,3,4,5,6,7,8 + + plsql + + \ No newline at end of file From b51fa59cf60bb27ad540d218f9438a8697cadc90 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 19:04:33 +0100 Subject: [PATCH 40/99] Update release notes, fixes #1716 --- docs/pages/release_notes.md | 8 ++++++++ pmd-core/src/main/resources/rulesets/releases/6130.xml | 3 +++ 2 files changed, 11 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8aedaffbaf..f74f69df92 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -47,12 +47,20 @@ The designer will still be shipped with PMD's binaries. Do-While-Loops and While-Loops that can be simplified since they use simply `true` or `false` as their loop condition. +* The new PLSQL rule {% rule "plsql/codestyle/AvoidTabCharacter" %} (`plsql-codestyle`) checks, that there are + no tab characters ("\t") in the source file. + +* The new PLSQL rule {% rule "plsql/codestyle/LineLength" %} (`plsql-codestyle`) helps to enforce a maximum + line length. + ### Fixed Issues * doc * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods +* plsql + * [#1716](https://github.com/pmd/pmd/issues/1716): \[plsql] Support access to whole plsql code ### API Changes diff --git a/pmd-core/src/main/resources/rulesets/releases/6130.xml b/pmd-core/src/main/resources/rulesets/releases/6130.xml index 55c31de0d4..5389a2ad1a 100644 --- a/pmd-core/src/main/resources/rulesets/releases/6130.xml +++ b/pmd-core/src/main/resources/rulesets/releases/6130.xml @@ -12,5 +12,8 @@ This ruleset contains links to rules that are new in PMD v6.13.0 + + + From ba31b0ce9f453da81c3a3c74f177a1570b7e9d31 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 19:27:14 +0100 Subject: [PATCH 41/99] [plsql] Add test for TomKytesDespair --- .../bestpractices/TomKytesDespairTest.java | 11 ++ .../bestpractices/xml/TomKytesDespair.xml | 103 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/bestpractices/TomKytesDespairTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/bestpractices/xml/TomKytesDespair.xml diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/bestpractices/TomKytesDespairTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/bestpractices/TomKytesDespairTest.java new file mode 100644 index 0000000000..103b36337c --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/bestpractices/TomKytesDespairTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.bestpractices; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class TomKytesDespairTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/bestpractices/xml/TomKytesDespair.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/bestpractices/xml/TomKytesDespair.xml new file mode 100644 index 0000000000..c69d0d0a38 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/bestpractices/xml/TomKytesDespair.xml @@ -0,0 +1,103 @@ + + + + + Example code + 1 + 34 + + plsql + + + + Fixed Example code + 0 + + plsql + + From 14ad94340c8d3e07fc0231dbe20bb161c4d8f36c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Mar 2019 20:06:44 +0100 Subject: [PATCH 42/99] [plsql] Add test for TooManyMethods and fix the rule --- .../main/resources/category/plsql/design.xml | 12 +-- .../plsql/rule/design/TooManyMethodsTest.java | 11 +++ .../plsql/rule/design/xml/TooManyMethods.xml | 93 +++++++++++++++++++ 3 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyMethodsTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/design/xml/TooManyMethods.xml diff --git a/pmd-plsql/src/main/resources/category/plsql/design.xml b/pmd-plsql/src/main/resources/category/plsql/design.xml index 24e549f2ab..d48d7c5461 100644 --- a/pmd-plsql/src/main/resources/category/plsql/design.xml +++ b/pmd-plsql/src/main/resources/category/plsql/design.xml @@ -512,22 +512,22 @@ have more fine grained objects. ( count(/descendant::ProgramUnit[ not ( - starts-with(@Image,'get') + starts-with(@Name,'get') or - starts-with(@Image,'set') + starts-with(@Name,'set') or - starts-with(@Image,'is') + starts-with(@Name,'is') ) ] ) + count(/descendant::TypeMethod[ not ( - starts-with(@Image,'get') + starts-with(@Name,'get') or - starts-with(@Image,'set') + starts-with(@Name,'set') or - starts-with(@Image,'is') + starts-with(@Name,'is') ) ] ) diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyMethodsTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyMethodsTest.java new file mode 100644 index 0000000000..391b08d111 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/design/TooManyMethodsTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.design; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class TooManyMethodsTest extends PmdRuleTst { + // no additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/design/xml/TooManyMethods.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/design/xml/TooManyMethods.xml new file mode 100644 index 0000000000..52ef1705e6 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/design/xml/TooManyMethods.xml @@ -0,0 +1,93 @@ + + + + + Too many methods in a package + 3 + 1 + + + + plsql + + + + Getters are ignored + 3 + 0 + + + + plsql + + + + Too many methods in a type definition + 3 + 1 + + + + plsql + + + + Getters/Setters are ignored for types + 3 + 0 + + + + plsql + + + + From e7a0198b4b8b538bc4d304eaaedba6d91242c0b3 Mon Sep 17 00:00:00 2001 From: guo fei Date: Tue, 26 Feb 2019 15:51:24 +0800 Subject: [PATCH 43/99] AbstractRuleViolationFactory.cleanup() skip MessageFormat when args is empty --- .../rule/JavaRuleViolationFactoryTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java new file mode 100644 index 0000000000..8fb40ff313 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java @@ -0,0 +1,25 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.rule; + +import org.junit.Test; + +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.java.rule.codestyle.DuplicateImportsRule; +import net.sourceforge.pmd.lang.rule.RuleViolationFactory; + +/** + * @author guofei + * + */ +public class JavaRuleViolationFactoryTest { + + @Test + public void messageWithSingleBrace() { + RuleViolationFactory factory = JavaRuleViolationFactory.INSTANCE; + factory.addViolation(new RuleContext(), new DuplicateImportsRule(), null, "message with \"{\"", null); + } + +} From 1337dce1fba8970c4fc07ef8fe0c54f9e65e9922 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 19 Mar 2019 17:12:03 +0100 Subject: [PATCH 44/99] Add escaping to the test, add extended test in pmd-core for AbstractRuleViolationFactory --- .../AbstractRuleViolationFactoryTest.java | 65 +++++++++++++++++++ .../rule/JavaRuleViolationFactoryTest.java | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/AbstractRuleViolationFactoryTest.java diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/AbstractRuleViolationFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/AbstractRuleViolationFactoryTest.java new file mode 100644 index 0000000000..beb48181f5 --- /dev/null +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/AbstractRuleViolationFactoryTest.java @@ -0,0 +1,65 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleViolation; +import net.sourceforge.pmd.lang.ast.Node; + +public class AbstractRuleViolationFactoryTest { + private RuleContext ruleContext; + private RuleViolationFactory factory; + + private static class TestRuleViolationFactory extends AbstractRuleViolationFactory { + @Override + protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message) { + return new ParametricRuleViolation<>(rule, ruleContext, node, message); + } + + @Override + protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message, + int beginLine, int endLine) { + ParametricRuleViolation violation = new ParametricRuleViolation<>(rule, ruleContext, node, message); + violation.setLines(beginLine, endLine); + return violation; + } + } + + private static class TestRule extends AbstractRule { + @Override + public void apply(List nodes, RuleContext ctx) { + throw new UnsupportedOperationException("not implemented"); + } + } + + @Before + public void setup() { + ruleContext = new RuleContext(); + factory = new TestRuleViolationFactory(); + } + + @Test + public void testMessage() { + factory.addViolation(ruleContext, new TestRule(), null, "message with \"'{'\"", null); + + RuleViolation violation = ruleContext.getReport().iterator().next(); + Assert.assertEquals("message with \"{\"", violation.getDescription()); + } + + @Test + public void testMessageArgs() { + factory.addViolation(ruleContext, new TestRule(), null, "message with 1 argument: \"{0}\"", new Object[] {"testarg1"}); + + RuleViolation violation = ruleContext.getReport().iterator().next(); + Assert.assertEquals("message with 1 argument: \"testarg1\"", violation.getDescription()); + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java index 8fb40ff313..fab7669e39 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationFactoryTest.java @@ -19,7 +19,7 @@ public class JavaRuleViolationFactoryTest { @Test public void messageWithSingleBrace() { RuleViolationFactory factory = JavaRuleViolationFactory.INSTANCE; - factory.addViolation(new RuleContext(), new DuplicateImportsRule(), null, "message with \"{\"", null); + factory.addViolation(new RuleContext(), new DuplicateImportsRule(), null, "message with \"'{'\"", null); } } From 3a866ddb9fc6f63cf81096a786ff22130d99005d Mon Sep 17 00:00:00 2001 From: "Travis CI (pmd-bot)" Date: Tue, 19 Mar 2019 16:34:34 +0000 Subject: [PATCH 45/99] Update documentation TRAVIS_JOB_NUMBER=3562.1 TRAVIS_COMMIT_RANGE=1876a068e6ba...1337dce1fba8 --- docs/pages/pmd/rules/apex/bestpractices.md | 20 +- docs/pages/pmd/rules/apex/codestyle.md | 57 +++- docs/pages/pmd/rules/apex/design.md | 185 +++++++--- docs/pages/pmd/rules/apex/documentation.md | 2 +- docs/pages/pmd/rules/apex/errorprone.md | 22 +- docs/pages/pmd/rules/apex/performance.md | 18 +- docs/pages/pmd/rules/apex/security.md | 66 ++-- .../pmd/rules/ecmascript/bestpractices.md | 15 +- docs/pages/pmd/rules/ecmascript/codestyle.md | 16 +- docs/pages/pmd/rules/ecmascript/errorprone.md | 12 +- docs/pages/pmd/rules/java/bestpractices.md | 134 +++++++- docs/pages/pmd/rules/java/codestyle.md | 303 +++++++++++++++-- docs/pages/pmd/rules/java/design.md | 318 +++++++++++++++--- docs/pages/pmd/rules/java/documentation.md | 53 ++- docs/pages/pmd/rules/java/errorprone.md | 124 ++++++- docs/pages/pmd/rules/java/multithreading.md | 12 +- docs/pages/pmd/rules/java/performance.md | 22 +- docs/pages/pmd/rules/plsql/codestyle.md | 24 +- docs/pages/pmd/rules/plsql/design.md | 188 ++++++++--- docs/pages/pmd/rules/pom/errorprone.md | 11 +- docs/pages/pmd/rules/vm/design.md | 28 +- docs/pages/pmd/rules/xsl/performance.md | 11 +- 22 files changed, 1367 insertions(+), 274 deletions(-) diff --git a/docs/pages/pmd/rules/apex/bestpractices.md b/docs/pages/pmd/rules/apex/bestpractices.md index 559ce4a5a4..b4800dc6c9 100644 --- a/docs/pages/pmd/rules/apex/bestpractices.md +++ b/docs/pages/pmd/rules/apex/bestpractices.md @@ -38,11 +38,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Bug Risk|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -75,11 +75,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Bug Risk|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -110,10 +110,10 @@ global class Unchangeable { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -154,10 +154,10 @@ trigger Accounts on Account (before insert, before update, before delete, after |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|200|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/apex/codestyle.md b/docs/pages/pmd/rules/apex/codestyle.md index 8f88cc0789..7f8f72b1a5 100644 --- a/docs/pages/pmd/rules/apex/codestyle.md +++ b/docs/pages/pmd/rules/apex/codestyle.md @@ -30,10 +30,10 @@ public class Foo {} |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|5|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -74,7 +74,7 @@ for (int i = 0; i < 42; i++) { // preferred approach |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -117,7 +117,7 @@ else |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -156,7 +156,7 @@ if (foo) { // preferred approach |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -189,11 +189,20 @@ public class Foo { |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |skipTestMethodUnderscores|false|Skip underscores in test methods|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## OneDeclarationPerLine **Since:** PMD 6.7.0 @@ -235,11 +244,20 @@ Integer b; |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## VariableNamingConventions **Since:** PMD 5.5.0 @@ -267,7 +285,7 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|5|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |checkMembers|true|Check member variables|no| |checkLocals|true|Check local variables|no| @@ -281,11 +299,30 @@ public class Foo { |parameterPrefix||Method parameter variable prefixes|yes. Delimiter is ','.| |parameterSuffix||Method parameter variable suffixes|yes. Delimiter is ','.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + + + +``` + ## WhileLoopsMustUseBraces **Since:** PMD 5.6.0 @@ -320,7 +357,7 @@ while (true) { // preferred approach |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/apex/design.md b/docs/pages/pmd/rules/apex/design.md index f5f2aed813..b7043622cf 100644 --- a/docs/pages/pmd/rules/apex/design.md +++ b/docs/pages/pmd/rules/apex/design.md @@ -39,16 +39,25 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|200|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |problemDepth|3|The if statement depth reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CyclomaticComplexity **Since:** PMD 6.0.0 @@ -110,11 +119,21 @@ public class Complicated { |classReportLevel|40|Total class complexity reporting threshold|no| |methodReportLevel|10|Cyclomatic complexity reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## ExcessiveClassLength **Since:** PMD 5.5.0 @@ -150,18 +169,27 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|150|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveParameterList **Since:** PMD 5.5.0 @@ -190,18 +218,27 @@ public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|4.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|50|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessivePublicCount **Since:** PMD 5.5.0 @@ -235,18 +272,27 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|20.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|150|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssConstructorCount **Since:** PMD 5.5.0 @@ -279,18 +325,27 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|20.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|50|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssMethodCount **Since:** PMD 5.5.0 @@ -322,18 +377,27 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|40.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|50|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssTypeCount **Since:** PMD 5.5.0 @@ -367,18 +431,27 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|topscore||Deprecated Top score value|no| +|minimum|500.0|Minimum reporting threshold|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|250|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -|sigma||Sigma value|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## StdCyclomaticComplexity **Since:** PMD 5.5.0 @@ -437,18 +510,29 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|250|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |reportLevel|10|Cyclomatic Complexity reporting threshold|no| |showClassesComplexity|true|Add class average violations to the report|no| |showMethodsComplexity|true|Add method average violations to the report|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## TooManyFields **Since:** PMD 5.5.0 @@ -484,13 +568,22 @@ public class Person { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Complexity|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|200|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| |maxfields|15|Max allowable fields|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + diff --git a/docs/pages/pmd/rules/apex/documentation.md b/docs/pages/pmd/rules/apex/documentation.md index 8eba7496b8..20a24496e8 100644 --- a/docs/pages/pmd/rules/apex/documentation.md +++ b/docs/pages/pmd/rules/apex/documentation.md @@ -52,7 +52,7 @@ public class HelloWorld { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/apex/errorprone.md b/docs/pages/pmd/rules/apex/errorprone.md index ecaa2fa60a..2e1c5ae832 100644 --- a/docs/pages/pmd/rules/apex/errorprone.md +++ b/docs/pages/pmd/rules/apex/errorprone.md @@ -42,7 +42,7 @@ trigger AccountTrigger on Account (before insert, before update) { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -79,10 +79,10 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -118,7 +118,7 @@ A full list of supported annotations can be found at https://developer.salesforc |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -159,7 +159,7 @@ public void doSomething() { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -198,7 +198,7 @@ public class Foo { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -239,7 +239,7 @@ public class Foo { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -289,7 +289,7 @@ public class Foo { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -327,7 +327,7 @@ public void bar(Integer a, Integer b) { |cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -358,10 +358,10 @@ public class MyClass { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| |cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_remediation\_points\_multiplier|50|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/apex/performance.md b/docs/pages/pmd/rules/apex/performance.md index 901fdfcbdd..d092b7820f 100644 --- a/docs/pages/pmd/rules/apex/performance.md +++ b/docs/pages/pmd/rules/apex/performance.md @@ -37,11 +37,11 @@ public class Something { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Performance|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|150|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -72,11 +72,11 @@ public class Something { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Performance|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|150|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -107,11 +107,11 @@ public class Something { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Performance|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|150|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/apex/security.md b/docs/pages/pmd/rules/apex/security.md index fffe3e55e2..e77159bddb 100644 --- a/docs/pages/pmd/rules/apex/security.md +++ b/docs/pages/pmd/rules/apex/security.md @@ -35,11 +35,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -79,11 +79,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -117,11 +117,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -157,11 +157,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -192,11 +192,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -227,11 +227,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -259,11 +259,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -292,11 +292,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -339,11 +339,11 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -372,11 +372,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` @@ -405,11 +405,11 @@ public without sharing class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_categories|Security|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|50|Deprecated Code Climate Remediation Points multiplier|no| |cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` diff --git a/docs/pages/pmd/rules/ecmascript/bestpractices.md b/docs/pages/pmd/rules/ecmascript/bestpractices.md index 76181a224e..9815aaf2f7 100644 --- a/docs/pages/pmd/rules/ecmascript/bestpractices.md +++ b/docs/pages/pmd/rules/ecmascript/bestpractices.md @@ -71,15 +71,26 @@ function bar() { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|rhinoLanguageVersion|VERSION\_DEFAULT|Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.|no| +|rhinoLanguageVersion|default|Specifies the Rhino Language Version to use for parsing. Defaults to Rhino default.|no| |recordingLocalJsDocComments|true|Specifies that JsDoc comments are produced in the AST.|no| |recordingComments|true|Specifies that comments are produced in the AST.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## GlobalVariable **Since:** PMD 5.0 diff --git a/docs/pages/pmd/rules/ecmascript/codestyle.md b/docs/pages/pmd/rules/ecmascript/codestyle.md index 0e02165cbf..4ced64c596 100644 --- a/docs/pages/pmd/rules/ecmascript/codestyle.md +++ b/docs/pages/pmd/rules/ecmascript/codestyle.md @@ -58,11 +58,25 @@ function getX() { |allowTernaryResults|false|Allow assignment within the result expressions of a ternary operator|no| |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + +``` + ## ForLoopsMustUseBraces **Since:** PMD 5.0 diff --git a/docs/pages/pmd/rules/ecmascript/errorprone.md b/docs/pages/pmd/rules/ecmascript/errorprone.md index 6880e2e5f0..a3cf0fd5fa 100644 --- a/docs/pages/pmd/rules/ecmascript/errorprone.md +++ b/docs/pages/pmd/rules/ecmascript/errorprone.md @@ -43,11 +43,21 @@ function(arg) { |allowObjectLiteral|false|Allow a trailing comma within an object literal|no| |allowArrayLiteral|false|Allow a trailing comma within an array literal|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## EqualComparison **Since:** PMD 5.0 diff --git a/docs/pages/pmd/rules/java/bestpractices.md b/docs/pages/pmd/rules/java/bestpractices.md index 2686ebf7ef..68feb9d383 100644 --- a/docs/pages/pmd/rules/java/bestpractices.md +++ b/docs/pages/pmd/rules/java/bestpractices.md @@ -230,11 +230,21 @@ public class Foo { |foreachReassign|deny|how/if foreach control variables may be reassigned|no| |forReassign|deny|how/if for control variables may be reassigned|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## AvoidReassigningParameters **Since:** PMD 1.0 @@ -312,11 +322,20 @@ public class Foo { |----|-------------|-----------|-----------| |checkAddressTypes|IPv4 mapped IPv6 \| IPv6 \| IPv4|Check for IP address types.|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CheckResultSet **Since:** PMD 4.1 @@ -395,11 +414,20 @@ public interface YetAnotherConstantInterface { |----|-------------|-----------|-----------| |ignoreIfHasMethods|true|Whether to ignore constants in interfaces if the interface defines any methods|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## DefaultLabelNotLastInSwitchStmt **Since:** PMD 1.5 @@ -501,11 +529,20 @@ for (int i = 0, j = 0; i < 10; i++, j += 2) { |----|-------------|-----------|-----------| |maximumVariables|1|A regular for statement will have 1 control variable|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## GuardLogStatement **Since:** PMD 5.1.0 @@ -532,11 +569,21 @@ otherwise skip the associate String creation and manipulation. |logLevels|trace , debug , info , warn , error , log , finest , finer , fine , info , warning , severe|LogLevels to guard|yes. Delimiter is ','.| |guardsMethods|isTraceEnabled , isDebugEnabled , isInfoEnabled , isWarnEnabled , isErrorEnabled , isLoggable|Method use to guard the log statement|yes. Delimiter is ','.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## JUnit4SuitesShouldUseSuiteAnnotation **Since:** PMD 4.0 @@ -702,11 +749,20 @@ public class MyTest { |----|-------------|-----------|-----------| |testClassPattern|Test|The regex pattern used to identify test classes|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## JUnitAssertionsShouldIncludeMessage **Since:** PMD 1.04 @@ -787,11 +843,20 @@ public class MyTestCase extends TestCase { |----|-------------|-----------|-----------| |maximumAsserts|1|Maximum number of Asserts in a test method|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## JUnitTestsShouldIncludeAssert **Since:** PMD 2.0 @@ -993,11 +1058,20 @@ String name, |----|-------------|-----------|-----------| |strictMode|false|If true, mark combined declaration even if the declarations are on separate lines.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## PositionLiteralsFirstInCaseInsensitiveComparisons **Since:** PMD 5.1 @@ -1303,11 +1377,20 @@ public class Foo { |----|-------------|-----------|-----------| |checkAll|false|Check all methods, including non-private ones|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnusedImports **Since:** PMD 1.0 @@ -1387,11 +1470,20 @@ public class Something { |----|-------------|-----------|-----------| |ignoredAnnotations|lombok.Setter \| lombok.Getter \| lombok.Builder \| lombok.Data \| lombok.RequiredArgsConstructor \| lombok.AllArgsConstructor \| lombok.Value \| lombok.NoArgsConstructor \| java.lang.Deprecated \| javafx.fxml.FXML|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnusedPrivateMethod **Since:** PMD 0.7 @@ -1416,11 +1508,20 @@ public class Something { |----|-------------|-----------|-----------| |ignoredAnnotations|java.lang.Deprecated|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UseAssertEqualsInsteadOfAssertTrue **Since:** PMD 3.1 @@ -1694,11 +1795,20 @@ public class TryWithResources { |----|-------------|-----------|-----------| |closeMethods|close , closeQuietly|Method names in finally block, which trigger this rule|yes. Delimiter is ','.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UseVarargs **Since:** PMD 5.0 diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index 2124e2cd3c..6936314df0 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -47,11 +47,20 @@ public abstract class Foo { // should be AbstractFoo |----|-------------|-----------|-----------| |strict|true|Also flag classes, that are named Abstract, but are not abstract.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## AtLeastOneConstructor **Since:** PMD 1.04 @@ -79,11 +88,20 @@ public class Foo { |----|-------------|-----------|-----------| |ignoredAnnotations|lombok.Data \| lombok.Value \| lombok.Builder \| lombok.NoArgsConstructor \| lombok.RequiredArgsConstructor \| lombok.AllArgsConstructor|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## AvoidDollarSigns **Since:** PMD 1.5 @@ -334,11 +352,20 @@ public boolean getFoo(boolean bar); // ok, unless checkParameterizedMethods=true |----|-------------|-----------|-----------| |checkParameterizedMethods|false|Check parameterized methods|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CallSuperInConstructor **Since:** PMD 3.0 @@ -421,11 +448,25 @@ public class Éléphant {} |annotationPattern|\[A-Z\]\[a-zA-Z0-9\]\*|Regex which applies to annotation names|no| |utilityClassPattern|\[A-Z\]\[a-zA-Z0-9\]+(Utils?\|Helper)|Regex which applies to utility class names|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + +``` + ## CommentDefaultAccessModifier **Since:** PMD 5.4.0 @@ -472,11 +513,21 @@ public class Foo { |ignoredAnnotations|com.google.common.annotations.VisibleForTesting \| android.support.annotation.VisibleForTesting|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| |regex|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|Regular expression|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## ConfusingTernary **Since:** PMD 1.9 @@ -506,11 +557,20 @@ boolean bar(int x, int y) { |----|-------------|-----------|-----------| |ignoreElseIf|false|Ignore conditions with an else-if case|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ControlStatementBraces **Since:** PMD 6.2.0 @@ -573,11 +633,26 @@ while (true) { // preferred approach |checkCaseStmt|false|Require that cases of a switch have braces|no| |allowEmptyLoop|false|Allow loops with an empty statement, e.g. 'while(true);'|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + +``` + ## DefaultPackage **Since:** PMD 3.4 @@ -763,11 +838,22 @@ public class HelloWorldBean { |ignoreAnonymousClassDeclarations|true|Ignore Field Declarations, that are initialized with anonymous class declarations|no| |ignoreInterfaceDeclarations|false|Ignore Interface Declarations that precede fields.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## FieldNamingConventions **Since:** PMD 6.7.0 @@ -816,11 +902,26 @@ class Foo { |defaultFieldPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to field names|no| |exclusions|serialVersionUID|Names of fields to whitelist.|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + +``` + ## ForLoopShouldBeWhileLoop **Since:** PMD 1.02 @@ -933,11 +1034,23 @@ class Foo { |lambdaParameterPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to inferred-type lambda parameter names|no| |explicitLambdaParameterPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to explicitly-typed lambda parameter names|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + +``` + ## GenericsNaming **Since:** PMD 4.2.6 @@ -1172,11 +1285,30 @@ public class LinguisticNaming { |checkVariables|true|Check local variable names and types for inconsistent naming.|no| |booleanFieldPrefixes|is \| has \| can \| have \| will \| should|The prefixes of fields and variables that indicate boolean.|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + + + +``` + ## LocalHomeNamingConvention **Since:** PMD 4.0 @@ -1276,11 +1408,20 @@ public class Bar { |----|-------------|-----------|-----------| |ignoreForEachDecl|false|Ignore non-final loop variables in a for-each statement.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## LocalVariableNamingConventions **Since:** PMD 6.6.0 @@ -1324,11 +1465,22 @@ class Foo { |finalVarPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to final local variable names|no| |catchParameterPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to exception block parameter names|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## LongVariable **Since:** PMD 0.3 @@ -1362,11 +1514,20 @@ public class Something { |----|-------------|-----------|-----------| |minimum|17|The variable length reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## MDBAndSessionBeanNamingConvention **Since:** PMD 4.0 @@ -1467,11 +1628,24 @@ public class Foo { |junit3TestPattern|test\[A-Z0-9\]\[a-zA-Z0-9\]\*|Regex which applies to JUnit 3 test method names|no| |junit4TestPattern|\[a-z\]\[a-zA-Z0-9\]\*|Regex which applies to JUnit 4 test method names|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + +``` + ## MIsLeadingVariableName Deprecated @@ -1728,11 +1902,20 @@ public class Foo { |----|-------------|-----------|-----------| |minimum|5|Number of characters that are required as a minimum for a class name.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ShortMethodName **Since:** PMD 0.3 @@ -1761,11 +1944,20 @@ public class ShortMethod { |----|-------------|-----------|-----------| |minimum|3|Number of characters that are required as a minimum for a method name.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ShortVariable **Since:** PMD 0.3 @@ -1810,11 +2002,20 @@ public class Something { |----|-------------|-----------|-----------| |minimum|3|Number of characters that are required as a minimum for a variable name.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## SuspiciousConstantFieldName Deprecated @@ -1885,11 +2086,20 @@ import static Yoko; // Too much ! |----|-------------|-----------|-----------| |maximumStaticImports|4|All static imports can be disallowed by setting this to 0|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnnecessaryAnnotationValueElement **Since:** PMD 6.2.0 @@ -1963,11 +2173,20 @@ public class Foo { |----|-------------|-----------|-----------| |ignoredAnnotations|javax.inject.Inject|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnnecessaryFullyQualifiedName **Since:** PMD 5.0 @@ -2022,11 +2241,20 @@ 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.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnnecessaryModifier **Since:** PMD 1.02 @@ -2322,11 +2550,20 @@ public class Foo { |----|-------------|-----------|-----------| |acceptableDecimalLength|4|Length under which literals in base 10 are not required to have underscores|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## VariableNamingConventions Deprecated @@ -2373,11 +2610,31 @@ public class Foo { |checkParameters|true|Check constructor and method parameter variables|no| |checkNativeMethodParameters|true|Check method parameter of native methods|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + + + + +``` + ## WhileLoopsMustUseBraces Deprecated diff --git a/docs/pages/pmd/rules/java/design.md b/docs/pages/pmd/rules/java/design.md index 78c6bdad18..6ddb0d0ae2 100644 --- a/docs/pages/pmd/rules/java/design.md +++ b/docs/pages/pmd/rules/java/design.md @@ -115,11 +115,20 @@ public class Foo { |----|-------------|-----------|-----------| |problemDepth|3|The if statement depth reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## AvoidRethrowingException **Since:** PMD 3.8 @@ -425,11 +434,20 @@ public class Foo { |----|-------------|-----------|-----------| |threshold|20|Unique type reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CyclomaticComplexity **Since:** PMD 1.03 @@ -492,11 +510,22 @@ class Foo { |cycloOptions||Choose options for the computation of Cyclo|yes. Delimiter is '\|'.| |reportLevel|10|Deprecated Cyclomatic Complexity reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## DataClass **Since:** PMD 6.0.0 @@ -631,15 +660,24 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveImports **Since:** PMD 1.04 @@ -667,15 +705,24 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|30.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveMethodLength **Since:** PMD 0.6 @@ -703,15 +750,24 @@ public void doSomething() { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|100.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveParameterList **Since:** PMD 0.9 @@ -743,15 +799,24 @@ public void addPerson( // preferred approach |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|10.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessivePublicCount **Since:** PMD 1.04 @@ -785,15 +850,24 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|45.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## FinalFieldCouldBeStatic **Since:** PMD 1.1 @@ -879,11 +953,20 @@ public class Foo { |----|-------------|-----------|-----------| |ignoredAnnotations|lombok.Setter \| lombok.Getter \| lombok.Builder \| lombok.Data \| lombok.RequiredArgsConstructor \| lombok.AllArgsConstructor \| lombok.Value \| lombok.NoArgsConstructor|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## LawOfDemeter **Since:** PMD 5.0 @@ -998,11 +1081,21 @@ public class Bar { |packages||Restricted packages|yes. Delimiter is ','.| |classes||Allowed classes|yes. Delimiter is ','.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## ModifiedCyclomaticComplexity Deprecated @@ -1071,11 +1164,22 @@ public class Foo { // This has a Cyclomatic Complexity = 9 |showClassesComplexity|true|Add class average violations to the report|no| |reportLevel|10|Cyclomatic Complexity reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## NcssConstructorCount Deprecated @@ -1114,15 +1218,24 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|100.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssCount **Since:** PMD 6.0.0 @@ -1174,11 +1287,22 @@ class Foo { // +1, total Ncss = 12 |classReportLevel|1500|NCSS reporting threshold for classes|no| |ncssOptions||Choose options for the computation of Ncss|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## NcssMethodCount Deprecated @@ -1218,15 +1342,24 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|100.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssTypeCount Deprecated @@ -1265,15 +1398,24 @@ public class Foo extends Bar { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1500.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NPathComplexity **Since:** PMD 3.9 @@ -1337,11 +1479,20 @@ public class Foo { |reportLevel|200|N-Path Complexity reporting threshold|no| |minimum|200.0|Deprecated Minimum reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## SignatureDeclareThrowsException **Since:** PMD 1.2 @@ -1368,11 +1519,20 @@ public void foo() throws Exception { |----|-------------|-----------|-----------| |IgnoreJUnitCompletely|false|Allow all methods in a JUnit testcase to throw Exceptions|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## SimplifiedTernary **Since:** PMD 5.4.0 @@ -1623,11 +1783,22 @@ public class Foo { |checkInnerClasses|false|Check inner classes|no| |disallowNotAssignment|false|Disallow violations where the first usage is not an assignment|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## StdCyclomaticComplexity Deprecated @@ -1695,11 +1866,22 @@ public class Foo { // This has a Cyclomatic Complexity = 12 |showClassesComplexity|true|Add class average violations to the report|no| |reportLevel|10|Cyclomatic Complexity reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## SwitchDensity **Since:** PMD 1.02 @@ -1734,15 +1916,24 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|10.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## TooManyFields **Since:** PMD 3.0 @@ -1778,11 +1969,20 @@ public class Person { // this is more manageable |----|-------------|-----------|-----------| |maxfields|15|Max allowable fields|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## TooManyMethods **Since:** PMD 4.2 @@ -1814,11 +2014,20 @@ complexity and find a way to have more fine grained objects. |----|-------------|-----------|-----------| |maxmethods|10|The method count reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UselessOverridingMethod **Since:** PMD 3.3 @@ -1852,11 +2061,20 @@ public Long getId() { |----|-------------|-----------|-----------| |ignoreAnnotations|false|Ignore annotations|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UseObjectForClearerAPI **Since:** PMD 4.2.6 diff --git a/docs/pages/pmd/rules/java/documentation.md b/docs/pages/pmd/rules/java/documentation.md index 0cdedbf1a5..a8cf2374fa 100644 --- a/docs/pages/pmd/rules/java/documentation.md +++ b/docs/pages/pmd/rules/java/documentation.md @@ -32,11 +32,21 @@ A rule for the politically correct... we don't want to offend anyone. |caseSensitive|false|Case sensitive|no| |disallowedTerms|idiot \| jerk|Illegal terms or phrases|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## CommentRequired **Since:** PMD 5.1 @@ -70,11 +80,27 @@ Denotes whether comments are required (or unwanted) for specific language elemen |enumCommentRequirement|Required|Enum comments. Possible values: \[Required, Ignored, Unwanted\]|no| |serialVersionUIDCommentRequired|Ignored|Serial version UID comments. Possible values: \[Required, Ignored, Unwanted\]|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + +``` + ## CommentSize **Since:** PMD 5.0 @@ -113,11 +139,21 @@ Determines whether the dimensions of non-header comments found are within the sp |maxLines|6|Maximum lines|no| |maxLineLength|80|Maximum line length|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## UncommentedEmptyConstructor **Since:** PMD 3.4 @@ -150,11 +186,20 @@ public Foo() { |----|-------------|-----------|-----------| |ignoreExplicitConstructorInvocation|false|Ignore explicit constructor invocation when deciding whether constructor is empty or not|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UncommentedEmptyMethodBody **Since:** PMD 3.4 diff --git a/docs/pages/pmd/rules/java/errorprone.md b/docs/pages/pmd/rules/java/errorprone.md index 35cd2237ca..adb805ee8b 100644 --- a/docs/pages/pmd/rules/java/errorprone.md +++ b/docs/pages/pmd/rules/java/errorprone.md @@ -39,11 +39,23 @@ public void bar() { |allowWhile|false|Allow assignment within the conditional expression of a while statement|no| |allowIncrementDecrement|false|Allow increment or decrement operators within the conditional expression of an if, for, or while statement|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + +``` + ## AssignmentToNonFinalStatic **Since:** PMD 2.2 @@ -209,11 +221,22 @@ for (int i = 0; i < 10; i++) { |checkContinueLoopTypes|for \| do \| while|List of loop types in which continue statements will be checked|yes. Delimiter is '\|'.| |checkReturnLoopTypes|for \| do \| while|List of loop types in which return statements will be checked|yes. Delimiter is '\|'.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## AvoidCallingFinalize **Since:** PMD 3.0 @@ -389,11 +412,24 @@ private void buz(String x) {} |skipAnnotations|false|Skip literals within annotations|no| |exceptionList||List of literals to ignore. A literal is ignored if its image can be found in this list. Components of this list should not be surrounded by double quotes.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + + + +``` + ## AvoidEnumAsIdentifier **Since:** PMD 3.4 @@ -562,11 +598,20 @@ public void checkRequests() { |----|-------------|-----------|-----------| |ignoreMagicNumbers|-1,0|Comma-separated list of magic numbers, that should be ignored|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## AvoidLosingExceptionInformation **Since:** PMD 4.2.6 @@ -672,11 +717,20 @@ k = i * j; // set k with 80 not 120 |----|-------------|-----------|-----------| |strict|false|Detect violations between 00 and 07|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## BadComparison **Since:** PMD 1.8 @@ -741,11 +795,21 @@ private int getMoreFoo(){ |ignoredAnnotations|lombok.Data \| lombok.Getter \| lombok.Value|Fully qualified names of the annotation types that should be ignored by this rule|yes. Delimiter is '\|'.| |prefix||A variable prefix to skip, i.e., m\_|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## BrokenNullCheck **Since:** PMD 3.8 @@ -1129,11 +1193,22 @@ public class Bar { |types|java.sql.Connection , java.sql.Statement , java.sql.ResultSet|Affected types|yes. Delimiter is ','.| |closeAsDefaultTarget|true|Consider 'close' as a target by default|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## CompareObjectsWithEquals **Since:** PMD 3.2 @@ -1236,11 +1311,21 @@ 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.|no| |maxViolations|100|Maximum number of anomalies per class|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## DetachedTestCase **Since:** PMD 6.13.0 @@ -1571,11 +1656,21 @@ public void doSomething() { |allowCommentedBlocks|false|Empty blocks containing comments will be skipped|no| |allowExceptionNameRegex|^(ignored\|expected)$|Empty blocks catching exceptions with names matching this regular expression will be skipped|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## EmptyFinalizer **Since:** PMD 1.5 @@ -2784,11 +2879,20 @@ public class Foo { |----|-------------|-----------|-----------| |staticLoggerName|LOG|Name of the static Logger variable|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ReturnEmptyArrayRatherThanNull **Since:** PMD 4.2 diff --git a/docs/pages/pmd/rules/java/multithreading.md b/docs/pages/pmd/rules/java/multithreading.md index 1af1852efb..43373006ee 100644 --- a/docs/pages/pmd/rules/java/multithreading.md +++ b/docs/pages/pmd/rules/java/multithreading.md @@ -268,11 +268,21 @@ public static Foo getFoo() { |checkNonStaticMethods|true|Check for non-static methods. Do not set this to false and checkNonStaticFields to true.|no| |checkNonStaticFields|false|Check for non-static fields. Do not set this to true and checkNonStaticMethods to false.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## UnsynchronizedStaticDateFormatter Deprecated diff --git a/docs/pages/pmd/rules/java/performance.md b/docs/pages/pmd/rules/java/performance.md index adb891150c..039c9bf319 100644 --- a/docs/pages/pmd/rules/java/performance.md +++ b/docs/pages/pmd/rules/java/performance.md @@ -387,11 +387,20 @@ buf.append("1m"); // good |----|-------------|-----------|-----------| |threshold|1|Max consecutive appends|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## InefficientEmptyStringCheck **Since:** PMD 3.6 @@ -800,11 +809,20 @@ public class Foo { |----|-------------|-----------|-----------| |minimumNumberCaseForASwitch|3|Minimum number of branches for a switch|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## UnnecessaryWrapperObjectCreation **Since:** PMD 3.8 diff --git a/docs/pages/pmd/rules/plsql/codestyle.md b/docs/pages/pmd/rules/plsql/codestyle.md index 607d522e8c..195199aba7 100644 --- a/docs/pages/pmd/rules/plsql/codestyle.md +++ b/docs/pages/pmd/rules/plsql/codestyle.md @@ -81,11 +81,20 @@ END; |----|-------------|-----------|-----------| |indentation|2|Indentation to be used for blocks|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ForLoopNaming **Since:** PMD 6.7.0 @@ -145,11 +154,22 @@ END; |cursorPattern|\[a-zA-Z\_0-9\]{5,}|The pattern used for the curosr loop variable|no| |indexPattern|\[a-zA-Z\_0-9\]{5,}|The pattern used for the index loop variable|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## MisplacedPragma **Since:** PMD 5.5.2 diff --git a/docs/pages/pmd/rules/plsql/design.md b/docs/pages/pmd/rules/plsql/design.md index 76129b9f61..d44c48ce3b 100644 --- a/docs/pages/pmd/rules/plsql/design.md +++ b/docs/pages/pmd/rules/plsql/design.md @@ -149,11 +149,22 @@ END; |showClassesComplexity|true|Add class average violations to the report|no| |reportLevel|10|Cyclomatic Complexity reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + + + +``` + ## ExcessiveMethodLength **Since:** PMD 5.1 @@ -182,15 +193,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|100.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveObjectLength **Since:** PMD 5.1 @@ -229,15 +249,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessivePackageBodyLength **Since:** PMD 5.1 @@ -276,15 +305,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessivePackageSpecificationLength **Since:** PMD 5.1 @@ -316,15 +354,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveParameterList **Since:** PMD 5.1 @@ -358,15 +405,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|10.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ExcessiveTypeLength **Since:** PMD 5.1 @@ -405,15 +461,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssMethodCount **Since:** PMD 5.1 @@ -441,15 +506,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|100.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NcssObjectCount **Since:** PMD 5.1 @@ -479,15 +553,24 @@ CREATE OR REPLACE PACKAGE pkg_ |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1500.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NPathComplexity **Since:** PMD 5.1 @@ -541,15 +624,24 @@ END; |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|200.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## TooManyFields **Since:** PMD 5.1 @@ -579,11 +671,20 @@ END pkg_too_many_fields; |----|-------------|-----------|-----------| |maxfields|15|Max allowable fields|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## TooManyMethods **Since:** PMD 5.1 @@ -634,8 +735,17 @@ have more fine grained objects. |----|-------------|-----------|-----------| |maxmethods|1|The method count reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + diff --git a/docs/pages/pmd/rules/pom/errorprone.md b/docs/pages/pmd/rules/pom/errorprone.md index 3168a75a4a..aeb3e52dc9 100644 --- a/docs/pages/pmd/rules/pom/errorprone.md +++ b/docs/pages/pmd/rules/pom/errorprone.md @@ -50,11 +50,20 @@ The following types are considered valid: pom, jar, maven-plugin, ejb, war, ear, |----|-------------|-----------|-----------| |validTypes|pom , jar , maven-plugin , ejb , war , ear , rar , par|Set of valid types.|yes. Delimiter is ','.| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## ProjectVersionAsDependencyVersion **Since:** PMD 5.4 diff --git a/docs/pages/pmd/rules/vm/design.md b/docs/pages/pmd/rules/vm/design.md index 2b9aa4b5b6..7d4a614cc3 100644 --- a/docs/pages/pmd/rules/vm/design.md +++ b/docs/pages/pmd/rules/vm/design.md @@ -25,11 +25,20 @@ Avoid creating deeply nested if-then statements since they are harder to read an |----|-------------|-----------|-----------| |problemDepth|3|The if statement depth reporting threshold|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CollapsibleIfStatements **Since:** PMD 5.1 @@ -59,15 +68,24 @@ The template is too long. It should be broken up into smaller pieces. |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|topscore||Top score value|no| -|minimum||Minimum reporting threshold|no| -|sigma||Sigma value|no| +|topscore||Deprecated Top score value|no| +|minimum|1000.0|Minimum reporting threshold|no| +|sigma||Deprecated Sigma value|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + ## NoInlineJavaScript **Since:** PMD 5.1 diff --git a/docs/pages/pmd/rules/xsl/performance.md b/docs/pages/pmd/rules/xsl/performance.md index 400b0855d9..3b5cca3dd4 100644 --- a/docs/pages/pmd/rules/xsl/performance.md +++ b/docs/pages/pmd/rules/xsl/performance.md @@ -50,8 +50,17 @@ cutting through 100% of the document. |----|-------------|-----------|-----------| |checkSelfDescendantAbreviation|false|descendant::self abreviation, '//', will also trigger this rule.|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` +**Use this rule and customize it:** +``` xml + + + + + +``` + From 5ff9555870db58d05955ab086e99ba0a72aa6993 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Mar 2019 17:34:19 +0100 Subject: [PATCH 46/99] [plsql] Add test for TO_DATE_TO_CHAR and fix the rule --- .../resources/category/plsql/errorprone.xml | 10 ++-- .../rule/errorprone/TO_DATE_TO_CHARTest.java | 11 ++++ .../rule/errorprone/xml/TO_DATE_TO_CHAR.xml | 51 +++++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATE_TO_CHAR.xml diff --git a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml index ccc1780ef6..44aed96901 100644 --- a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml +++ b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml @@ -23,13 +23,9 @@ TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-v diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java new file mode 100644 index 0000000000..25e6b14273 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class TO_DATE_TO_CHARTest extends PmdRuleTst { + // No additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATE_TO_CHAR.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATE_TO_CHAR.xml new file mode 100644 index 0000000000..9023d8dedd --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATE_TO_CHAR.xml @@ -0,0 +1,51 @@ + + + + Example code + 1 + 8 + + + plsql + + + + Example code fixed + 0 + + + plsql + + + From 0a90468e0bb765d7245ef77a9d9451dc03207212 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Mar 2019 17:37:46 +0100 Subject: [PATCH 47/99] [plsql] Add test for TO_DATEWithoutDateFormat and fix the rule --- .../resources/category/plsql/errorprone.xml | 3 +- .../TO_DATEWithoutDateFormatTest.java | 11 +++++ .../xml/TO_DATEWithoutDateFormat.xml | 42 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATEWithoutDateFormat.xml diff --git a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml index 44aed96901..23432cc430 100644 --- a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml +++ b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml @@ -63,7 +63,8 @@ TO_DATE without date format- use TO_DATE(expression, date-format) diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java new file mode 100644 index 0000000000..e7e8d04846 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class TO_DATEWithoutDateFormatTest extends PmdRuleTst { + // No additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATEWithoutDateFormat.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATEWithoutDateFormat.xml new file mode 100644 index 0000000000..f3d2e07e5d --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_DATEWithoutDateFormat.xml @@ -0,0 +1,42 @@ + + + + Example code + 1 + 8 + + + plsql + + + From 0c98fbffc16f4a1740215471cab5acb12d65f8c2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Mar 2019 17:40:02 +0100 Subject: [PATCH 48/99] [plsql] Add test for TO_TIMESTAMPWithoutDateFormat and fix the rule --- .../resources/category/plsql/errorprone.xml | 3 +- .../TO_TIMESTAMPWithoutDateFormatTest.java | 11 +++++ .../xml/TO_TIMESTAMPWithoutDateFormat.xml | 42 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_TIMESTAMPWithoutDateFormat.xml diff --git a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml index 23432cc430..ff7127701b 100644 --- a/pmd-plsql/src/main/resources/category/plsql/errorprone.xml +++ b/pmd-plsql/src/main/resources/category/plsql/errorprone.xml @@ -115,7 +115,8 @@ TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java new file mode 100644 index 0000000000..e5a1e09976 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class TO_TIMESTAMPWithoutDateFormatTest extends PmdRuleTst { + // No additional unit tests +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_TIMESTAMPWithoutDateFormat.xml b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_TIMESTAMPWithoutDateFormat.xml new file mode 100644 index 0000000000..11e13b3787 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/rule/errorprone/xml/TO_TIMESTAMPWithoutDateFormat.xml @@ -0,0 +1,42 @@ + + + + Example code + 1 + 8 + + + plsql + + + From b2860c6b729f4e22d84f90fa02ca06951ffd5ded Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Mar 2019 17:48:23 +0100 Subject: [PATCH 49/99] Rename test classes --- .../TO_DATEWithoutDateFormatTest.java | 11 ---------- .../rule/errorprone/TO_DATE_TO_CHARTest.java | 11 ---------- .../TO_TIMESTAMPWithoutDateFormatTest.java | 11 ---------- .../rule/errorprone/ToDateToCharTest.java | 21 +++++++++++++++++++ .../ToDateWithoutDateFormatTest.java | 21 +++++++++++++++++++ .../ToTimestampWithoutDateFormatTest.java | 21 +++++++++++++++++++ 6 files changed, 63 insertions(+), 33 deletions(-) delete mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java delete mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java delete mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateToCharTest.java create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateWithoutDateFormatTest.java create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToTimestampWithoutDateFormatTest.java diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java deleted file mode 100644 index e7e8d04846..0000000000 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATEWithoutDateFormatTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.plsql.rule.errorprone; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class TO_DATEWithoutDateFormatTest extends PmdRuleTst { - // No additional unit tests -} diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java deleted file mode 100644 index 25e6b14273..0000000000 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_DATE_TO_CHARTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.plsql.rule.errorprone; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class TO_DATE_TO_CHARTest extends PmdRuleTst { - // No additional unit tests -} diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java deleted file mode 100644 index e5a1e09976..0000000000 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/TO_TIMESTAMPWithoutDateFormatTest.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.plsql.rule.errorprone; - -import net.sourceforge.pmd.testframework.PmdRuleTst; - -public class TO_TIMESTAMPWithoutDateFormatTest extends PmdRuleTst { - // No additional unit tests -} diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateToCharTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateToCharTest.java new file mode 100644 index 0000000000..046bbab1ad --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateToCharTest.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import java.util.Collections; +import java.util.List; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class ToDateToCharTest extends PmdRuleTst { + // No additional unit tests + + @Override + protected List getRules() { + Rule rule = findRule("category/plsql/errorprone.xml", "TO_DATE_TO_CHAR"); + return Collections.singletonList(rule); + } +} diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateWithoutDateFormatTest.java new file mode 100644 index 0000000000..ef77054422 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToDateWithoutDateFormatTest.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import java.util.Collections; +import java.util.List; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class ToDateWithoutDateFormatTest extends PmdRuleTst { + // No additional unit tests + + @Override + protected List getRules() { + Rule rule = findRule("category/plsql/errorprone.xml", "TO_DATEWithoutDateFormat"); + return Collections.singletonList(rule); + } +} diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToTimestampWithoutDateFormatTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToTimestampWithoutDateFormatTest.java new file mode 100644 index 0000000000..5c0b4fe312 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/rule/errorprone/ToTimestampWithoutDateFormatTest.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.rule.errorprone; + +import java.util.Collections; +import java.util.List; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.testframework.PmdRuleTst; + +public class ToTimestampWithoutDateFormatTest extends PmdRuleTst { + // No additional unit tests + + @Override + protected List getRules() { + Rule rule = findRule("category/plsql/errorprone.xml", "TO_TIMESTAMPWithoutDateFormat"); + return Collections.singletonList(rule); + } +} From 35e1e6cd8b9084ae6212337cde13a6962d132490 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 22 Mar 2019 16:33:16 +0100 Subject: [PATCH 50/99] Update release notes, fixes #1734, fixes #1735 --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8aedaffbaf..05dd5129ca 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -53,6 +53,9 @@ The designer will still be shipped with PMD's binaries. * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods +* plsql + * [#1734](https://github.com/pmd/pmd/issues/1734): \[plsql] TooManyMethods false-negative + * [#1735](https://github.com/pmd/pmd/issues/1735): \[plsql] False-negatives for TO_DATE_TO_CHAR, TO_DATEWithoutDateFormat, TO_TIMESTAMPWithoutDateFormat ### API Changes From acb30271668581c270c352d85bda4c171b404ce2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 23 Mar 2019 18:49:21 +0100 Subject: [PATCH 51/99] [apex] Expose more information on the nodes Annotation.isResolved, AnnotationParameter.getName Modifiers on various nodes (UserClass, Field, Method, ...) Method.isConstructor, Method.getReturnType --- .../pmd/lang/apex/ast/ASTAnnotation.java | 4 ++++ .../lang/apex/ast/ASTAnnotationParameter.java | 20 ++++++++++++++-- .../pmd/lang/apex/ast/ASTField.java | 4 ++++ .../ast/ASTFieldDeclarationStatements.java | 4 ++++ .../lang/apex/ast/ASTLiteralExpression.java | 4 ++++ .../pmd/lang/apex/ast/ASTMethod.java | 12 ++++++++++ .../apex/ast/ASTMethodCallExpression.java | 4 ++-- .../pmd/lang/apex/ast/ASTModifierNode.java | 2 +- .../lang/apex/ast/ASTNewObjectExpression.java | 4 ++++ .../pmd/lang/apex/ast/ASTParameter.java | 4 ++++ .../pmd/lang/apex/ast/ASTProperty.java | 4 ++++ .../pmd/lang/apex/ast/ASTUserClass.java | 4 ++++ .../pmd/lang/apex/ast/ASTUserEnum.java | 4 ++++ .../pmd/lang/apex/ast/ASTUserInterface.java | 4 ++++ .../pmd/lang/apex/ast/ASTUserTrigger.java | 4 ++++ .../ast/ASTVariableDeclarationStatements.java | 4 ++++ .../pmd/lang/apex/ast/AbstractApexNode.java | 2 +- .../pmd/lang/apex/ast/ApexRootNode.java | 7 ++++++ .../pmd/lang/apex/ast/ASTFieldTest.java | 24 +++++++++++++++++++ 19 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java index 6bc20bb3c3..4297f536bf 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotation.java @@ -47,4 +47,8 @@ public class ASTAnnotation extends AbstractApexNode { return false; } + + public boolean isResolved() { + return node.getType().isResolved(); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java index be17773e78..43bbc8cada 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTAnnotationParameter.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.apex.ast; import apex.jorje.semantic.ast.modifier.AnnotationParameter; public class ASTAnnotationParameter extends AbstractApexNode { + public static final String SEE_ALL_DATA = "seeAllData"; public ASTAnnotationParameter(AnnotationParameter annotationParameter) { super(annotationParameter); @@ -17,11 +18,26 @@ public class ASTAnnotationParameter extends AbstractApexNode implements CanSuppressWarn public String getTypeRef() { return String.valueOf(node.getTypeRef()); } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java index 56ff04c40a..358b3fb733 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclarationStatements.java @@ -31,4 +31,8 @@ public class ASTFieldDeclarationStatements extends AbstractApexNode { return node.getLiteralType(); } + public boolean isString() { + return getLiteralType() == LiteralType.STRING; + } + @Override public String getImage() { return String.valueOf(node.getLiteral()); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java index 3a73b4456a..61a8f9505d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethod.java @@ -69,4 +69,16 @@ public class ASTMethod extends AbstractApexNode implements ApexQualifiab } return false; } + + public boolean isConstructor() { + return node.getMethodInfo().isConstructor(); + } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } + + public String getReturnType() { + return node.getReturnTypeRef().toString(); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java index b15ccfd1ec..99bcd1a37f 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTMethodCallExpression.java @@ -21,13 +21,13 @@ public class ASTMethodCallExpression extends AbstractApexNode it = getNode().getReferenceContext().getNames().iterator(); it.hasNext();) { + for (Iterator it = node.getReferenceContext().getNames().iterator(); it.hasNext();) { typeName.append(it.next().getValue()).append('.'); } return typeName.toString() + methodName; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java index ed9465d9b1..0fff8cab0b 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTModifierNode.java @@ -86,7 +86,7 @@ public class ASTModifierNode extends AbstractApexNode implements A return node.getModifiers().has(ModifierTypeInfos.GLOBAL); } - public boolean hasOverride() { + public boolean isOverride() { return node.getModifiers().has(ModifierTypeInfos.OVERRIDE); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java index 7195c58afc..745578637a 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java @@ -16,4 +16,8 @@ public class ASTNewObjectExpression extends AbstractApexNode implements CanSupp } return false; } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java index d847356a9a..12fb1d3e39 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java @@ -23,4 +23,8 @@ public class ASTProperty extends AbstractApexNode { } return null; } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java index 8e8594e13e..87f94bc3ce 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserClass.java @@ -72,4 +72,8 @@ public class ASTUserClass extends ApexRootNode implements ASTUserClas } return false; } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java index 9e05252daf..7249cba5ce 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserEnum.java @@ -21,4 +21,8 @@ public class ASTUserEnum extends ApexRootNode { public String getImage() { return node.getClass().getName(); } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java index bf7995bd26..af6ccb8100 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserInterface.java @@ -69,4 +69,8 @@ public class ASTUserInterface extends ApexRootNode implements AST } return false; } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java index 3c9f5b1bef..3360750889 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTUserTrigger.java @@ -31,4 +31,8 @@ public class ASTUserTrigger extends ApexRootNode { throw new RuntimeException(e); } } + + public ASTModifierNode getModifiers() { + return getFirstChildOfType(ASTModifierNode.class); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java index 0a5a9b3155..77dbb33074 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclarationStatements.java @@ -16,4 +16,8 @@ public class ASTVariableDeclarationStatements extends AbstractApexNode extends AbstractApexNo return node; } - protected boolean hasRealLoc() { + public boolean hasRealLoc() { try { Location loc = node.getLoc(); return loc != null && Locations.isReal(loc); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java index d706474b34..f2a0fcfa40 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexRootNode.java @@ -8,6 +8,7 @@ import net.sourceforge.pmd.lang.ast.RootNode; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; import apex.jorje.semantic.ast.AstNode; +import apex.jorje.services.Version; public abstract class ApexRootNode extends AbstractApexNode implements RootNode { public ApexRootNode(T node) { @@ -22,6 +23,12 @@ public abstract class ApexRootNode extends AbstractApexNode= Version.V176.getExternal()} + * @return the apex version + */ public double getApexVersion() { return getNode().getDefiningType().getCodeUnitDetails().getVersion().getExternal(); } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java new file mode 100644 index 0000000000..c528176739 --- /dev/null +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java @@ -0,0 +1,24 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.apex.ast; + +import static net.sourceforge.pmd.lang.apex.ast.ApexParserTestHelpers.parse; + +import org.junit.Assert; +import org.junit.Test; + +import apex.jorje.semantic.ast.compilation.Compilation; + +public class ASTFieldTest { + + @Test + public void testGetType() { + ApexNode node = parse("public class Foo { private String myField = \"a\"; }"); + ASTField field = node.getFirstDescendantOfType(ASTField.class); + + Assert.assertEquals("myField", field.getImage()); + Assert.assertEquals("String", field.getTypeRef()); + } +} From 8b1b67ae9ed0ee7e105c912594dc94ecdd1dd424 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 23 Mar 2019 18:54:26 +0100 Subject: [PATCH 52/99] [apex] Refactor rules to use new nodes attributes This moves the dependency to jorje into the AST nodes and keeps the rules only dependent on PMD. --- .../apex/rule/AbstractApexUnitTestRule.java | 7 +-- ...nitTestShouldNotUseSeeAllDataTrueRule.java | 32 +++------- .../AvoidGlobalModifierRule.java | 6 +- .../AvoidLogicInTriggerRule.java | 1 + .../MethodNamingConventionsRule.java | 15 ++--- .../VariableNamingConventionsRule.java | 14 ++--- .../rule/design/ExcessiveClassLengthRule.java | 4 +- .../rule/design/ExcessivePublicCountRule.java | 7 +-- .../rule/design/NcssConstructorCountRule.java | 2 +- .../apex/rule/design/NcssMethodCountRule.java | 4 +- .../design/StdCyclomaticComplexityRule.java | 2 +- .../apex/rule/design/TooManyFieldsRule.java | 10 ++- .../apex/rule/documentation/ApexDocRule.java | 26 +++----- .../errorprone/AvoidHardcodingIdRule.java | 5 +- .../AvoidNonExistentAnnotationsRule.java | 61 ++++--------------- ...ethodWithSameNameAsEnclosingClassRule.java | 6 +- .../lang/apex/rule/security/ApexCSRFRule.java | 4 +- .../security/ApexDangerousMethodsRule.java | 6 +- .../security/ApexInsecureEndpointRule.java | 16 ++--- .../rule/security/ApexOpenRedirectRule.java | 32 ++-------- .../security/ApexXSSFromURLParamRule.java | 6 +- .../pmd/lang/apex/rule/security/Helper.java | 2 +- 22 files changed, 85 insertions(+), 183 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/AbstractApexUnitTestRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/AbstractApexUnitTestRule.java index 974954d0b2..de089b5d89 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/AbstractApexUnitTestRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/AbstractApexUnitTestRule.java @@ -25,12 +25,11 @@ public abstract class AbstractApexUnitTestRule extends AbstractApexRule { /** * Don't bother visiting this class if it's not a class with @isTest and - * newer than API v24 + * newer than API v24 (V176 internal). */ @Override public Object visit(final ASTUserClass node, final Object data) { - final Version classApiVersion = node.getNode().getDefiningType().getCodeUnitDetails().getVersion(); - if (!isTestMethodOrClass(node) && classApiVersion.isGreaterThan(Version.V174)) { + if (!isTestMethodOrClass(node) && node.getApexVersion() >= Version.V176.getExternal()) { return data; } return super.visit(node, data); @@ -38,6 +37,6 @@ public abstract class AbstractApexUnitTestRule extends AbstractApexRule { protected boolean isTestMethodOrClass(final ApexNode node) { final ASTModifierNode modifierNode = node.getFirstChildOfType(ASTModifierNode.class); - return modifierNode != null && modifierNode.getNode().getModifiers().isTest(); + return modifierNode != null && modifierNode.isTest(); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestShouldNotUseSeeAllDataTrueRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestShouldNotUseSeeAllDataTrueRule.java index 38788da466..496ef408f7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestShouldNotUseSeeAllDataTrueRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestShouldNotUseSeeAllDataTrueRule.java @@ -4,18 +4,15 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; +import java.util.List; + +import net.sourceforge.pmd.lang.apex.ast.ASTAnnotationParameter; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; -import apex.jorje.semantic.ast.modifier.Annotation; -import apex.jorje.semantic.ast.modifier.AnnotationParameter; -import apex.jorje.semantic.ast.modifier.ModifierOrAnnotation; -import apex.jorje.semantic.symbol.type.AnnotationTypeInfos; -import apex.jorje.semantic.symbol.type.ModifierOrAnnotationTypeInfo; -import apex.jorje.semantic.symbol.type.TypeInfoEquivalence; import apex.jorje.services.Version; /** @@ -31,11 +28,8 @@ public class ApexUnitTestShouldNotUseSeeAllDataTrueRule extends AbstractApexUnit @Override public Object visit(final ASTUserClass node, final Object data) { - // @isTest(seeAllData) was introduced in v24, and was set to false by - // default - final Version classApiVersion = node.getNode().getDefiningType().getCodeUnitDetails().getVersion(); - - if (!isTestMethodOrClass(node) && classApiVersion.isGreaterThan(Version.V174)) { + // @isTest(seeAllData) was introduced in v24, and was set to false by default + if (!isTestMethodOrClass(node) && node.getApexVersion() >= Version.V176.getExternal()) { return data; } @@ -56,17 +50,11 @@ public class ApexUnitTestShouldNotUseSeeAllDataTrueRule extends AbstractApexUnit final ASTModifierNode modifierNode = node.getFirstChildOfType(ASTModifierNode.class); if (modifierNode != null) { - for (final ModifierOrAnnotationTypeInfo modifierOrAnnotationTypeInfo : modifierNode.getNode().getModifiers().all()) { - ModifierOrAnnotation modifierOrAnnotation = modifierNode.getNode().getModifiers().get(modifierOrAnnotationTypeInfo); - if (modifierOrAnnotation instanceof Annotation && TypeInfoEquivalence - .isEquivalent(modifierOrAnnotationTypeInfo, AnnotationTypeInfos.IS_TEST)) { - final Annotation annotation = (Annotation) modifierOrAnnotation; - final AnnotationParameter parameter = annotation.getParameter("seeAllData"); - - if (parameter != null && parameter.getBooleanValue() == true) { - addViolation(data, node); - return data; - } + List annotationParameters = modifierNode.findDescendantsOfType(ASTAnnotationParameter.class); + for (ASTAnnotationParameter parameter : annotationParameters) { + if (ASTAnnotationParameter.SEE_ALL_DATA.equals(parameter.getName()) && parameter.getBooleanValue()) { + addViolation(data, node); + return data; } } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidGlobalModifierRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidGlobalModifierRule.java index 9d583e7f0c..095c20bc38 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidGlobalModifierRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidGlobalModifierRule.java @@ -14,8 +14,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.semantic.symbol.type.ModifierTypeInfos; - public class AvoidGlobalModifierRule extends AbstractApexRule { public AvoidGlobalModifierRule() { @@ -56,11 +54,11 @@ public class AvoidGlobalModifierRule extends AbstractApexRule { } private boolean isWebService(ASTModifierNode modifierNode) { - return modifierNode != null && modifierNode.getNode().getModifiers().has(ModifierTypeInfos.WEB_SERVICE); + return modifierNode != null && modifierNode.isWebService(); } private boolean isGlobal(ASTModifierNode modifierNode) { - return modifierNode != null && modifierNode.getNode().getModifiers().has(ModifierTypeInfos.GLOBAL); + return modifierNode != null && modifierNode.isGlobal(); } private boolean hasRestAnnotation(ASTModifierNode modifierNode) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidLogicInTriggerRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidLogicInTriggerRule.java index 3d74db85c0..1bfcb6c5c1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidLogicInTriggerRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/AvoidLogicInTriggerRule.java @@ -16,6 +16,7 @@ public class AvoidLogicInTriggerRule extends AbstractApexRule { setProperty(CODECLIMATE_CATEGORIES, "Style"); setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 200); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); + addRuleChainVisit(ASTUserTrigger.class); } @Override diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/MethodNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/MethodNamingConventionsRule.java index 878231067a..af57206f65 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/MethodNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/MethodNamingConventionsRule.java @@ -4,13 +4,10 @@ package net.sourceforge.pmd.lang.apex.rule.codestyle; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.OVERRIDE; import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTProperty; -import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -29,11 +26,8 @@ public class MethodNamingConventionsRule extends AbstractApexRule { // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 1); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); - } - @Override - public Object visit(ASTUserClass node, Object data) { - return super.visit(node, data); + addRuleChainVisit(ASTMethod.class); } @Override @@ -57,7 +51,7 @@ public class MethodNamingConventionsRule extends AbstractApexRule { } private boolean isOverriddenMethod(ASTMethod node) { - return node.getNode().getModifiers().has(OVERRIDE); + return node.getModifiers().isOverride(); } private boolean isPropertyAccessor(ASTMethod node) { @@ -65,11 +59,10 @@ public class MethodNamingConventionsRule extends AbstractApexRule { } private boolean isConstructor(ASTMethod node) { - return node.getNode().getMethodInfo().isConstructor(); + return node.isConstructor(); } private boolean isTestMethod(ASTMethod node) { - final ASTModifierNode modifierNode = node.getFirstChildOfType(ASTModifierNode.class); - return modifierNode != null && modifierNode.isTest(); + return node.getModifiers().isTest(); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java index 6472460446..ff1cc6caa2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codestyle/VariableNamingConventionsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.codestyle; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; import static net.sourceforge.pmd.properties.PropertyFactory.booleanProperty; import static net.sourceforge.pmd.properties.PropertyFactory.stringListProperty; @@ -18,6 +16,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; +import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclarationStatements; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -141,8 +140,8 @@ public class VariableNamingConventionsRule extends AbstractApexRule { if (!checkMembers) { return data; } - boolean isStatic = node.getNode().getFieldInfo().getModifiers().has(STATIC); - boolean isFinal = node.getNode().getFieldInfo().getModifiers().has(FINAL); + boolean isStatic = node.getModifiers().isStatic(); + boolean isFinal = node.getModifiers().isFinal(); return checkName(isStatic ? staticPrefixes : memberPrefixes, isStatic ? staticSuffixes : memberSuffixes, node, isStatic, isFinal, data); @@ -155,7 +154,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { return data; } - boolean isFinal = node.getNode().getLocalInfo().getModifiers().has(FINAL); + boolean isFinal = node.getFirstParentOfType(ASTVariableDeclarationStatements.class).getModifiers().isFinal(); return checkName(localPrefixes, localSuffixes, node, false, isFinal, data); } @@ -165,7 +164,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { return data; } - boolean isFinal = node.getNode().getModifierInfo().has(FINAL); + boolean isFinal = node.getModifiers().isFinal(); return checkName(parameterPrefixes, parameterSuffixes, node, false, isFinal, data); } @@ -212,8 +211,7 @@ public class VariableNamingConventionsRule extends AbstractApexRule { if (suffixes != null) { for (String suffix : suffixes) { if (varName.endsWith(suffix)) { - varName = varName.substring(0, varName.length() - suffix.length()); - break; + return varName.substring(0, varName.length() - suffix.length()); } } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessiveClassLengthRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessiveClassLengthRule.java index 5bd4156c04..a34a524979 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessiveClassLengthRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessiveClassLengthRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.design; -import static apex.jorje.semantic.symbol.type.AnnotationTypeInfos.IS_TEST; - import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; /** @@ -24,7 +22,7 @@ public class ExcessiveClassLengthRule extends ExcessiveLengthRule { @Override public Object visit(ASTUserClass node, Object data) { - if (node.getNode().getModifiers().getModifiers().not(IS_TEST)) { + if (!node.getModifiers().isTest()) { return super.visit(node, data); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java index 8c8be1c698..ec38a69771 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/ExcessivePublicCountRule.java @@ -4,9 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.design; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.PUBLIC; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; - import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclarationStatements; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; @@ -38,7 +35,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule { @Override public Object visit(ASTMethod node, Object data) { - if (node.getNode().getModifiers().has(PUBLIC) && !node.getImage().matches("||clone")) { + if (node.getModifiers().isPublic() && !node.getImage().matches("||clone")) { return NumericConstants.ONE; } return NumericConstants.ZERO; @@ -46,7 +43,7 @@ public class ExcessivePublicCountRule extends ExcessiveNodeCountRule { @Override public Object visit(ASTFieldDeclarationStatements node, Object data) { - if (node.getNode().getModifiers().has(PUBLIC) && !node.getNode().getModifiers().has(STATIC)) { + if (node.getModifiers().isPublic() && !node.getModifiers().isStatic()) { return NumericConstants.ONE; } return NumericConstants.ZERO; diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssConstructorCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssConstructorCountRule.java index f9ba66be18..4c4c40b698 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssConstructorCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssConstructorCountRule.java @@ -28,7 +28,7 @@ public class NcssConstructorCountRule extends AbstractNcssCountRule { @Override public Object visit(ASTMethod node, Object data) { - if (node.getNode().getMethodInfo().isConstructor()) { + if (node.isConstructor()) { return super.visit(node, data); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssMethodCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssMethodCountRule.java index 0604ecfa07..563e5a5e8c 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssMethodCountRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/NcssMethodCountRule.java @@ -28,7 +28,7 @@ public class NcssMethodCountRule extends AbstractNcssCountRule { @Override public Object visit(ASTMethod node, Object data) { - if (!node.getNode().getMethodInfo().isConstructor()) { + if (!node.isConstructor()) { return super.visit(node, data); } @@ -37,7 +37,7 @@ public class NcssMethodCountRule extends AbstractNcssCountRule { @Override public Object[] getViolationParameters(DataPoint point) { - return new String[] { ((ASTMethod) point.getNode()).getNode().getMethodInfo().getName(), + return new String[] { ((ASTMethod) point.getNode()).getImage(), String.valueOf((int) point.getScore()), }; } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java index 37bb9d4598..82c4544574 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/StdCyclomaticComplexityRule.java @@ -155,7 +155,7 @@ public class StdCyclomaticComplexityRule extends AbstractApexRule { } if (showMethodsComplexity && methodEntry.decisionPoints >= reportLevel) { - String methodType = node.getNode().getMethodInfo().isConstructor() ? "constructor" : "method"; + String methodType = node.isConstructor() ? "constructor" : "method"; addViolation(data, node, new String[] { methodType, node.getImage(), String.valueOf(methodEntry.decisionPoints) }); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java index 31f47b78a8..971b8e48eb 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/design/TooManyFieldsRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.design; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.FINAL; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.STATIC; import static net.sourceforge.pmd.properties.constraints.NumericConstraints.positive; import java.util.HashMap; @@ -51,13 +49,13 @@ public class TooManyFieldsRule extends AbstractApexRule { stats = new HashMap<>(5); nodes = new HashMap<>(5); - List l = node.findDescendantsOfType(ASTField.class); + List fields = node.findDescendantsOfType(ASTField.class); - for (ASTField fd : l) { - if (fd.getNode().getModifierInfo().all(FINAL, STATIC)) { + for (ASTField field : fields) { + if (field.getModifiers().isFinal() && field.getModifiers().isStatic()) { continue; } - ASTUserClass clazz = fd.getFirstParentOfType(ASTUserClass.class); + ASTUserClass clazz = field.getFirstParentOfType(ASTUserClass.class); if (clazz != null) { bumpCounterFor(clazz); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/documentation/ApexDocRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/documentation/ApexDocRule.java index d50277fd23..96b10c3703 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/documentation/ApexDocRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/documentation/ApexDocRule.java @@ -4,9 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.documentation; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.GLOBAL; -import static apex.jorje.semantic.symbol.type.ModifierTypeInfos.OVERRIDE; - import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -17,15 +14,14 @@ import net.sourceforge.pmd.lang.apex.ast.ASTAnnotation; import net.sourceforge.pmd.lang.apex.ast.ASTFormalComment; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; +import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTProperty; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; +import net.sourceforge.pmd.lang.apex.ast.AbstractApexNode; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.data.Locations; -import apex.jorje.semantic.ast.modifier.ModifierGroup; - public class ApexDocRule extends AbstractApexRule { private static final Pattern DESCRIPTION_PATTERN = Pattern.compile("@description\\s"); private static final Pattern RETURN_PATTERN = Pattern.compile("@return\\s"); @@ -73,7 +69,7 @@ public class ApexDocRule extends AbstractApexRule { addViolationWithMessage(data, node, MISSING_DESCRIPTION_MESSAGE); } - String returnType = node.getNode().getReturnTypeRef().toString(); + String returnType = node.getReturnType(); boolean shouldHaveReturn = !(returnType.isEmpty() || "void".equalsIgnoreCase(returnType)); if (comment.hasReturn != shouldHaveReturn) { if (shouldHaveReturn) { @@ -84,8 +80,8 @@ public class ApexDocRule extends AbstractApexRule { } // Collect parameter names in order - final List params = node.getNode().getMethodInfo().getParameters() - .stream().map(p -> p.getName().getValue()).collect(Collectors.toList()); + final List params = node.findChildrenOfType(ASTParameter.class) + .stream().map(p -> p.getImage()).collect(Collectors.toList()); if (!comment.params.equals(params)) { addViolationWithMessage(data, node, MISMATCHED_PARAM_MESSAGE); @@ -111,7 +107,7 @@ public class ApexDocRule extends AbstractApexRule { return data; } - private void handleClassOrInterface(ApexNode node, Object data) { + private void handleClassOrInterface(AbstractApexNode node, Object data) { ApexDocComment comment = getApexDocComment(node); if (comment == null) { if (shouldHaveApexDocs(node)) { @@ -124,8 +120,8 @@ public class ApexDocRule extends AbstractApexRule { } } - private boolean shouldHaveApexDocs(ApexNode node) { - if (node.getNode().getLoc() == Locations.NONE) { + private boolean shouldHaveApexDocs(AbstractApexNode node) { + if (!node.hasRealLoc()) { return false; } @@ -138,11 +134,7 @@ public class ApexDocRule extends AbstractApexRule { ASTModifierNode modifier = node.getFirstChildOfType(ASTModifierNode.class); if (modifier != null) { - boolean isPublic = modifier.isPublic(); - ModifierGroup modifierGroup = modifier.getNode().getModifiers(); - boolean isGlobal = modifierGroup.has(GLOBAL); - boolean isOverride = modifierGroup.has(OVERRIDE); - return (isPublic || isGlobal) && !isOverride; + return (modifier.isPublic() || modifier.isGlobal()) && !modifier.isOverride(); } return false; } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidHardcodingIdRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidHardcodingIdRule.java index 248784713d..b536b34648 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidHardcodingIdRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidHardcodingIdRule.java @@ -37,9 +37,8 @@ public class AvoidHardcodingIdRule extends AbstractApexRule { @Override public Object visit(ASTLiteralExpression node, Object data) { - Object o = node.getNode().getLiteral(); - if (o instanceof String) { - String literal = (String) o; + if (node.isString()) { + String literal = node.getImage(); if (PATTERN.matcher(literal).matches()) { // 18-digit ids are just 15 digit ids + checksums, validate it or it's not an id if (literal.length() == 18 && !validateChecksum(literal)) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidNonExistentAnnotationsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidNonExistentAnnotationsRule.java index 11eeb52b2b..59a8b63e09 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidNonExistentAnnotationsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/AvoidNonExistentAnnotationsRule.java @@ -4,11 +4,10 @@ package net.sourceforge.pmd.lang.apex.rule.errorprone; -import java.util.HashSet; -import java.util.Set; - +import net.sourceforge.pmd.lang.apex.ast.ASTAnnotation; import net.sourceforge.pmd.lang.apex.ast.ASTField; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; +import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTProperty; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTUserEnum; @@ -16,17 +15,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; import net.sourceforge.pmd.lang.apex.ast.AbstractApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.semantic.ast.compilation.UserClass; -import apex.jorje.semantic.ast.compilation.UserEnum; -import apex.jorje.semantic.ast.compilation.UserInterface; -import apex.jorje.semantic.ast.member.Field; -import apex.jorje.semantic.ast.member.Method; -import apex.jorje.semantic.ast.member.Property; -import apex.jorje.semantic.ast.modifier.Annotation; -import apex.jorje.semantic.ast.modifier.ModifierNode; -import apex.jorje.semantic.symbol.type.AnnotationTypeInfos; -import apex.jorje.semantic.symbol.type.StandardAnnotationTypeInfo; - /** * Apex supported non existent annotations for legacy reasons. * In the future, use of such non-existent annotations could result in broken apex code that will not compile. @@ -36,71 +24,46 @@ import apex.jorje.semantic.symbol.type.StandardAnnotationTypeInfo; * @author a.subramanian */ public class AvoidNonExistentAnnotationsRule extends AbstractApexRule { - - private static final Set SUPPORTED_APEX_ANNOTATIONS = getSupportedApexAnnotations(); - @Override public Object visit(final ASTUserClass node, final Object data) { - final UserClass userClass = node.getNode(); - checkForNonExistentAnnotation(node, userClass.getModifiers(), data); + checkForNonExistentAnnotation(node, node.getModifiers(), data); return super.visit(node, data); } @Override - public final Object visit(ASTUserInterface node, final Object data) { - final UserInterface userInterface = node.getNode(); - checkForNonExistentAnnotation(node, userInterface.getModifiers(), data); + public Object visit(final ASTUserInterface node, final Object data) { + checkForNonExistentAnnotation(node, node.getModifiers(), data); return super.visit(node, data); } @Override public Object visit(final ASTUserEnum node, final Object data) { - final UserEnum userEnum = node.getNode(); - checkForNonExistentAnnotation(node, userEnum.getModifiers(), data); + checkForNonExistentAnnotation(node, node.getModifiers(), data); return super.visit(node, data); } @Override public Object visit(final ASTMethod node, final Object data) { - final Method method = node.getNode(); - return checkForNonExistentAnnotation(node, method.getModifiersNode(), data); + return checkForNonExistentAnnotation(node, node.getModifiers(), data); } @Override public Object visit(final ASTProperty node, final Object data) { - final Property property = node.getNode(); // may have nested methods, don't visit children - return checkForNonExistentAnnotation(node, property.getModifiersNode(), data); + return checkForNonExistentAnnotation(node, node.getModifiers(), data); } @Override public Object visit(final ASTField node, final Object data) { - final Field field = node.getNode(); - return checkForNonExistentAnnotation(node, field.getModifiers(), data); + return checkForNonExistentAnnotation(node, node.getModifiers(), data); } - private Object checkForNonExistentAnnotation(final AbstractApexNode node, final ModifierNode modifierNode, final Object data) { - for (final Annotation annotation : modifierNode.getModifiers().getAnnotations()) { - if (!SUPPORTED_APEX_ANNOTATIONS.contains(annotation.getType())) { + private Object checkForNonExistentAnnotation(final AbstractApexNode node, final ASTModifierNode modifierNode, final Object data) { + for (ASTAnnotation annotation : modifierNode.findChildrenOfType(ASTAnnotation.class)) { + if (!annotation.isResolved()) { addViolationWithMessage(data, node, "Use of non existent annotations will lead to broken Apex code which will not compile in the future."); } } return data; } - - private static Set getSupportedApexAnnotations() { - final java.lang.reflect.Field[] fields = AnnotationTypeInfos.class.getFields(); - final Set annotationTypeInfos = new HashSet<>(); - for (final java.lang.reflect.Field field : fields) { - if (field.getType().isAssignableFrom(StandardAnnotationTypeInfo.class)) { - field.setAccessible(true); - try { - annotationTypeInfos.add((StandardAnnotationTypeInfo) field.get(null)); - } catch (final Exception illegalAccessException) { - continue; - } - } - } - return annotationTypeInfos; - } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/MethodWithSameNameAsEnclosingClassRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/MethodWithSameNameAsEnclosingClassRule.java index 835b8575c0..8b1e8b4a93 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/MethodWithSameNameAsEnclosingClassRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/errorprone/MethodWithSameNameAsEnclosingClassRule.java @@ -17,6 +17,8 @@ public class MethodWithSameNameAsEnclosingClassRule extends AbstractApexRule { // Note: x10 as Apex has not automatic refactoring setProperty(CODECLIMATE_REMEDIATION_MULTIPLIER, 50); setProperty(CODECLIMATE_BLOCK_HIGHLIGHTING, false); + + addRuleChainVisit(ASTUserClass.class); } @Override @@ -28,11 +30,11 @@ public class MethodWithSameNameAsEnclosingClassRule extends AbstractApexRule { for (ASTMethod m : methods) { String methodName = m.getImage(); - if (!m.getNode().getMethodInfo().isConstructor() && methodName.equalsIgnoreCase(className)) { + if (!m.isConstructor() && methodName.equalsIgnoreCase(className)) { addViolation(data, m); } } - return super.visit(node, data); + return data; } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java index 0d24dc782c..e77199cb63 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCSRFRule.java @@ -46,14 +46,14 @@ public class ApexCSRFRule extends AbstractApexRule { * @param data */ private void checkForCSRF(ASTMethod node, Object data) { - if (node.getNode().getMethodInfo().isConstructor()) { + if (node.isConstructor()) { if (Helper.foundAnyDML(node)) { addViolation(data, node); } } - String name = node.getNode().getMethodInfo().getName(); + String name = node.getImage(); if (name.equalsIgnoreCase(INIT)) { if (Helper.foundAnyDML(node)) { addViolation(data, node); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java index 91d9a6dfe4..f44c398b7e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexDangerousMethodsRule.java @@ -73,7 +73,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { private void collectBenignVariables(ASTUserClass node) { List fields = node.findDescendantsOfType(ASTField.class); for (ASTField field : fields) { - if (BOOLEAN.equalsIgnoreCase(field.getNode().getFieldInfo().getType().getApexName())) { + if (BOOLEAN.equalsIgnoreCase(field.getTypeRef())) { whiteListedVariables.add(Helper.getFQVariableName(field)); } @@ -81,7 +81,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { List declarations = node.findDescendantsOfType(ASTVariableDeclaration.class); for (ASTVariableDeclaration decl : declarations) { - if (BOOLEAN.equalsIgnoreCase(decl.getNode().getLocalInfo().getType().getApexName())) { + if (BOOLEAN.equalsIgnoreCase(decl.getTypeName())) { whiteListedVariables.add(Helper.getFQVariableName(decl)); } } @@ -91,7 +91,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { private void validateParameters(ASTMethodCallExpression methodCall, Object data) { List variables = methodCall.findDescendantsOfType(ASTVariableExpression.class); for (ASTVariableExpression var : variables) { - if (REGEXP.matcher(var.getNode().getIdentifier().getValue()).matches()) { + if (REGEXP.matcher(var.getImage()).matches()) { if (!whiteListedVariables.contains(Helper.getFQVariableName(var))) { addViolation(data, methodCall); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java index aff2755b47..1375e476bf 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexInsecureEndpointRule.java @@ -70,9 +70,8 @@ public class ApexInsecureEndpointRule extends AbstractApexRule { ASTLiteralExpression literalNode = node.getFirstChildOfType(ASTLiteralExpression.class); if (literalNode != null && variableNode != null) { - Object o = literalNode.getNode().getLiteral(); - if (o instanceof String) { - String literal = (String) o; + if (literalNode.isString()) { + String literal = literalNode.getImage(); if (PATTERN.matcher(literal).matches()) { httpEndpointStrings.add(Helper.getFQVariableName(variableNode)); } @@ -102,13 +101,10 @@ public class ApexInsecureEndpointRule extends AbstractApexRule { private void runChecks(AbstractApexNode node, Object data) { ASTLiteralExpression literalNode = node.getFirstChildOfType(ASTLiteralExpression.class); - if (literalNode != null) { - Object o = literalNode.getNode().getLiteral(); - if (o instanceof String) { - String literal = (String) o; - if (PATTERN.matcher(literal).matches()) { - addViolation(data, literalNode); - } + if (literalNode != null && literalNode.isString()) { + String literal = literalNode.getImage(); + if (PATTERN.matcher(literal).matches()) { + addViolation(data, literalNode); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java index 3485828004..520ac77068 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.security; -import java.lang.reflect.Field; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -22,8 +21,6 @@ import net.sourceforge.pmd.lang.apex.ast.AbstractApexNode; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.data.Identifier; -import apex.jorje.data.ast.TypeRefs.ClassTypeRef; import apex.jorje.semantic.symbol.member.variable.StandardFieldInfo; /** @@ -102,26 +99,12 @@ public class ApexOpenRedirectRule extends AbstractApexRule { } } else { if (node instanceof ASTField) { - /* - * sergey.gorbaty: Apex Jorje parser is returning a null from - * Field.getFieldInfo(), but the info is available from an inner - * field. DO NOT attempt to optimize this block without checking - * that Jorje parser actually fixed its bug. - * - */ - try { - final Field f = node.getNode().getClass().getDeclaredField("fieldInfo"); - f.setAccessible(true); - final StandardFieldInfo fieldInfo = (StandardFieldInfo) f.get(node.getNode()); - if (fieldInfo.getType().getApexName().equalsIgnoreCase("String")) { - if (fieldInfo.getValue() != null) { - addVariable(fieldInfo); - } + ASTField field = (ASTField) node; + if ("String".equalsIgnoreCase(field.getTypeRef())) { + StandardFieldInfo fieldInfo = (StandardFieldInfo) field.getNode().getFieldInfo(); + if (fieldInfo.getValue() != null) { + addVariable(fieldInfo); } - - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException - | IllegalAccessException e) { - throw new RuntimeException(e); } } } @@ -159,10 +142,7 @@ public class ApexOpenRedirectRule extends AbstractApexRule { return; } - ClassTypeRef classRef = (ClassTypeRef) node.getNode().getTypeRef(); - Identifier identifier = classRef.getNames().get(0); - - if (identifier.getValue().equalsIgnoreCase(PAGEREFERENCE)) { + if (node.getTypeRef().equalsIgnoreCase(PAGEREFERENCE)) { getObjectValue(node, data); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java index 1a2e588442..b1669bbc9d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java @@ -120,7 +120,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { private String getReturnType(ASTReturnStatement node) { ASTMethod method = node.getFirstParentOfType(ASTMethod.class); if (method != null) { - return method.getNode().getMethodInfo().getReturnType().getApexName(); + return method.getReturnType(); } return ""; @@ -175,7 +175,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { String varType = null; if (node instanceof ASTVariableDeclaration) { - varType = ((ASTVariableDeclaration) node).getNode().getLocalInfo().getType().getApexName(); + varType = ((ASTVariableDeclaration) node).getTypeName(); } @@ -214,7 +214,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { String varType = null; if (node instanceof ASTVariableDeclaration) { - varType = ((ASTVariableDeclaration) node).getNode().getLocalInfo().getType().getApexName(); + varType = ((ASTVariableDeclaration) node).getTypeName(); } if (varType == null || !"id".equalsIgnoreCase(varType)) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java index 4aae267893..fb40bfacf9 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java @@ -53,7 +53,7 @@ public final class Helper { static boolean isTestMethodOrClass(final ApexNode node) { final List modifierNode = node.findChildrenOfType(ASTModifierNode.class); for (final ASTModifierNode m : modifierNode) { - if (m.getNode().getModifiers().isTest()) { + if (m.isTest()) { return true; } } From 99f9cc60545825680f51cc218be88f3dd4206715 Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 23 Mar 2019 14:49:50 -0700 Subject: [PATCH 53/99] Modified is test annotation rule and renamed ApexAssertionsShouldIncludeMessage rule --- docs/pages/pmd/rules/apex/bestpractices.md | 2 +- ...exAssertionsShouldIncludeMessageRule.java} | 16 ++-- ...tMethodShouldHaveIsTestAnnotationRule.java | 76 +++++++------------ .../resources/category/apex/bestpractices.xml | 10 ++- .../main/resources/rulesets/apex/ruleset.xml | 9 --- ...exAssertionsShouldIncludeMessageTest.java} | 2 +- ...=> ApexAssertionsShouldIncludeMessage.xml} | 0 ...itTestMethodShouldHaveIsTestAnnotation.xml | 21 ++++- 8 files changed, 61 insertions(+), 75 deletions(-) rename pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/{ApexUnitTestAssertStatementRule.java => ApexAssertionsShouldIncludeMessageRule.java} (80%) rename pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/{ApexUnitTestAssertStatementTest.java => ApexAssertionsShouldIncludeMessageTest.java} (76%) rename pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/{ApexUnitTestAssertStatement.xml => ApexAssertionsShouldIncludeMessage.xml} (100%) diff --git a/docs/pages/pmd/rules/apex/bestpractices.md b/docs/pages/pmd/rules/apex/bestpractices.md index d3d684aed8..6c3e96b13f 100644 --- a/docs/pages/pmd/rules/apex/bestpractices.md +++ b/docs/pages/pmd/rules/apex/bestpractices.md @@ -18,7 +18,7 @@ language: Apex The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. -**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexUnitTestAssertStatementRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java) +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java) **Example(s):** diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java similarity index 80% rename from pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java rename to pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java index 35ff462122..8aced97aca 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java @@ -17,20 +17,20 @@ import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; * * @author sudhansu */ -public class ApexUnitTestAssertStatementRule extends AbstractApexUnitTestRule { +public class ApexAssertionsShouldIncludeMessageRule extends AbstractApexUnitTestRule { private static final Set ASSERT_METHODS = new HashSet<>(); - private static final String ASSERT = "system.assert"; - private static final String ASSERT_EQUALS = "system.assertequals"; - private static final String ASSERT_NOT_EQUALS = "system.assertnotequals"; + private static final String ASSERT = "System.assert"; + private static final String ASSERT_EQUALS = "System.assertEquals"; + private static final String ASSERT_NOT_EQUALS = "System.assertNotEquals"; static { - ASSERT_METHODS.add(ASSERT); - ASSERT_METHODS.add(ASSERT_EQUALS); - ASSERT_METHODS.add(ASSERT_NOT_EQUALS); + ASSERT_METHODS.add(ASSERT.toLowerCase(Locale.ROOT)); + ASSERT_METHODS.add(ASSERT_EQUALS.toLowerCase(Locale.ROOT)); + ASSERT_METHODS.add(ASSERT_NOT_EQUALS.toLowerCase(Locale.ROOT) ); } - public ApexUnitTestAssertStatementRule() { + public ApexAssertionsShouldIncludeMessageRule() { addRuleChainVisit(ASTMethodCallExpression.class); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java index 6d8ca1f082..973ded14d5 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java @@ -4,77 +4,53 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Map; +import java.util.Set; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; -import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; +import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; -import apex.jorje.semantic.ast.modifier.Annotation; -import apex.jorje.semantic.ast.modifier.ModifierOrAnnotation; -import apex.jorje.semantic.symbol.type.AnnotationTypeInfos; -import apex.jorje.semantic.symbol.type.ModifierOrAnnotationTypeInfo; -import apex.jorje.semantic.symbol.type.TypeInfoEquivalence; -import apex.jorje.services.Version; - public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractApexUnitTestRule { - private static final String TEST = "test"; + private static final Set ASSERT_METHODS = new HashSet<>(); + private static final String ASSERT = "system.assert"; + private static final String ASSERT_EQUALS = "system.assertequals"; + private static final String ASSERT_NOT_EQUALS = "system.assertnotequals"; + + static { + ASSERT_METHODS.add(ASSERT); + ASSERT_METHODS.add(ASSERT_EQUALS); + ASSERT_METHODS.add(ASSERT_NOT_EQUALS); + } public ApexUnitTestMethodShouldHaveIsTestAnnotationRule() { - addRuleChainVisit(ASTUserClass.class); + addRuleChainVisit(ASTMethod.class); } @Override - public Object visit(final ASTUserClass node, final Object data) { + public Object visit(final ASTMethod node, final Object data) { // test methods should have @isTest annotation. - final Version classApiVersion = node.getNode().getDefiningType().getCodeUnitDetails().getVersion(); - - if (!isTestMethodOrClass(node) && classApiVersion.isGreaterThan(Version.V174)) { + if (isTestMethodOrClass(node)) { return data; } - - checkForIsTestAnnotation(node, data); - return data; + return checkForIsTestAnnotation(node, data); } private Object checkForIsTestAnnotation(final ApexNode node, final Object data) { - final List methods = node.findDescendantsOfType(ASTMethod.class); - final List testMethods = new ArrayList<>(); - for (ASTMethod method : methods) { - final Version classApiVersion = method.getNode().getDefiningType().getCodeUnitDetails().getVersion(); - if (!isTestMethodOrClass(method) && classApiVersion.isGreaterThan(Version.V174) - && !method.getImage().toLowerCase(Locale.ROOT).contains(TEST)) { - continue; - } - testMethods.add(method); + ASTMethod testMethod = (ASTMethod) node; + if (testMethod == null) { + return data; } - Map methodLocMap = new HashMap<>(); - for (ASTMethod testMethod : testMethods) { - methodLocMap.put(testMethod.getNode().getLoc().getLine(), testMethod); - } - List modifierList = node.findDescendantsOfType(ASTModifierNode.class); - final Map modifierLocMap = new HashMap<>(); - for (ASTModifierNode modifier : modifierList) { - for (final ModifierOrAnnotationTypeInfo modifierOrAnnotationTypeInfo : modifier.getNode().getModifiers().all()) { - ModifierOrAnnotation modifierOrAnnotation = modifier.getNode().getModifiers().get(modifierOrAnnotationTypeInfo); - if (modifierOrAnnotation instanceof Annotation && TypeInfoEquivalence - .isEquivalent(modifierOrAnnotationTypeInfo, AnnotationTypeInfos.IS_TEST)) { - modifierLocMap.put(modifierOrAnnotation.getLoc().getLine(), modifierOrAnnotation); - } - } - } - for (Map.Entry entry : methodLocMap.entrySet()) { - if (entry != null && modifierLocMap.get(entry.getKey()) == null - && modifierLocMap.get(entry.getKey() - 1) == null) { + List methodCallList = testMethod.findDescendantsOfType(ASTMethodCallExpression.class); + for (ASTMethodCallExpression assertMethodCall : methodCallList) { + if (ASSERT_METHODS.contains(assertMethodCall.getFullMethodName().toLowerCase(Locale.ROOT))) { addViolationWithMessage(data, node, - "''{0}'' method should have @isTest annotation.", - new Object[] { entry.getValue().getImage() }); + "''{0}'' method should have @IsTest annotation.", + new Object[] { testMethod.getImage() }); + return data; } } return data; diff --git a/pmd-apex/src/main/resources/category/apex/bestpractices.xml b/pmd-apex/src/main/resources/category/apex/bestpractices.xml index 55a77e5189..d5b6606913 100644 --- a/pmd-apex/src/main/resources/category/apex/bestpractices.xml +++ b/pmd-apex/src/main/resources/category/apex/bestpractices.xml @@ -109,11 +109,11 @@ trigger Accounts on Account (before insert, before update, before delete, after ]]> - + class="net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule" + externalInfoUrl="${pmd.website.baseurl}/pmd_rules_apex_bestpractices.html#apexassertionsshouldincludemessage"> The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. @@ -154,6 +154,10 @@ private class ATest { static void methodBTest() { } @isTest static void methodCTest() { + System.assert(1==2); + } + @isTest static void methodCTest() { + System.debug('I am a debug statement'); } private void fetchData() { } diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index c49d32854a..96230cbc5c 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -233,15 +233,6 @@ - - 3 - - - - - - - 3 diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageTest.java similarity index 76% rename from pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java rename to pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageTest.java index 1ceb9c97df..8b9464e9e9 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageTest.java @@ -6,6 +6,6 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -public class ApexUnitTestAssertStatementTest extends PmdRuleTst { +public class ApexAssertionsShouldIncludeMessageTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml similarity index 100% rename from pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestAssertStatement.xml rename to pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml index a0ef640db7..4a1861280f 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml @@ -6,7 +6,8 @@ Problematic apex unit test methods - test methods should have @isTest annotation. - 1 + 2 + 6,18 - + \ No newline at end of file From 7e44f025e4ad98c81c37e21f2462eca0b6eab327 Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 23 Mar 2019 15:23:31 -0700 Subject: [PATCH 54/99] removed spaces --- .../bestpractices/ApexAssertionsShouldIncludeMessageRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java index 8aced97aca..3f0031dd35 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java @@ -27,7 +27,7 @@ public class ApexAssertionsShouldIncludeMessageRule extends AbstractApexUnitTest static { ASSERT_METHODS.add(ASSERT.toLowerCase(Locale.ROOT)); ASSERT_METHODS.add(ASSERT_EQUALS.toLowerCase(Locale.ROOT)); - ASSERT_METHODS.add(ASSERT_NOT_EQUALS.toLowerCase(Locale.ROOT) ); + ASSERT_METHODS.add(ASSERT_NOT_EQUALS.toLowerCase(Locale.ROOT)); } public ApexAssertionsShouldIncludeMessageRule() { From a0eabd34b0ce4a86a6b2f30a197d9695a06c1f59 Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 23 Mar 2019 16:16:32 -0700 Subject: [PATCH 55/99] merge conflicts --- .../main/resources/rulesets/apex/ruleset.xml | 496 ++---------------- 1 file changed, 47 insertions(+), 449 deletions(-) diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index 96230cbc5c..821fb07339 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -2,452 +2,50 @@ Default ruleset used by the Code Climate Engine for Salesforce.com Apex - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - - - - 3 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 72cbd2b63bdd7df56f9d70b622128869c5e5e376 Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sat, 23 Mar 2019 16:25:40 -0700 Subject: [PATCH 56/99] merge conflicts --- pmd-apex/src/main/resources/rulesets/apex/ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index 821fb07339..00b1054ad8 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -48,4 +48,4 @@ - \ No newline at end of file + From d1a9630ee20fd2d89e551f4972decc4ef6489ef8 Mon Sep 17 00:00:00 2001 From: sudhansu Date: Sun, 24 Mar 2019 21:01:24 -0700 Subject: [PATCH 57/99] review feedback --- ...pexAssertionsShouldIncludeMessageRule.java | 49 ++++--------------- ...tMethodShouldHaveIsTestAnnotationRule.java | 30 +++--------- .../ApexAssertionsShouldIncludeMessage.xml | 15 +++++- ...itTestMethodShouldHaveIsTestAnnotation.xml | 11 +++++ 4 files changed, 42 insertions(+), 63 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java index 3f0031dd35..03be1465a8 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java @@ -4,65 +4,36 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; -import java.util.HashSet; import java.util.Locale; -import java.util.Set; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; -import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; -/** - * Apex unit tests should have System.assert methods in them - * - * @author sudhansu - */ public class ApexAssertionsShouldIncludeMessageRule extends AbstractApexUnitTestRule { - private static final Set ASSERT_METHODS = new HashSet<>(); private static final String ASSERT = "System.assert"; private static final String ASSERT_EQUALS = "System.assertEquals"; private static final String ASSERT_NOT_EQUALS = "System.assertNotEquals"; - static { - ASSERT_METHODS.add(ASSERT.toLowerCase(Locale.ROOT)); - ASSERT_METHODS.add(ASSERT_EQUALS.toLowerCase(Locale.ROOT)); - ASSERT_METHODS.add(ASSERT_NOT_EQUALS.toLowerCase(Locale.ROOT)); - } - - public ApexAssertionsShouldIncludeMessageRule() { - addRuleChainVisit(ASTMethodCallExpression.class); - } - @Override public Object visit(ASTMethodCallExpression node, Object data) { - if (!ASSERT_METHODS.contains(node.getFullMethodName().toLowerCase(Locale.ROOT))) { + String methodName = node.getFullMethodName().toLowerCase(Locale.ROOT); + if (!ASSERT.equalsIgnoreCase(methodName) + && !ASSERT_EQUALS.equalsIgnoreCase(methodName) + && !ASSERT_NOT_EQUALS.equalsIgnoreCase(methodName)) { return data; } - - return checkForAssertStatement(node, data); - } - - protected Object checkForAssertStatement(ApexNode node, Object data) { - // if System.assert has 1 argument, throw error - // if System.assertEquals/System.assertNotEquals has only 2 arguments, throw error - ASTMethodCallExpression assertMethodCall = (ASTMethodCallExpression) node; - if (assertMethodCall == null) { - return data; - } - if (ASSERT.equalsIgnoreCase(assertMethodCall.getFullMethodName()) - && assertMethodCall.jjtGetNumChildren() == 2) { + if (ASSERT.equalsIgnoreCase(methodName) + && node.jjtGetNumChildren() == 2) { addViolationWithMessage(data, node, "''{0}'' should have 2 parameters.", new Object[] { ASSERT }); - } else if ((ASSERT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName()) - || ASSERT_NOT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName())) - && assertMethodCall.jjtGetNumChildren() == 3) { - Object obj = ASSERT_EQUALS.equalsIgnoreCase(assertMethodCall.getFullMethodName()) - ? ASSERT_EQUALS : ASSERT_NOT_EQUALS; + } else if ((ASSERT_EQUALS.equalsIgnoreCase(methodName) + || ASSERT_NOT_EQUALS.equalsIgnoreCase(methodName)) + && node.jjtGetNumChildren() == 3) { addViolationWithMessage(data, node, "''{0}'' should have 3 parameters.", - new Object[] { obj }); + new Object[] { methodName }); } return data; } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java index 973ded14d5..843d001696 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java @@ -4,50 +4,36 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; -import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Set; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; -import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractApexUnitTestRule { - private static final Set ASSERT_METHODS = new HashSet<>(); private static final String ASSERT = "system.assert"; private static final String ASSERT_EQUALS = "system.assertequals"; private static final String ASSERT_NOT_EQUALS = "system.assertnotequals"; - static { - ASSERT_METHODS.add(ASSERT); - ASSERT_METHODS.add(ASSERT_EQUALS); - ASSERT_METHODS.add(ASSERT_NOT_EQUALS); - } - - public ApexUnitTestMethodShouldHaveIsTestAnnotationRule() { - addRuleChainVisit(ASTMethod.class); - } - @Override public Object visit(final ASTMethod node, final Object data) { // test methods should have @isTest annotation. if (isTestMethodOrClass(node)) { return data; } - return checkForIsTestAnnotation(node, data); + return checkForAssertStatements(node, data); } - private Object checkForIsTestAnnotation(final ApexNode node, final Object data) { - ASTMethod testMethod = (ASTMethod) node; - if (testMethod == null) { - return data; - } + private Object checkForAssertStatements(final ASTMethod testMethod, final Object data) { List methodCallList = testMethod.findDescendantsOfType(ASTMethodCallExpression.class); + String assertMethodName; for (ASTMethodCallExpression assertMethodCall : methodCallList) { - if (ASSERT_METHODS.contains(assertMethodCall.getFullMethodName().toLowerCase(Locale.ROOT))) { - addViolationWithMessage(data, node, + assertMethodName = assertMethodCall.getFullMethodName().toLowerCase(Locale.ROOT); + if (ASSERT.equalsIgnoreCase(assertMethodName) + || ASSERT_EQUALS.equalsIgnoreCase(assertMethodName) + || ASSERT_NOT_EQUALS.equalsIgnoreCase(assertMethodName)) { + addViolationWithMessage(data, testMethod, "''{0}'' method should have @IsTest annotation.", new Object[] { testMethod.getImage() }); return data; diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml index dba55d1863..9c1d0ec390 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexAssertionsShouldIncludeMessage.xml @@ -21,18 +21,29 @@ public class Foo { } ]]> - [apex] assert should have 2 param and assertEquals should have 3 param. 0 + + + [apex] Avoid false positive in non test classes. + 0 + diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml index 4a1861280f..4c804775d9 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/bestpractices/xml/ApexUnitTestMethodShouldHaveIsTestAnnotation.xml @@ -56,6 +56,17 @@ private class ATest { } private void fetchData() { } +} + ]]> + + + Avoid false positive in non test class methods. + 0 + From b4ce59abcd3131e9d848fe5e03040a53eea4995f Mon Sep 17 00:00:00 2001 From: Itai Gilo Date: Mon, 25 Mar 2019 20:26:32 +0200 Subject: [PATCH 58/99] Add escaping to documentation of CommentDefaultAccessModifier --- docs/pages/pmd/rules/java/codestyle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index 6936314df0..45e9c7f000 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -475,7 +475,7 @@ public class Éléphant {} To avoid mistakes if we want that a Method, Constructor, Field or Nested class have a default access modifier we must add a comment at the beginning of it's declaration. -By default the comment must be /* default */ or /* package */, if you want another, you have to provide a regular expression. +By default the comment must be `/* default */` or `/* package */`, if you want another, you have to provide a regular expression. This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the property "ignoredAnnotations" to customize the recognized annotations. From db3b211d8faa2cca2aee8c4007685d42bb544b05 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 25 Mar 2019 19:50:32 +0100 Subject: [PATCH 59/99] Undo changes to rulesets/apex/ruleset.xml --- .../main/resources/rulesets/apex/ruleset.xml | 487 ++++++++++++++++-- 1 file changed, 440 insertions(+), 47 deletions(-) diff --git a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml index 00b1054ad8..25a94a61ca 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/ruleset.xml @@ -2,50 +2,443 @@ Default ruleset used by the Code Climate Engine for Salesforce.com Apex - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + + + + 3 + + + + + + + + \ No newline at end of file From 2958f83517865f2dff2c16808c87d240c3f2acc3 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 25 Mar 2019 19:56:47 +0100 Subject: [PATCH 60/99] Simplify the rules even more --- .../ApexAssertionsShouldIncludeMessageRule.java | 13 +++---------- ...TestMethodShouldHaveIsTestAnnotationRule.java | 16 ++++++++++------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java index 03be1465a8..10c8424826 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; -import java.util.Locale; - import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; @@ -17,14 +15,9 @@ public class ApexAssertionsShouldIncludeMessageRule extends AbstractApexUnitTest @Override public Object visit(ASTMethodCallExpression node, Object data) { - String methodName = node.getFullMethodName().toLowerCase(Locale.ROOT); - if (!ASSERT.equalsIgnoreCase(methodName) - && !ASSERT_EQUALS.equalsIgnoreCase(methodName) - && !ASSERT_NOT_EQUALS.equalsIgnoreCase(methodName)) { - return data; - } - if (ASSERT.equalsIgnoreCase(methodName) - && node.jjtGetNumChildren() == 2) { + String methodName = node.getFullMethodName(); + + if (ASSERT.equalsIgnoreCase(methodName) && node.jjtGetNumChildren() == 2) { addViolationWithMessage(data, node, "''{0}'' should have 2 parameters.", new Object[] { ASSERT }); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java index 843d001696..66185f9a3d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotationRule.java @@ -4,17 +4,23 @@ package net.sourceforge.pmd.lang.apex.rule.bestpractices; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; import net.sourceforge.pmd.lang.apex.rule.AbstractApexUnitTestRule; public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractApexUnitTestRule { - private static final String ASSERT = "system.assert"; - private static final String ASSERT_EQUALS = "system.assertequals"; - private static final String ASSERT_NOT_EQUALS = "system.assertnotequals"; + private static final Set ASSERT_METHODS = new HashSet<>(); + + static { + ASSERT_METHODS.add("system.assert"); + ASSERT_METHODS.add("system.assertequals"); + ASSERT_METHODS.add("system.assertnotequals"); + } @Override public Object visit(final ASTMethod node, final Object data) { @@ -30,9 +36,7 @@ public class ApexUnitTestMethodShouldHaveIsTestAnnotationRule extends AbstractAp String assertMethodName; for (ASTMethodCallExpression assertMethodCall : methodCallList) { assertMethodName = assertMethodCall.getFullMethodName().toLowerCase(Locale.ROOT); - if (ASSERT.equalsIgnoreCase(assertMethodName) - || ASSERT_EQUALS.equalsIgnoreCase(assertMethodName) - || ASSERT_NOT_EQUALS.equalsIgnoreCase(assertMethodName)) { + if (ASSERT_METHODS.contains(assertMethodName)) { addViolationWithMessage(data, testMethod, "''{0}'' method should have @IsTest annotation.", new Object[] { testMethod.getImage() }); From 53d123703b0757602f7f7a16e160e2eaa30cb2ad Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 25 Mar 2019 20:04:19 +0100 Subject: [PATCH 61/99] Update release notes, refs #1694 --- docs/pages/release_notes.md | 7 ++ .../resources/category/apex/bestpractices.xml | 115 +++++++++--------- .../main/resources/rulesets/releases/6130.xml | 15 +++ 3 files changed, 81 insertions(+), 56 deletions(-) create mode 100644 pmd-core/src/main/resources/rulesets/releases/6130.xml diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 2a49668a30..eb6602df54 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -52,6 +52,12 @@ More information is available in [the user documentation](pmd_userdocs_cpd.html# for try-blocks, that could be changed to a try-with-resources statement. This statement ensures that each resource is closed at the end of the statement and is available since Java 7. +* The new Apex rule {% rule "apex/bestpractices/ApexAssertionsShouldIncludeMessage" %} (`apex-bestpractices`) + searches for assertions in unit tests and checks, whether they use a message argument. + +* The new Apex rule {% rule "apex/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotation" %} (`apex-bestpractices`) + searches for methods in test classes, which are missing the `@IsTest` annotation. + #### Modified Rules * The Apex rule {% rule "apex/codestyle/MethodNamingConventions" %} (apex-codestyle) has a new @@ -106,6 +112,7 @@ More information is available in [the user documentation](pmd_userdocs_cpd.html# * [#1654](https://github.com/pmd/pmd/pull/1654): \[core] Antlr token filter - [Tomi De Lucca](https://github.com/tomidelucca) * [#1655](https://github.com/pmd/pmd/pull/1655): \[kotlin] Kotlin tokenizer refactor - [Lucas Soncini](https://github.com/lsoncini) * [#1686](https://github.com/pmd/pmd/pull/1686): \[doc] Replaced wrong escaping with ">" - [Himanshu Pandey](https://github.com/hpandeycodeit) +* [#1694](https://github.com/pmd/pmd/pull/1694): \[apex] New rules for test method and assert statements - [triandicAnt](https://github.com/triandicAnt) {% endtocmaker %} diff --git a/pmd-apex/src/main/resources/category/apex/bestpractices.xml b/pmd-apex/src/main/resources/category/apex/bestpractices.xml index d5b6606913..404502d662 100644 --- a/pmd-apex/src/main/resources/category/apex/bestpractices.xml +++ b/pmd-apex/src/main/resources/category/apex/bestpractices.xml @@ -9,6 +9,33 @@ Rules which enforce generally accepted best practices. + + +The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. +Having a second/third parameter provides more information and makes it easier to debug the test failure and +improves the readability of test output. + + 3 + + + + + + + +Apex test methods should have @isTest annotation. +As testMethod keyword is deprecated, Salesforce advices to use @isTest annotation for test class/methods. + + 3 + + + + + - - - - - The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. - Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. - - 3 - - - - - - - Apex test methods should have @isTest annotation. - As testMethod keyword is deprecated, Salesforce advices to use @isTest annotation for test class/methods. - - 3 - - diff --git a/pmd-core/src/main/resources/rulesets/releases/6130.xml b/pmd-core/src/main/resources/rulesets/releases/6130.xml new file mode 100644 index 0000000000..0dbbfb1f5e --- /dev/null +++ b/pmd-core/src/main/resources/rulesets/releases/6130.xml @@ -0,0 +1,15 @@ + + + + +This ruleset contains links to rules that are new in PMD v6.13.0 + + + + + + + From 895ee7bc9f9443c95eda5e327f8dd74544c3257b Mon Sep 17 00:00:00 2001 From: "Travis CI (pmd-bot)" Date: Mon, 25 Mar 2019 19:29:53 +0000 Subject: [PATCH 62/99] Update documentation TRAVIS_JOB_NUMBER=3569.1 TRAVIS_COMMIT_RANGE=3a866ddb9fc6...17ab453db976 --- docs/pages/pmd/rules/apex.md | 3 ++- docs/pages/pmd/rules/apex/bestpractices.md | 31 +++++++++++++--------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/pages/pmd/rules/apex.md b/docs/pages/pmd/rules/apex.md index 5390a956a8..dec0347f36 100644 --- a/docs/pages/pmd/rules/apex.md +++ b/docs/pages/pmd/rules/apex.md @@ -11,8 +11,9 @@ folder: pmd/rules {% include callout.html content="Rules which enforce generally accepted best practices." %} +* [ApexAssertionsShouldIncludeMessage](pmd_rules_apex_bestpractices.html#apexassertionsshouldincludemessage): The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEqua... * [ApexUnitTestClassShouldHaveAsserts](pmd_rules_apex_bestpractices.html#apexunittestclassshouldhaveasserts): Apex unit tests should include at least one assertion. This makes the tests more robust, and usi... -* [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation): Apex test methods should have @isTest annotation. As testMethod keyword is deprecated,... +* [ApexUnitTestMethodShouldHaveIsTestAnnotation](pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation): Apex test methods should have @isTest annotation.As testMethod keyword is deprecated, Salesforce ... * [ApexUnitTestShouldNotUseSeeAllDataTrue](pmd_rules_apex_bestpractices.html#apexunittestshouldnotuseseealldatatrue): Apex unit tests should not use @isTest(seeAllData=true) because it opens up the existing database... * [AvoidGlobalModifier](pmd_rules_apex_bestpractices.html#avoidglobalmodifier): Global classes should be avoided (especially in managed packages) as they can never be deleted or... * [AvoidLogicInTrigger](pmd_rules_apex_bestpractices.html#avoidlogicintrigger): As triggers do not allow methods like regular classes they are less flexible and suited to apply ... diff --git a/docs/pages/pmd/rules/apex/bestpractices.md b/docs/pages/pmd/rules/apex/bestpractices.md index 4978698a37..4acf3f478d 100644 --- a/docs/pages/pmd/rules/apex/bestpractices.md +++ b/docs/pages/pmd/rules/apex/bestpractices.md @@ -5,20 +5,21 @@ permalink: pmd_rules_apex_bestpractices.html folder: pmd/rules/apex sidebaractiveurl: /pmd_rules_apex.html editmepath: ../pmd-apex/src/main/resources/category/apex/bestpractices.xml -keywords: Best Practices, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestShouldNotUseSeeAllDataTrue, AvoidGlobalModifier, AvoidLogicInTrigger, ApexUnitTestAssertStatement, ApexUnitTestMethodShouldHaveIsTestAnnotation +keywords: Best Practices, ApexAssertionsShouldIncludeMessage, ApexUnitTestClassShouldHaveAsserts, ApexUnitTestMethodShouldHaveIsTestAnnotation, ApexUnitTestShouldNotUseSeeAllDataTrue, AvoidGlobalModifier, AvoidLogicInTrigger language: Apex --- -## ApexUnitTestAssertStatement +## ApexAssertionsShouldIncludeMessage **Since:** PMD 6.13.0 **Priority:** Medium (3) The second parameter of System.assert/third parameter of System.assertEquals/System.assertNotEquals is a message. -Having a second/third parameter provides more information and makes it easier to debug the test failure and improves the readability of test output. +Having a second/third parameter provides more information and makes it easier to debug the test failure and +improves the readability of test output. -**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexUnitTestAssertStatementRule.java) +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.apex.rule.bestpractices.ApexAssertionsShouldIncludeMessageRule](https://github.com/pmd/pmd/blob/master/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/bestpractices/ApexAssertionsShouldIncludeMessageRule.java) **Example(s):** @@ -39,13 +40,13 @@ public class Foo { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| -|cc\_block\_highlighting|false|Code Climate Block Highlighting|no| +|cc\_categories|Bug Risk|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml - + ``` ## ApexUnitTestClassShouldHaveAsserts @@ -108,6 +109,10 @@ private class ATest { static void methodBTest() { } @isTest static void methodCTest() { + System.assert(1==2); + } + @isTest static void methodCTest() { + System.debug('I am a debug statement'); } private void fetchData() { } @@ -118,11 +123,11 @@ private class ATest { |Name|Default Value|Description|Multivalued| |----|-------------|-----------|-----------| -|cc\_categories|Style|Code Climate Categories|yes. Delimiter is '\|'.| -|cc\_remediation\_points\_multiplier|1|Code Climate Remediation Points multiplier|no| -|cc\_block\_highlighting|false|Code Climate Block Highlighting|no| +|cc\_categories|Bug Risk|Deprecated Code Climate Categories|yes. Delimiter is '\|'.| +|cc\_remediation\_points\_multiplier|100|Deprecated Code Climate Remediation Points multiplier|no| +|cc\_block\_highlighting|false|Deprecated Code Climate Block Highlighting|no| -**Use this rule by referencing it:** +**Use this rule with the default properties by just referencing it:** ``` xml ``` From 6df4100ca8de0c9c1dea2f359bd2eb9e10aee592 Mon Sep 17 00:00:00 2001 From: Itai Gilo Date: Mon, 25 Mar 2019 21:31:08 +0200 Subject: [PATCH 63/99] Revert changes to auto-generated file --- docs/pages/pmd/rules/java/codestyle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index 45e9c7f000..6936314df0 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -475,7 +475,7 @@ public class Éléphant {} To avoid mistakes if we want that a Method, Constructor, Field or Nested class have a default access modifier we must add a comment at the beginning of it's declaration. -By default the comment must be `/* default */` or `/* package */`, if you want another, you have to provide a regular expression. +By default the comment must be /* default */ or /* package */, if you want another, you have to provide a regular expression. This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the property "ignoredAnnotations" to customize the recognized annotations. From e7f7422f50733fdfb89cb69b1e7167b9f9b4cc7f Mon Sep 17 00:00:00 2001 From: Itai Gilo Date: Mon, 25 Mar 2019 21:32:35 +0200 Subject: [PATCH 64/99] Update the right file --- pmd-java/src/main/resources/category/java/codestyle.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml index d2a60ffa5b..a7a89bf795 100644 --- a/pmd-java/src/main/resources/category/java/codestyle.xml +++ b/pmd-java/src/main/resources/category/java/codestyle.xml @@ -404,7 +404,7 @@ public class Éléphant {} To avoid mistakes if we want that a Method, Constructor, Field or Nested class have a default access modifier we must add a comment at the beginning of it's declaration. -By default the comment must be /* default */ or /* package */, if you want another, you have to provide a regular expression. +By default the comment must be `/* default */` or `/* package */`, if you want another, you have to provide a regular expression. This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the property "ignoredAnnotations" to customize the recognized annotations. From 3a22449b868fb17efec7fd0898144cfc69147206 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Tue, 26 Mar 2019 18:21:52 +0100 Subject: [PATCH 65/99] Update release notes, fixes #1674, refs #1737 --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8aedaffbaf..2f36c13979 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -53,6 +53,8 @@ The designer will still be shipped with PMD's binaries. * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods +* java-codestyle + * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong ### API Changes @@ -74,6 +76,7 @@ The designer will still be shipped with PMD's binaries. * [#1709](https://github.com/pmd/pmd/pull/1709): \[java] Detect while loops with literal booleans conditions - [David Burström](https://github.com/davidburstromspotify) * [#1717](https://github.com/pmd/pmd/pull/1717): \[java] Fix false positive in useTryWithResources when using a custom close method with multiple arguments - [Rishabh Jain](https://github.com/jainrish) * [#1724](https://github.com/pmd/pmd/pull/1724): \[doc] Correct property override example - [Felix W. Dekker](https://github.com/FWDekker) +* [#1737](https://github.com/pmd/pmd/pull/1737): \[java] fix escaping of CommentDefaultAccessModifier documentation - [itaigilo](https://github.com/itaigilo) {% endtocmaker %} From f6549d6c0bbc896d9a27838dcc6eac0c5b97ce89 Mon Sep 17 00:00:00 2001 From: "Travis CI (pmd-bot)" Date: Tue, 26 Mar 2019 17:44:50 +0000 Subject: [PATCH 66/99] Update documentation TRAVIS_JOB_NUMBER=3572.1 TRAVIS_COMMIT_RANGE=895ee7bc9f94...d5186afc527d --- docs/pages/pmd/rules/java/codestyle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index 6936314df0..45e9c7f000 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -475,7 +475,7 @@ public class Éléphant {} To avoid mistakes if we want that a Method, Constructor, Field or Nested class have a default access modifier we must add a comment at the beginning of it's declaration. -By default the comment must be /* default */ or /* package */, if you want another, you have to provide a regular expression. +By default the comment must be `/* default */` or `/* package */`, if you want another, you have to provide a regular expression. This rule ignores by default all cases that have a @VisibleForTesting annotation. Use the property "ignoredAnnotations" to customize the recognized annotations. From ca6ad5fd22e484cebdf5c652155247a4961eabbf Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Mar 2019 16:51:08 +0100 Subject: [PATCH 67/99] [pslql] ParseException when parsing ELSIF Fixes #1731 --- docs/pages/release_notes.md | 2 ++ pmd-plsql/etc/grammar/PldocAST.jjt | 6 ++---- .../pmd/lang/plsql/ast/IfStatementTest.java | 20 +++++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/IfStatementTest.java diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8c9f42def8..a33c3a95b6 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -61,6 +61,8 @@ The designer will still be shipped with PMD's binaries. * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods * java-codestyle * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong +* plsql + * [#1731](https://github.com/pmd/pmd/issues/1731): \[pslql] ParseException when parsing ELSIF ### API Changes diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 87715b4055..0f1cedfa1e 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -2085,7 +2085,7 @@ ASTElseClause ElseClause() : ASTElsifClause ElsifClause() : {} { - Expression() (Statement())+ + Expression() (LOOKAHEAD(1, {!(getToken(1).kind == ELSIF)}) Statement())+ { return jjtThis ; } } @@ -2280,7 +2280,7 @@ ASTWhileStatement WhileStatement() : ASTIfStatement IfStatement() : {} { - Expression() (Statement())+ + Expression() (LOOKAHEAD(1, {!(getToken(1).kind == ELSIF)}) Statement())+ ( ElsifClause() {jjtThis.setHasElse();} )* [ ElseClause() {jjtThis.setHasElse();} ] @@ -6095,7 +6095,6 @@ ASTID ID(): {} //| //RESERVED WORD | | //RESERVED WORD - //| //SYNTAX //RESERVED WORD | //SYNTAX //| | @@ -6339,7 +6338,6 @@ ASTQualifiedID QualifiedID(): {} // | // - // | // // diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/IfStatementTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/IfStatementTest.java new file mode 100644 index 0000000000..b5422b6a04 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/IfStatementTest.java @@ -0,0 +1,20 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; + +public class IfStatementTest extends AbstractPLSQLParserTst { + + @Test + public void parseIfWithElseIf() throws Exception { + String code = "BEGIN\nIF 1 = 1 THEN null;\nELSIF (2 = 2) THEN null;\nELSE null;\nEND IF;\nEND;\n/\n"; + ASTInput input = parsePLSQL(code); + Assert.assertNotNull(input); + } +} From 1d0143582093e2d1e0e728a5df3e8cecf93103ad Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Mar 2019 17:21:51 +0100 Subject: [PATCH 68/99] [plsql] % not supported in "TestSearch%notfound" Fixes #1733 --- docs/pages/release_notes.md | 1 + pmd-plsql/etc/grammar/PldocAST.jjt | 8 +++++ .../lang/plsql/ast/CursorAttributesTest.java | 22 +++++++++++++ .../pmd/lang/plsql/ast/CursorAttributes.pls | 32 +++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorAttributesTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorAttributes.pls diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index a33c3a95b6..de5259d49b 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -63,6 +63,7 @@ The designer will still be shipped with PMD's binaries. * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong * plsql * [#1731](https://github.com/pmd/pmd/issues/1731): \[pslql] ParseException when parsing ELSIF + * [#1733](https://github.com/pmd/pmd/issues/1733): \[plsql] % not supported in "TestSearch%notfound" ### API Changes diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 0f1cedfa1e..89875ee8df 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1508,6 +1508,14 @@ ASTSimpleExpression SimpleExpression() : LOOKAHEAD(4) TableName() { sb.append(token.image); } "." { sb.append(token.image); } Column() { sb.append(token.image); } + | + // Named Cursor: https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/named-cursor-attribute.html#GUID-CD8D8415-FF19-4D81-99BA-7825FD40CC96 + LOOKAHEAD(3) + Column() { sb.append(token.image); } "%" ( LOOKAHEAD({getToken(1).image.equalsIgnoreCase("isopen")}) KEYWORD("ISOPEN") + | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("found")}) KEYWORD("FOUND") + | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("notfound")}) KEYWORD("NOTFOUND") + | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("rowcount")}) KEYWORD("ROWCOUNT") + ) { sb.append('%').append(token.image); } | LOOKAHEAD(2) Column() { sb.append(token.image); } diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorAttributesTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorAttributesTest.java new file mode 100644 index 0000000000..4e4dc6ea60 --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/CursorAttributesTest.java @@ -0,0 +1,22 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; + +public class CursorAttributesTest extends AbstractPLSQLParserTst { + + @Test + public void parseCursorWithAttribute() { + String code = loadTestResource("CursorAttributes.pls"); + ASTInput input = parsePLSQL(code); + ASTExpression exp = input.getFirstDescendantOfType(ASTIfStatement.class).getFirstChildOfType(ASTExpression.class); + Assert.assertEquals("TestSearch%notfound", exp.getImage()); + } + +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorAttributes.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorAttributes.pls new file mode 100644 index 0000000000..79dec6cdca --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CursorAttributes.pls @@ -0,0 +1,32 @@ +CREATE OR REPLACE PACKAGE lpe_test is + +procedure testif; + +end lpe_test; +/ + +CREATE OR REPLACE PACKAGE BODY lpe_test is + + +procedure testif +is +cursor TestSearch +is +select 1 from dual; + +TestRow TestSearch%rowtype; + +begin + open TestSearch; + fetch TestSearch into TestRow; + + if TestSearch%notfound then + DBMS_OUTPUT.PUT_LINE('Not found'); + else + DBMS_OUTPUT.PUT_LINE('Found'); + end if; + close TestSearch; +end testif; + +end lpe_test; +/ \ No newline at end of file From 680b164e105c101c491a7d88d544e63f3234f9d0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Mar 2019 20:06:44 +0100 Subject: [PATCH 69/99] [apex] Refactor rules to use new nodes attributes Also unifying getType() on ASTField, ASTProperty, ASTVariableDeclaration, ASTParameter Adding remaining types in ASTLiteralExpression --- .../pmd/lang/apex/ast/ASTField.java | 16 ++++++---- .../lang/apex/ast/ASTLiteralExpression.java | 32 +++++++++++++++++-- .../pmd/lang/apex/ast/ASTParameter.java | 4 +++ .../pmd/lang/apex/ast/ASTProperty.java | 7 ++-- .../lang/apex/ast/ASTVariableDeclaration.java | 12 +++++-- .../lang/apex/metrics/impl/CycloMetric.java | 2 +- .../security/ApexDangerousMethodsRule.java | 4 +-- .../rule/security/ApexOpenRedirectRule.java | 16 ++-------- .../rule/security/ApexSOQLInjectionRule.java | 25 ++++++--------- .../security/ApexSharingViolationsRule.java | 20 ++---------- .../ApexSuggestUsingNamedCredRule.java | 13 +++----- .../security/ApexXSSFromEscapeFalseRule.java | 7 ++-- .../security/ApexXSSFromURLParamRule.java | 4 +-- .../pmd/lang/apex/rule/security/Helper.java | 7 ++++ .../pmd/lang/apex/ast/ASTFieldTest.java | 21 ++++++++++-- 15 files changed, 106 insertions(+), 84 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java index c486c1eef0..fdc0feb161 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTField.java @@ -21,10 +21,7 @@ public class ASTField extends AbstractApexNode implements CanSuppressWarn @Override public String getImage() { - if (node.getFieldInfo() != null) { - return node.getFieldInfo().getName(); - } - return null; + return node.getFieldInfo().getName(); } @Override @@ -39,11 +36,18 @@ public class ASTField extends AbstractApexNode implements CanSuppressWarn return false; } - public String getTypeRef() { - return String.valueOf(node.getTypeRef()); + public String getType() { + return node.getFieldInfo().getType().getApexName(); } public ASTModifierNode getModifiers() { return getFirstChildOfType(ASTModifierNode.class); } + + public String getValue() { + if (node.getFieldInfo().getValue() != null) { + return String.valueOf(node.getFieldInfo().getValue()); + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java index 09fa3621b7..ab76f960f0 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java @@ -20,17 +20,43 @@ public class ASTLiteralExpression extends AbstractApexNode { return visitor.visit(this, data); } - public LiteralType getLiteralType() { return node.getLiteralType(); } public boolean isString() { - return getLiteralType() == LiteralType.STRING; + return node.getLiteralType() == LiteralType.STRING; + } + + public boolean isBoolean() { + return node.getLiteralType() == LiteralType.TRUE || node.getLiteralType() == LiteralType.FALSE; + } + + public boolean isInteger() { + return node.getLiteralType() == LiteralType.INTEGER; + } + + public boolean isDouble() { + return node.getLiteralType() == LiteralType.DOUBLE; + } + + public boolean isLong() { + return node.getLiteralType() == LiteralType.LONG; + } + + public boolean isDecimal() { + return node.getLiteralType() == LiteralType.DECIMAL; + } + + public boolean isNull() { + return node.getLiteralType() == LiteralType.NULL; } @Override public String getImage() { - return String.valueOf(node.getLiteral()); + if (node.getLiteral() != null) { + return String.valueOf(node.getLiteral()); + } + return null; } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java index a58bd25fb3..22c1924e65 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTParameter.java @@ -39,4 +39,8 @@ public class ASTParameter extends AbstractApexNode implements CanSupp public ASTModifierNode getModifiers() { return getFirstChildOfType(ASTModifierNode.class); } + + public String getType() { + return node.getType().getApexName(); + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java index 12fb1d3e39..f73ac2c761 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTProperty.java @@ -17,11 +17,8 @@ public class ASTProperty extends AbstractApexNode { return visitor.visit(this, data); } - public String getTypeName() { - if (node.getFieldInfo() != null) { - return node.getFieldInfo().getType().getApexName(); - } - return null; + public String getType() { + return node.getFieldInfo().getType().getApexName(); } public ASTModifierNode getModifiers() { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java index 361305e251..fb22c425ba 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTVariableDeclaration.java @@ -21,7 +21,10 @@ public class ASTVariableDeclaration extends AbstractApexNode fields = node.findDescendantsOfType(ASTField.class); for (ASTField field : fields) { - if (BOOLEAN.equalsIgnoreCase(field.getTypeRef())) { + if (BOOLEAN.equalsIgnoreCase(field.getType())) { whiteListedVariables.add(Helper.getFQVariableName(field)); } @@ -81,7 +81,7 @@ public class ApexDangerousMethodsRule extends AbstractApexRule { List declarations = node.findDescendantsOfType(ASTVariableDeclaration.class); for (ASTVariableDeclaration decl : declarations) { - if (BOOLEAN.equalsIgnoreCase(decl.getTypeName())) { + if (BOOLEAN.equalsIgnoreCase(decl.getType())) { whiteListedVariables.add(Helper.getFQVariableName(decl)); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java index 520ac77068..ea4ac2794d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexOpenRedirectRule.java @@ -21,8 +21,6 @@ import net.sourceforge.pmd.lang.apex.ast.AbstractApexNode; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.semantic.symbol.member.variable.StandardFieldInfo; - /** * Looking for potential Open redirect via PageReference variable input * @@ -100,10 +98,9 @@ public class ApexOpenRedirectRule extends AbstractApexRule { } else { if (node instanceof ASTField) { ASTField field = (ASTField) node; - if ("String".equalsIgnoreCase(field.getTypeRef())) { - StandardFieldInfo fieldInfo = (StandardFieldInfo) field.getNode().getFieldInfo(); - if (fieldInfo.getValue() != null) { - addVariable(fieldInfo); + if ("String".equalsIgnoreCase(field.getType())) { + if (field.getValue() != null) { + listOfStringLiteralVariables.add(Helper.getFQVariableName(field)); } } } @@ -111,13 +108,6 @@ public class ApexOpenRedirectRule extends AbstractApexRule { } - private void addVariable(StandardFieldInfo fieldInfo) { - StringBuilder sb = new StringBuilder().append(fieldInfo.getDefiningType().getApexName()).append(":") - .append(fieldInfo.getName()); - listOfStringLiteralVariables.add(sb.toString()); - - } - private void addVariable(ASTVariableDeclaration node) { ASTVariableExpression variable = node.getFirstChildOfType(ASTVariableExpression.class); addVariable(variable); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java index ced42d6b7e..9824149bf1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSOQLInjectionRule.java @@ -18,6 +18,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTLiteralExpression; import net.sourceforge.pmd.lang.apex.ast.ASTMethod; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; +import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTStandardCondition; import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; @@ -25,9 +26,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTVariableExpression; import net.sourceforge.pmd.lang.apex.ast.AbstractApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.semantic.ast.member.Parameter; -import apex.jorje.semantic.ast.statement.VariableDeclaration; - /** * Detects if variables in Database.query(variable) is escaped with * String.escapeSingleQuotes @@ -107,9 +105,8 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { } private void findSafeVariablesInSignature(ASTMethod m) { - List parameters = m.getNode().getMethodInfo().getParameters(); - for (Parameter p : parameters) { - switch (p.getType().getApexName().toLowerCase(Locale.ROOT)) { + for (ASTParameter p : m.findChildrenOfType(ASTParameter.class)) { + switch (p.getType().toLowerCase(Locale.ROOT)) { case ID: case INTEGER: case BOOLEAN: @@ -134,13 +131,12 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { // look for String a = 'b'; if (literal != null) { if (left != null) { - Object o = literal.getNode().getLiteral(); - if (o instanceof Integer || o instanceof Boolean || o instanceof Double) { + if (literal.isInteger() || literal.isBoolean() || literal.isDouble()) { safeVariables.add(Helper.getFQVariableName(left)); } - if (o instanceof String) { - if (SELECT_PATTERN.matcher((String) o).matches()) { + if (literal.isString()) { + if (SELECT_PATTERN.matcher(literal.getImage()).matches()) { selectContainingVariables.put(Helper.getFQVariableName(left), Boolean.TRUE); } else { safeVariables.add(Helper.getFQVariableName(left)); @@ -159,8 +155,7 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { } if (node instanceof ASTVariableDeclaration) { - VariableDeclaration o = (VariableDeclaration) node.getNode(); - switch (o.getLocalInfo().getType().getApexName().toLowerCase(Locale.ROOT)) { + switch (((ASTVariableDeclaration) node).getType().toLowerCase(Locale.ROOT)) { case INTEGER: case ID: case BOOLEAN: @@ -207,10 +202,8 @@ public class ApexSOQLInjectionRule extends AbstractApexRule { final ASTLiteralExpression literal = node.getFirstChildOfType(ASTLiteralExpression.class); if (literal != null) { - - Object o = literal.getNode().getLiteral(); - if (o instanceof String) { - if (SELECT_PATTERN.matcher((String) o).matches()) { + if (literal.isString()) { + if (SELECT_PATTERN.matcher(literal.getImage()).matches()) { if (!isSafeVariable) { // select literal + other unsafe vars selectContainingVariables.put(Helper.getFQVariableName(var), Boolean.FALSE); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java index 824c80e651..b2de63fc32 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSharingViolationsRule.java @@ -13,9 +13,6 @@ import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; import net.sourceforge.pmd.lang.apex.ast.ApexNode; import net.sourceforge.pmd.lang.apex.rule.AbstractApexRule; -import apex.jorje.semantic.ast.modifier.OldModifiers.ModifierType; -import apex.jorje.semantic.symbol.type.ModifierOrAnnotationTypeInfo; - /** * Finds Apex class that do not define sharing * @@ -98,21 +95,8 @@ public class ApexSharingViolationsRule extends AbstractApexRule { * @param node * @return */ - private boolean isSharingPresent(ApexNode node) { - boolean sharingFound = false; - - for (ModifierOrAnnotationTypeInfo type : node.getNode().getDefiningType().getModifiers().all()) { - if (type.getBytecodeName().equalsIgnoreCase(ModifierType.WithoutSharing.toString())) { - sharingFound = true; - break; - } - if (type.getBytecodeName().equalsIgnoreCase(ModifierType.WithSharing.toString())) { - sharingFound = true; - break; - } - - } - return sharingFound; + private boolean isSharingPresent(ASTUserClass node) { + return node.getModifiers().isWithoutSharing() || node.getModifiers().isWithSharing(); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java index ed17d50002..fdaf43850d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexSuggestUsingNamedCredRule.java @@ -66,12 +66,8 @@ public class ApexSuggestUsingNamedCredRule extends AbstractApexRule { } private void findFieldLiterals(final ASTField fDecl) { - Object f = fDecl.getNode().getFieldInfo().getValue(); - if (f instanceof String) { - final String fieldValue = (String) f; - if (AUTHORIZATION.equalsIgnoreCase(fieldValue)) { - listOfAuthorizationVariables.add(Helper.getFQVariableName(fDecl)); - } + if ("String".equals(fDecl.getType()) && AUTHORIZATION.equalsIgnoreCase(fDecl.getValue())) { + listOfAuthorizationVariables.add(Helper.getFQVariableName(fDecl)); } } @@ -118,9 +114,8 @@ public class ApexSuggestUsingNamedCredRule extends AbstractApexRule { } private boolean isAuthorizationLiteral(final ASTLiteralExpression literal) { - Object o = literal.getNode().getLiteral(); - if (o instanceof String) { - String lit = (String) o; + if (literal.isString()) { + String lit = literal.getImage(); if (lit.equalsIgnoreCase(AUTHORIZATION)) { return true; } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java index e17db570b0..39068a5c45 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromEscapeFalseRule.java @@ -48,10 +48,9 @@ public class ApexXSSFromEscapeFalseRule extends AbstractApexRule { Object potentialLiteral = methodCall.jjtGetChild(2); if (potentialLiteral instanceof ASTLiteralExpression) { ASTLiteralExpression parameter = (ASTLiteralExpression) potentialLiteral; - Object o = parameter.getNode().getLiteral(); - if (o instanceof Boolean) { - Boolean paramValue = (Boolean) o; - if (paramValue.equals(Boolean.FALSE)) { + if (parameter.isBoolean()) { + boolean paramValue = Boolean.parseBoolean(parameter.getImage()); + if (!paramValue) { validateLiteralPresence(methodCall, data); } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java index b1669bbc9d..d061652ee7 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexXSSFromURLParamRule.java @@ -175,7 +175,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { String varType = null; if (node instanceof ASTVariableDeclaration) { - varType = ((ASTVariableDeclaration) node).getTypeName(); + varType = ((ASTVariableDeclaration) node).getType(); } @@ -214,7 +214,7 @@ public class ApexXSSFromURLParamRule extends AbstractApexRule { String varType = null; if (node instanceof ASTVariableDeclaration) { - varType = ((ASTVariableDeclaration) node).getTypeName(); + varType = ((ASTVariableDeclaration) node).getType(); } if (varType == null || !"id".equalsIgnoreCase(varType)) { diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java index fb40bfacf9..a1e37882be 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/Helper.java @@ -19,6 +19,7 @@ import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression; import net.sourceforge.pmd.lang.apex.ast.ASTModifierNode; import net.sourceforge.pmd.lang.apex.ast.ASTNewKeyValueObjectExpression; +import net.sourceforge.pmd.lang.apex.ast.ASTParameter; import net.sourceforge.pmd.lang.apex.ast.ASTReferenceExpression; import net.sourceforge.pmd.lang.apex.ast.ASTSoqlExpression; import net.sourceforge.pmd.lang.apex.ast.ASTSoslExpression; @@ -232,4 +233,10 @@ public final class Helper { return sb.toString(); } + static String getFQVariableName(ASTParameter p) { + StringBuffer sb = new StringBuffer(); + sb.append(p.getNode().getDefiningType()).append(":").append(p.getImage()); + return sb.toString(); + } + } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java index c528176739..f694ac55f1 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldTest.java @@ -15,10 +15,27 @@ public class ASTFieldTest { @Test public void testGetType() { - ApexNode node = parse("public class Foo { private String myField = \"a\"; }"); + ApexNode node = parse("public class Foo { private String myField = 'a'; }"); ASTField field = node.getFirstDescendantOfType(ASTField.class); Assert.assertEquals("myField", field.getImage()); - Assert.assertEquals("String", field.getTypeRef()); + Assert.assertEquals("String", field.getType()); + Assert.assertEquals("a", field.getValue()); + } + + @Test + public void testGetValue() { + ApexNode node = parse("public class Foo { private String myField = 'a'; }"); + ASTField field = node.getFirstDescendantOfType(ASTField.class); + + Assert.assertEquals("a", field.getValue()); + } + + @Test + public void testGetNoValue() { + ApexNode node = parse("public class Foo { private String myField; }"); + ASTField field = node.getFirstDescendantOfType(ASTField.class); + + Assert.assertNull(field.getValue()); } } From 91d0ebf4620b9cda44ce6f02232fe8a003d82efd Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 28 Mar 2019 21:04:49 +0100 Subject: [PATCH 70/99] [apex] Expose parameter names of NewKeyValueObjectExpression --- .../lang/apex/ast/ASTLiteralExpression.java | 35 ++++++++++++++++++ .../ast/ASTNewKeyValueObjectExpression.java | 8 +++++ .../pmd/lang/apex/rule/security/Helper.java | 30 +++++----------- .../ASTNewKeyValueObjectExpressionTest.java | 36 +++++++++++++++++++ 4 files changed, 87 insertions(+), 22 deletions(-) create mode 100644 pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpressionTest.java diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java index ab76f960f0..1ea93d98f1 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTLiteralExpression.java @@ -4,8 +4,13 @@ package net.sourceforge.pmd.lang.apex.ast; +import java.lang.reflect.Field; +import java.util.Optional; + +import apex.jorje.data.Identifier; import apex.jorje.data.ast.LiteralType; import apex.jorje.semantic.ast.expression.LiteralExpression; +import apex.jorje.semantic.ast.expression.NewKeyValueObjectExpression.NameValueParameter; public class ASTLiteralExpression extends AbstractApexNode { @@ -59,4 +64,34 @@ public class ASTLiteralExpression extends AbstractApexNode { } return null; } + + public String getName() { + if (jjtGetParent() instanceof ASTNewKeyValueObjectExpression) { + ASTNewKeyValueObjectExpression parent = (ASTNewKeyValueObjectExpression) jjtGetParent(); + try { + Field exprField = NameValueParameter.class.getDeclaredField("expression"); + exprField.setAccessible(true); + Optional parameter = parent.node.getParameters().stream().filter(p -> { + try { + return exprField.get(p) == this.node; + } catch (IllegalArgumentException | IllegalAccessException e) { + return false; + } + }).findFirst(); + + Field nameField = NameValueParameter.class.getDeclaredField("name"); + nameField.setAccessible(true); + return parameter.map(p -> { + try { + return (Identifier) nameField.get(p); + } catch (IllegalArgumentException | IllegalAccessException e) { + return null; + } + }).map(Identifier::getValue).orElse(null); + } catch (NoSuchFieldException | SecurityException e1) { + return null; + } + } + return null; + } } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java index 60269d4510..9ffa7b764e 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewKeyValueObjectExpression.java @@ -16,4 +16,12 @@ public class ASTNewKeyValueObjectExpression extends AbstractApexNode node = parse("public class Foo { \n" + + " public void foo(String newName, String tempID) { \n" + + " if (Contact.sObjectType.getDescribe().isCreateable() && Contact.sObjectType.getDescribe().isUpdateable()) {\n" + + " upsert new Contact(FirstName = 'First', LastName = 'Last', Phone = '414-414-4414');\n" + + " }\n" + " } \n" + "}"); + + ASTNewKeyValueObjectExpression keyValueExpr = node.getFirstDescendantOfType(ASTNewKeyValueObjectExpression.class); + Assert.assertEquals(3, keyValueExpr.getParameterCount()); + + List literals = keyValueExpr.findDescendantsOfType(ASTLiteralExpression.class); + Assert.assertEquals(3, literals.size()); + Assert.assertEquals("FirstName", literals.get(0).getName()); + Assert.assertEquals("LastName", literals.get(1).getName()); + Assert.assertEquals("Phone", literals.get(2).getName()); + } + +} From e8f8e1ac7a9f4f21bb7a0f9242a81fe7ab7e599c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 14:03:32 +0100 Subject: [PATCH 71/99] Update release notes, document apex attributes --- docs/pages/release_notes.md | 24 +++++++++++++++++++ .../lang/apex/ast/ASTCatchBlockStatement.java | 2 +- .../pmd/lang/apex/ast/ASTField.java | 6 ++++- .../lang/apex/ast/ASTFieldDeclaration.java | 4 ++++ .../lang/apex/ast/ASTNewObjectExpression.java | 2 +- .../rule/security/ApexOpenRedirectRule.java | 2 +- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index a7f700fafa..c55fcc2f93 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -33,6 +33,30 @@ will be developed at [pmd/pmd-designer](https://github.com/pmd/pmd-designer) from now on. The maven coordinates will stay the same for the time being. The designer will still be shipped with PMD's binaries. +#### Improved Apex Support + +* Many AST nodes now expose more information which makes it easier to write XPath-based rules for Apex. Here are + some examples: + * `Annotation[@Resolved = false()]` finds unsupported annotations. + * `AnnotationParameter[@Name='RestResource'][@Value='/myurl']` gives access to + annotation parameters. + * `CatchBlockStatement[@ExceptionType='Exception'][@VariableName='e']` finds catch + block for specific exception types. + * `Field[@Type='String']` find all String fields, `Field[string-length(@Name) < 5]` + finds all fields with short names and `Field[@Value='a']` find alls fields, that are + initialized with a specific value. + * `LiteralExpression[@String = true()]` finds all String literals. There are attributes + for each type: `@Boolean`, `@Integer`, `@Double`, `@Long`, `@Decimal`, `@Null`. + * `Method[@Constructor = true()]` selects all constructors. `Method[@ReturnType = 'String']` + selects all methods that return a String. + * The `ModifierNode` node has a couple of attributes to check for the existence of specific + modifiers: `@Test`, `@TestOrTestSetup`, `@WithSharing`, `@WithoutSharing`, `@InheritedSharing`, + `@WebService`, `@Global`, `@Override`. + * Many nodes now expose their type. E.g. with `Parameter[@Type='Integer']` you can find all + method parameters of type Integer. The same attribute `Type` exists as well for: + `NewObjectExpression`, `Property`, `VariableDeclaration`. + * `VariableExpression[@Image='i']` finds all variable usages of the variable "i". + #### New Rules * The new Java rule {% rule "java/design/AvoidUncheckedExceptionsInSignatures" %} (`java-design`) finds methods or constructors diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java index 217f803fd8..5c98af83f2 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTCatchBlockStatement.java @@ -17,7 +17,7 @@ public class ASTCatchBlockStatement extends AbstractApexNode implements CanSuppressWarn @Override public String getImage() { - return node.getFieldInfo().getName(); + return getName(); } @Override @@ -44,6 +44,10 @@ public class ASTField extends AbstractApexNode implements CanSuppressWarn return getFirstChildOfType(ASTModifierNode.class); } + public String getName() { + return node.getFieldInfo().getName(); + } + public String getValue() { if (node.getFieldInfo().getValue() != null) { return String.valueOf(node.getFieldInfo().getValue()); diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java index 5c382e3574..7198442c65 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTFieldDeclaration.java @@ -19,6 +19,10 @@ public class ASTFieldDeclaration extends AbstractApexNode { @Override public String getImage() { + return getName(); + } + + public String getName() { if (node.getFieldInfo() != null) { return node.getFieldInfo().getName(); } diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java index 745578637a..63c6465538 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ASTNewObjectExpression.java @@ -17,7 +17,7 @@ public class ASTNewObjectExpression extends AbstractApexNode Date: Sun, 17 Feb 2019 20:00:52 +0100 Subject: [PATCH 72/99] [plsql] Add Support for XMLTABLE Refs #1510 --- pmd-plsql/etc/grammar/PldocAST.jjt | 85 +++++++++++++-- .../plsql/ast/PLSQLParserVisitorAdapter.java | 25 +++++ .../lang/plsql/rule/AbstractPLSQLRule.java | 25 +++++ .../pmd/lang/plsql/ast/XMLTableTest.java | 23 ++++ .../pmd/lang/plsql/ast/XMLTable.pls | 101 ++++++++++++++++++ 5 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLTableTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 87715b4055..d50ff4935d 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -190,6 +190,14 @@ public class PLSQLParser { } return s.toString(); } + + /** + * Semantic lookahead to check if the next identifier is a + * specific keyword. + */ + private boolean isKeyword(String keyword) { + return getToken(1).kind == IDENTIFIER && getToken(1).image.equalsIgnoreCase(keyword); + } } PARSER_END(PLSQLParser) @@ -1503,14 +1511,14 @@ ASTSimpleExpression SimpleExpression() : LOOKAHEAD(6) SchemaName() { sb.append(token.image); } "." { sb.append(token.image); } TableName() { sb.append(token.image); } "." { sb.append(token.image); } - Column() { sb.append(token.image); } + ( "*" | Column() ) { sb.append(token.image); } | LOOKAHEAD(4) TableName() { sb.append(token.image); } "." { sb.append(token.image); } - Column() { sb.append(token.image); } + ( "*" | Column() ) { sb.append(token.image); } | LOOKAHEAD(2) - Column() { sb.append(token.image); } + ( "*" | Column() ) { sb.append(token.image); } ) { jjtThis.setImage(sb.toString()); @@ -1537,9 +1545,8 @@ ASTFunctionCall FunctionCall() : { name = FunctionName() ( - LOOKAHEAD({"TRIM".equalsIgnoreCase(token.image)}) TrimExpression() - | - Arguments() + LOOKAHEAD({"TRIM".equalsIgnoreCase(token.image)}) TrimExpression() + | Arguments() ) { @@ -1565,6 +1572,70 @@ ASTFunctionName FunctionName() : } } +/** + * https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/XMLTABLE.html + */ +ASTXMLTable XMLTable() : +{} +{ + KEYWORD("XMLTABLE") + "(" + [ LOOKAHEAD({isKeyword("XMLNAMESPACES")}) XMLNamespacesClause() "," ] + StringLiteral() + XMLTableOptions() + ")" + { return jjtThis; } +} + +ASTXMLNamespacesClause XMLNamespacesClause() : +{} +{ + KEYWORD("XMLNAMESPACES") "(" + ( + ( StringLiteral() ID() + | <_DEFAULT> StringLiteral() ) + (",")? + )+ + ")" + { return jjtThis; } +} + +ASTXMLTableOptions XMLTableOptions() : +{} +{ + [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] + [ KEYWORD("SEQUENCE") "REF" ] + [ ( XMLTableColum() (",")? )+ ] + { return jjtThis; } +} + +ASTXMLTableColum XMLTableColum() : +{} +{ + Column() + ( + KEYWORD("ORDINALITY") + | + ( + LOOKAHEAD({isKeyword("XMLTYPE")}) KEYWORD("XMLTYPE") [ "(" KEYWORD("SEQUENCE") ")" "REF" ] + | + Datatype() + ) + [ LOOKAHEAD({isKeyword("PATH")}) KEYWORD("PATH") StringLiteral() ] + [ <_DEFAULT> SqlExpression() ] + ) + { return jjtThis; } +} + +ASTXMLPassingClause XMLPassingClause() : +{} +{ + KEYWORD("PASSING") + [ "VALUE" ] + ( LOOKAHEAD(2) SqlExpression() [ LOOKAHEAD(2) ID() ] (",")? )+ + { return jjtThis; } +} + /** * See https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/Analytic-Functions.html */ @@ -1656,6 +1727,8 @@ void FromClauseEntry() #void : // using lookahead to avoid misinterpreting the token after the identifier // as a table alias rather than as a keyword LOOKAHEAD( (||||||)) JoinClause() + | + LOOKAHEAD( "(", {isKeyword("XMLTABLE")}) XMLTable() [ LOOKAHEAD(2) TableAlias() ] | LOOKAHEAD(3) TableReference() | diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java index 9ec26fdcfe..92d4c57cfb 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java @@ -1056,4 +1056,29 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { public Object visit(ASTSimpleExpression node, Object data) { return visit((PLSQLNode) node, data); } + + @Override + public Object visit(ASTXMLTable node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLNamespacesClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLTableOptions node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLPassingClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLTableColum node, Object data) { + return visit((PLSQLNode) node, data); + } } diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java index 136e84b364..7d9d58e052 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java @@ -1150,6 +1150,31 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar return visit((PLSQLNode) node, data); } + @Override + public Object visit(ASTXMLTable node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLNamespacesClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLTableOptions node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLPassingClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLTableColum node, Object data) { + return visit((PLSQLNode) node, data); + } + /* * Treat all Executable Code */ diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLTableTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLTableTest.java new file mode 100644 index 0000000000..476a35e29a --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLTableTest.java @@ -0,0 +1,23 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; + +public class XMLTableTest extends AbstractPLSQLParserTst { + + @Test + public void testParseXMLTable() throws Exception { + ASTInput input = parsePLSQL(IOUtils.toString(this.getClass().getResourceAsStream("XMLTable.pls"), + StandardCharsets.UTF_8)); + Assert.assertNotNull(input); + } +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls new file mode 100644 index 0000000000..8c75caf6b4 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls @@ -0,0 +1,101 @@ +-- +-- Samples from https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/XMLTABLE.html +-- + +BEGIN + +SELECT warehouse_name warehouse, + warehouse2."Water", warehouse2."Rail" + FROM warehouses, + XMLTABLE('/Warehouse' + PASSING warehouses.warehouse_spec + COLUMNS + "Water" varchar2(6) PATH 'WaterAccess', + "Rail" varchar2(6) PATH 'RailAccess') + warehouse2; + +/* +-- +-- Samples from https://docs.oracle.com/en/database/oracle/oracle-database/18/adxdb/xquery-and-XML-DB.html +-- + SELECT po.reference, li.* + FROM po_binaryxml p, + XMLTable('/PurchaseOrder' PASSING p.OBJECT_VALUE + COLUMNS + reference VARCHAR2(30) PATH 'Reference', + lineitem XMLType PATH 'LineItems/LineItem') po, + XMLTable('/LineItem' PASSING po.lineitem + COLUMNS + itemno NUMBER(38) PATH '@ItemNumber', + description VARCHAR2(256) PATH 'Description', + partno VARCHAR2(14) PATH 'Part/@Id', + quantity NUMBER(12, 2) PATH 'Part/@Quantity', + unitprice NUMBER(8, 4) PATH 'Part/@UnitPrice') li; + +SELECT OBJECT_VALUE + FROM purchaseorder + WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]' + PASSING OBJECT_VALUE); +SELECT XMLCast(XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE + RETURNING CONTENT) + AS VARCHAR2(100)) "REFERENCE" + FROM purchaseorder + WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]' + PASSING OBJECT_VALUE); + + +UPDATE oe.purchaseorder p SET p.OBJECT_VALUE = + XMLQuery( + 'copy $i := + $p1 modify (for $j in $i/PurchaseOrder/LineItems + return (#ora:child-element-name LineItem #) + {insert node $p2 into $j) + return $i' + PASSING p.OBJECT_VALUE AS "p1", :1 AS "p2" RETURNING CONTENT) + WHERE XMLQuery( + '/PurchaseOrder/Reference/text()' + PASSING p.OBJECT_VALUE RETURNING CONTENT).getStringVal() = + 'EMPTY_LINES'; + +SELECT XMLQuery('(#ora:invalid_path empty #) + {exists($p/PurchaseOrder//NotInTheSchema)}' + PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) + FROM oe.purchaseorder p; + +SELECT XMLQuery('(#ora:view_on_null empty #) + {for $i in fn:collection("oradb:/PUBLIC/NULL_TEST")/ROW + return $i}' + RETURNING CONTENT) + FROM DUAL; + +SELECT XMLQuery('(#ora:view_on_null null #) + {for $i in fn:collection("oradb:/PUBLIC/NULL_TEST")/ROW + return $i}' + RETURNING CONTENT) + FROM DUAL; + +SELECT XMLQuery('(#ora:no_xmlquery_rewrite#) (: Do not optimize expression :) + {for $i in (#ora:xmlquery_rewrite#) (: Optimize subexp. :) + {fn:collection("oradb:/HR/REGIONS")}, + $j in (#ora:xmlquery_rewrite#) (: Optimize subexpr. :) + {fn:collection("oradb:/HR/COUNTRIES")} + where $i/ROW/REGION_ID = $j/ROW/REGION_ID + and $i/ROW/REGION_NAME = $regionname + return $j}' + PASSING CAST('®ION' AS VARCHAR2(40)) AS "regionname" + RETURNING CONTENT) + AS asian_countries FROM DUAL; + +SELECT XMLQuery('declare default element namespace + "http://xmlns.oracle.com/xdb/xdbconfig.xsd"; (: :) + (#ora:transform_keep_schema#) + {copy $NEWXML := + $XML modify (for $CFG in $NEWXML/xdbconfig//httpconfig + return (replace value of node + $CFG/http-port with xs:int($PORTNO))) + return $NEWXML}' + PASSING CFG AS "XML", 81 as "PORTNO" RETURNING CONTENT) + FROM DUAL; +*/ + +END; From 44c6d0ed3b91aff6ce67351c921764eb3a44ab26 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Mon, 18 Feb 2019 19:42:35 +0100 Subject: [PATCH 73/99] [plsql] Add support for XMLEXISTS --- pmd-plsql/etc/grammar/PldocAST.jjt | 13 +++++++++++++ .../lang/plsql/ast/PLSQLParserVisitorAdapter.java | 5 +++++ .../pmd/lang/plsql/rule/AbstractPLSQLRule.java | 5 +++++ .../net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls | 3 ++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index d50ff4935d..4c6fbeb023 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1317,6 +1317,8 @@ void Condition2() #void : LOOKAHEAD() RegexpLikeCondition() | LOOKAHEAD() ExistsCondition() + | + LOOKAHEAD({isKeyword("XMLEXISTS")}) XMLExists() | LOOKAHEAD(MultisetCondition()) MultisetCondition() | @@ -1636,6 +1638,17 @@ ASTXMLPassingClause XMLPassingClause() : { return jjtThis; } } +ASTXMLExists XMLExists() : +{} +{ + KEYWORD("XMLEXISTS") + "(" + StringLiteral() + [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] + ")" + { return jjtThis; } +} + /** * See https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/Analytic-Functions.html */ diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java index 92d4c57cfb..7631a04352 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java @@ -1081,4 +1081,9 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { public Object visit(ASTXMLTableColum node, Object data) { return visit((PLSQLNode) node, data); } + + @Override + public Object visit(ASTXMLExists node, Object data) { + return visit((PLSQLNode) node, data); + } } diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java index 7d9d58e052..eb349e247f 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java @@ -1175,6 +1175,11 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar return visit((PLSQLNode) node, data); } + @Override + public Object visit(ASTXMLExists node, Object data) { + return visit((PLSQLNode) node, data); + } + /* * Treat all Executable Code */ diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls index 8c75caf6b4..3324041758 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls @@ -14,7 +14,6 @@ SELECT warehouse_name warehouse, "Rail" varchar2(6) PATH 'RailAccess') warehouse2; -/* -- -- Samples from https://docs.oracle.com/en/database/oracle/oracle-database/18/adxdb/xquery-and-XML-DB.html -- @@ -36,6 +35,8 @@ SELECT OBJECT_VALUE FROM purchaseorder WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]' PASSING OBJECT_VALUE); + +/* SELECT XMLCast(XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE RETURNING CONTENT) AS VARCHAR2(100)) "REFERENCE" From 4367841578e98c6e1b240581738e0f3df39f66b4 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Feb 2019 21:43:17 +0100 Subject: [PATCH 74/99] [plsql] Support XMLCAST, XMLQUERY, CAST --- pmd-plsql/etc/grammar/PldocAST.jjt | 7 +++++-- .../net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 4c6fbeb023..4bc55cc7ba 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1548,6 +1548,9 @@ ASTFunctionCall FunctionCall() : name = FunctionName() ( LOOKAHEAD({"TRIM".equalsIgnoreCase(token.image)}) TrimExpression() + | LOOKAHEAD({"XMLCAST".equalsIgnoreCase(token.image)}) "(" Expression() Datatype() ")" + | LOOKAHEAD({"XMLQUERY".equalsIgnoreCase(token.image)}) "(" StringLiteral() [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] KEYWORD("CONTENT") [ ] ")" + | LOOKAHEAD({"CAST".equalsIgnoreCase(token.image)}) "(" ( "(" Subquery() ")" | Expression() ) Datatype() ")" | Arguments() ) @@ -1634,7 +1637,8 @@ ASTXMLPassingClause XMLPassingClause() : { KEYWORD("PASSING") [ "VALUE" ] - ( LOOKAHEAD(2) SqlExpression() [ LOOKAHEAD(2) ID() ] (",")? )+ + ( SqlExpression() [ LOOKAHEAD(2) ID() ] ) + ( "," SqlExpression() [ LOOKAHEAD(2) ID() ] )* { return jjtThis; } } @@ -5189,7 +5193,6 @@ ASTKEYWORD_UNRESERVED KEYWORD_UNRESERVED (): {} //| | //| -//| //| | | diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls index 3324041758..667011bf8a 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls @@ -36,7 +36,7 @@ SELECT OBJECT_VALUE WHERE XMLExists('/PurchaseOrder[SpecialInstructions="Expedite"]' PASSING OBJECT_VALUE); -/* + SELECT XMLCast(XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE RETURNING CONTENT) AS VARCHAR2(100)) "REFERENCE" @@ -97,6 +97,5 @@ SELECT XMLQuery('declare default element namespace return $NEWXML}' PASSING CFG AS "XML", 81 as "PORTNO" RETURNING CONTENT) FROM DUAL; -*/ END; From 527ae5d785b85ceb2e346ccefbcc4c86f7eb8c1d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Feb 2019 21:54:34 +0100 Subject: [PATCH 75/99] [plsql] Support XMLFOREST --- pmd-plsql/etc/grammar/PldocAST.jjt | 1 + .../net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 4bc55cc7ba..eb87181532 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1551,6 +1551,7 @@ ASTFunctionCall FunctionCall() : | LOOKAHEAD({"XMLCAST".equalsIgnoreCase(token.image)}) "(" Expression() Datatype() ")" | LOOKAHEAD({"XMLQUERY".equalsIgnoreCase(token.image)}) "(" StringLiteral() [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] KEYWORD("CONTENT") [ ] ")" | LOOKAHEAD({"CAST".equalsIgnoreCase(token.image)}) "(" ( "(" Subquery() ")" | Expression() ) Datatype() ")" + | LOOKAHEAD({"XMLFOREST".equalsIgnoreCase(token.image)}) "(" SqlExpression() [ ID() ] ( "," SqlExpression() [ ID() ] )* ")" | Arguments() ) diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls index 667011bf8a..b56bfeb806 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLTable.pls @@ -98,4 +98,9 @@ SELECT XMLQuery('declare default element namespace PASSING CFG AS "XML", 81 as "PORTNO" RETURNING CONTENT) FROM DUAL; +SELECT XMLELEMENT("Emp", + XMLFOREST(e.employee_id AS foo, e.last_name, e.salary)) + "Emp Element" + FROM employees e WHERE employee_id = 204; + END; From 1f58482f542fdcd463781a1c9015d9c38a2f87d2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Wed, 20 Feb 2019 22:08:13 +0100 Subject: [PATCH 76/99] Update release notes, fixes #1510 --- docs/pages/release_notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8c9f42def8..41cd225fcf 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -61,6 +61,8 @@ The designer will still be shipped with PMD's binaries. * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods * java-codestyle * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong +* plsql + * [#1510](https://github.com/pmd/pmd/issues/1510): \[plsql] Support XMLTABLE functions ### API Changes From a0cb67308da86942c427a4446e79ce4e3700e367 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 15:08:32 +0100 Subject: [PATCH 77/99] [plsql] Add support for XMLElement --- pmd-plsql/etc/grammar/PldocAST.jjt | 35 +++++++++++++++++++ .../plsql/ast/PLSQLParserVisitorAdapter.java | 10 ++++++ .../lang/plsql/rule/AbstractPLSQLRule.java | 10 ++++++ .../pmd/lang/plsql/ast/XMLElementTest.java | 23 ++++++++++++ .../pmd/lang/plsql/ast/XMLElement.pls | 27 ++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLElement.pls diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index eb87181532..8cfdbbf15b 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1552,6 +1552,7 @@ ASTFunctionCall FunctionCall() : | LOOKAHEAD({"XMLQUERY".equalsIgnoreCase(token.image)}) "(" StringLiteral() [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] KEYWORD("CONTENT") [ ] ")" | LOOKAHEAD({"CAST".equalsIgnoreCase(token.image)}) "(" ( "(" Subquery() ")" | Expression() ) Datatype() ")" | LOOKAHEAD({"XMLFOREST".equalsIgnoreCase(token.image)}) "(" SqlExpression() [ ID() ] ( "," SqlExpression() [ ID() ] )* ")" + | LOOKAHEAD({"XMLELEMENT".equalsIgnoreCase(token.image)}) "(" XMLElement() ")" | Arguments() ) @@ -1654,6 +1655,40 @@ ASTXMLExists XMLExists() : { return jjtThis; } } +ASTXMLElement XMLElement() : +{} +{ + [ LOOKAHEAD({isKeyword("ENTITYESCAPING") || isKeyword("NOENTITYESCAPING")}) ] + ( + LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() + | + [ LOOKAHEAD({isKeyword("NAME")}) KEYWORD("NAME") ] ID() + ) + [ LOOKAHEAD(1) + "," + ( + LOOKAHEAD({isKeyword("XMLATTRIBUTES")}) XMLAttributesClause() + | + Expression() [ [ ] ColumnAlias() ] + ) + ] + ( "," Expression() [ [ ] ColumnAlias() ] )* + { return jjtThis; } +} + +ASTXMLAttributesClause XMLAttributesClause() : +{} +{ + KEYWORD("XMLATTRIBUTES") "(" + [ LOOKAHEAD({isKeyword("ENTITYESCAPING") || isKeyword("NOENTITYESCAPING")}) ] + [ LOOKAHEAD({isKeyword("SCHEMACHECK") || isKeyword("NOSCHEMACHECK")}) ] + + Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | ColumnAlias() | Expression() ) ] + ("," Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | ColumnAlias() | Expression() ) ] )* + ")" + { return jjtThis; } +} + /** * See https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/Analytic-Functions.html */ diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java index 7631a04352..3b274382f4 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/PLSQLParserVisitorAdapter.java @@ -1086,4 +1086,14 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { public Object visit(ASTXMLExists node, Object data) { return visit((PLSQLNode) node, data); } + + @Override + public Object visit(ASTXMLAttributesClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLElement node, Object data) { + return visit((PLSQLNode) node, data); + } } diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java index eb349e247f..598ac08534 100644 --- a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/AbstractPLSQLRule.java @@ -1180,6 +1180,16 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar return visit((PLSQLNode) node, data); } + @Override + public Object visit(ASTXMLAttributesClause node, Object data) { + return visit((PLSQLNode) node, data); + } + + @Override + public Object visit(ASTXMLElement node, Object data) { + return visit((PLSQLNode) node, data); + } + /* * Treat all Executable Code */ diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java new file mode 100644 index 0000000000..2398f32c3c --- /dev/null +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java @@ -0,0 +1,23 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; + +public class XMLElementTest extends AbstractPLSQLParserTst { + + @Test + public void testParseXMLElement() throws Exception { + ASTInput input = parsePLSQL(IOUtils.toString(this.getClass().getResourceAsStream("XMLElement.pls"), + StandardCharsets.UTF_8)); + Assert.assertNotNull(input); + } +} diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLElement.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLElement.pls new file mode 100644 index 0000000000..8f2731f697 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/XMLElement.pls @@ -0,0 +1,27 @@ +-- +-- Examples from: https://docs.oracle.com/en/database/oracle/oracle-database/18/sqlrf/XMLELEMENT.html#GUID-DEA75423-00EA-4034-A246-4A774ADC988E +-- +BEGIN + +SELECT XMLELEMENT("Emp", XMLELEMENT("Name", + e.job_id||' '||e.last_name), + XMLELEMENT("Hiredate", e.hire_date)) as "Result" + FROM employees e WHERE employee_id > 200; + +SELECT XMLELEMENT("Emp", + XMLATTRIBUTES(e.employee_id AS "ID", e.last_name), + XMLELEMENT("Dept", e.department_id), + XMLELEMENT("Salary", e.salary)) AS "Emp Element" + FROM employees e + WHERE e.employee_id = 206; + +SELECT XMLELEMENT("Emp", XMLATTRIBUTES(e.employee_id, e.last_name), + XMLELEMENT("Dept", XMLATTRIBUTES(e.department_id, + (SELECT d.department_name FROM departments d + WHERE d.department_id = e.department_id) as "Dept_name")), + XMLELEMENT("salary", e.salary), + XMLELEMENT("Hiredate", e.hire_date)) AS "Emp Element" + FROM employees e + WHERE employee_id = 205; + +END; From 9bb2492ba591b4ddf2251b52190765b59c2be1c0 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 17:46:52 +0100 Subject: [PATCH 78/99] [plsql] Fix choice conflicts - AS is a reserved word --- pmd-plsql/etc/grammar/PldocAST.jjt | 9 +++++---- .../sourceforge/pmd/lang/plsql/ast/XMLElementTest.java | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 8cfdbbf15b..f9e6f19f1b 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1552,7 +1552,7 @@ ASTFunctionCall FunctionCall() : | LOOKAHEAD({"XMLQUERY".equalsIgnoreCase(token.image)}) "(" StringLiteral() [ LOOKAHEAD({isKeyword("PASSING")}) XMLPassingClause() ] KEYWORD("CONTENT") [ ] ")" | LOOKAHEAD({"CAST".equalsIgnoreCase(token.image)}) "(" ( "(" Subquery() ")" | Expression() ) Datatype() ")" | LOOKAHEAD({"XMLFOREST".equalsIgnoreCase(token.image)}) "(" SqlExpression() [ ID() ] ( "," SqlExpression() [ ID() ] )* ")" - | LOOKAHEAD({"XMLELEMENT".equalsIgnoreCase(token.image)}) "(" XMLElement() ")" + | LOOKAHEAD({"XMLELEMENT".equalsIgnoreCase(token.image)}) XMLElement() | Arguments() ) @@ -1658,6 +1658,7 @@ ASTXMLExists XMLExists() : ASTXMLElement XMLElement() : {} { + "(" [ LOOKAHEAD({isKeyword("ENTITYESCAPING") || isKeyword("NOENTITYESCAPING")}) ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() @@ -1673,6 +1674,7 @@ ASTXMLElement XMLElement() : ) ] ( "," Expression() [ [ ] ColumnAlias() ] )* + ")" { return jjtThis; } } @@ -1683,8 +1685,8 @@ ASTXMLAttributesClause XMLAttributesClause() : [ LOOKAHEAD({isKeyword("ENTITYESCAPING") || isKeyword("NOENTITYESCAPING")}) ] [ LOOKAHEAD({isKeyword("SCHEMACHECK") || isKeyword("NOSCHEMACHECK")}) ] - Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | ColumnAlias() | Expression() ) ] - ("," Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | ColumnAlias() | Expression() ) ] )* + Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | LOOKAHEAD(2) ColumnAlias() | Expression() ) ] + ("," Expression() [ [ ] ( LOOKAHEAD({isKeyword("EVALNAME")}) KEYWORD("EVALNAME") Expression() | LOOKAHEAD(2) ColumnAlias() | Expression() ) ] )* ")" { return jjtThis; } } @@ -6188,7 +6190,6 @@ ASTID ID(): {} | //SYNTAX //RESERVED WORD | //RESERVED WORD | - | //SYNTAX //RESERVED WORD | //RESERVED WORD //20120429 | | //| diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java index 2398f32c3c..31781cb261 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/XMLElementTest.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.plsql.ast; import java.nio.charset.StandardCharsets; +import java.util.List; import org.apache.commons.io.IOUtils; import org.junit.Assert; @@ -19,5 +20,9 @@ public class XMLElementTest extends AbstractPLSQLParserTst { ASTInput input = parsePLSQL(IOUtils.toString(this.getClass().getResourceAsStream("XMLElement.pls"), StandardCharsets.UTF_8)); Assert.assertNotNull(input); + List xmlelements = input.findDescendantsOfType(ASTXMLElement.class); + Assert.assertEquals(10, xmlelements.size()); + Assert.assertEquals("\"Emp\"", xmlelements.get(0).getFirstChildOfType(ASTID.class).getImage()); + Assert.assertTrue(xmlelements.get(3).jjtGetChild(1) instanceof ASTXMLAttributesClause); } } From 2b092456fd53497979829d23634b2098937783c5 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 17:54:12 +0100 Subject: [PATCH 79/99] [plsql] Update grammar changelog --- pmd-plsql/etc/grammar/PldocAST.jjt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index f9e6f19f1b..b6cd4c5180 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -27,6 +27,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** + * Added support for XMLTABLE, XMLEXISTS, XMLCAST, XMLQUERY, CAST, XMLFOREST + * and XMLELEMENT + * + * Andreas Dangel 03/2019 + *==================================================================== + * More complete support for UPDATE statements and subqueries and hierarchical + * queries in SELECT statements. + * Added support for analytic functions such as LISTAGG. + * Conditions in WHERE clauses support now REGEX_LIKE and multiset conditions. + * + * Andreas Dangel 02/2019 + *==================================================================== + * Added support for TableCollectionExpressions + * + * Andreas Dangel 01/2019 + *==================================================================== * Added support for DELETE Statements * Added support for UPDATE Statements * Fully parse the select statement in CursorForLoops. From a0876f71f524b7f53ee211a3609e1646fe94f673 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 18:16:45 +0100 Subject: [PATCH 80/99] [java] UseUnderscoresInNumericLiterals false positive on floating point numbers Fixes #1527 --- docs/pages/release_notes.md | 1 + .../main/resources/category/java/codestyle.xml | 4 ++-- .../xml/UseUnderscoresInNumericLiterals.xml | 17 ++++++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8c9f42def8..49fd1f9172 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -60,6 +60,7 @@ The designer will still be shipped with PMD's binaries. * java-bestpractices * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods * java-codestyle + * [#1527](https://github.com/pmd/pmd/issues/1527): \[java] UseUnderscoresInNumericLiterals false positive on floating point numbers * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong ### API Changes diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml index a7a89bf795..195418159e 100644 --- a/pmd-java/src/main/resources/category/java/codestyle.xml +++ b/pmd-java/src/main/resources/category/java/codestyle.xml @@ -1405,11 +1405,11 @@ public class ClassInDefaultPackage { (: Filter out ignored field name :) [not(ancestor::VariableDeclarator[1][@Name = 'serialVersionUID'])] [ - some $num in tokenize(@Image, "[.dDfFlLeE+\-]") + some $num in tokenize(@Image, "[dDfFlLeE+\-]") satisfies not( string-length($num) <= $acceptableDecimalLength and not(contains($num,"_")) - or matches($num, "^[0-9]{1,3}(_[0-9]{3})*$") + or matches($num, "^[0-9]{1,3}(_[0-9]{3})*(\.([0-9]{3}_)*[0-9]{1,3})?$") ) ] ]]> diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml index 403dfd7d1f..e66c3b2343 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml @@ -322,8 +322,23 @@ public class Foo { 0 + + + #1527 [java] UseUnderscoresInNumericLiterals false positive on floating point numbers + 0 + + From 921ee050bd9b9bee8cd6e7a151382aef69357a33 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 18:22:47 +0100 Subject: [PATCH 81/99] Add additional test case --- .../xml/UseUnderscoresInNumericLiterals.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml index e66c3b2343..0c19095512 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml @@ -341,4 +341,17 @@ public class Foo { } ]]> + + + Decimal number test - bad cases + 4 + + From 878db5617fa3cf0419034755869e05d62f57bb16 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 19:10:24 +0100 Subject: [PATCH 82/99] [java] AvoidDuplicateLiterals warning about deprecated separator property when not used Fixes #1570 --- docs/pages/release_notes.md | 2 ++ .../net/sourceforge/pmd/lang/rule/AbstractRule.java | 7 ++++--- .../java/net/sourceforge/pmd/AbstractRuleTest.java | 10 +++++++--- .../rule/errorprone/AvoidDuplicateLiteralsTest.java | 11 +++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8c9f42def8..01f174177f 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -61,6 +61,8 @@ The designer will still be shipped with PMD's binaries. * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods * java-codestyle * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong +* java-errorprone + * [#1570](https://github.com/pmd/pmd/issues/1570): \[java] AvoidDuplicateLiterals warning about deprecated separator property when not used ### API Changes diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRule.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRule.java index c2614de710..e3b9ed5e6c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRule.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/AbstractRule.java @@ -468,10 +468,11 @@ public abstract class AbstractRule extends AbstractPropertySource implements Rul if (rule.getPropertyDescriptor(prop.name()) == null) { rule.definePropertyDescriptor(prop); // Property descriptors are immutable, and can be freely shared } - - rule.setProperty((PropertyDescriptor) prop, getProperty((PropertyDescriptor) prop)); + + if (isPropertyOverridden(prop)) { + rule.setProperty((PropertyDescriptor) prop, getProperty((PropertyDescriptor) prop)); + } } - return rule; } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java index f42e4b058c..66df658779 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java @@ -30,12 +30,17 @@ public class AbstractRuleTest { public static class MyRule extends AbstractRule { private static final StringProperty FOO_PROPERTY = new StringProperty("foo", "foo property", "x", 1.0f); + private static final PropertyDescriptor FOO_DEFAULT_PROPERTY = PropertyFactory.stringProperty("fooDefault") + .defaultValue("bar") + .desc("Property without value uses default value") + .build(); private static final StringProperty XPATH_PROPERTY = new StringProperty("xpath", "xpath property", "", 2.0f); public MyRule() { definePropertyDescriptor(FOO_PROPERTY); definePropertyDescriptor(XPATH_PROPERTY); + definePropertyDescriptor(FOO_DEFAULT_PROPERTY); setName("MyRule"); setMessage("my rule msg"); setPriority(RulePriority.MEDIUM); @@ -223,9 +228,8 @@ public class AbstractRuleTest { assertEquals(r1.getRuleClass(), r2.getRuleClass()); assertEquals(r1.getRuleSetName(), r2.getRuleSetName()); assertEquals(r1.getSince(), r2.getSince()); - } - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(AbstractRuleTest.class); + assertEquals(r1.isPropertyOverridden(MyRule.FOO_DEFAULT_PROPERTY), + r2.isPropertyOverridden(MyRule.FOO_DEFAULT_PROPERTY)); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsTest.java index f6cc10d645..30dde60d0f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/AvoidDuplicateLiteralsTest.java @@ -9,8 +9,10 @@ import static org.junit.Assert.assertTrue; import java.util.Set; +import org.junit.Assert; import org.junit.Test; +import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.testframework.PmdRuleTst; public class AvoidDuplicateLiteralsTest extends PmdRuleTst { @@ -50,4 +52,13 @@ public class AvoidDuplicateLiteralsTest extends PmdRuleTst { assertTrue(res.contains("b")); assertTrue(res.contains("\\")); } + + @Test + public void testSeparatorPropertyWarning() throws Exception { + AvoidDuplicateLiteralsRule rule = new AvoidDuplicateLiteralsRule(); + Assert.assertFalse(rule.isPropertyOverridden(AvoidDuplicateLiteralsRule.SEPARATOR_DESCRIPTOR)); + + Rule copy = rule.deepCopy(); + Assert.assertFalse(copy.isPropertyOverridden(AvoidDuplicateLiteralsRule.SEPARATOR_DESCRIPTOR)); + } } From ae4b56e70ff3ffd9ea56f17c581cff2c4ef73a10 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 29 Mar 2019 19:57:48 +0100 Subject: [PATCH 83/99] [java] UseUnderscoresInNumericLiterals - check the length before and after decimal point separately --- pmd-java/src/main/resources/category/java/codestyle.xml | 8 ++++++-- .../codestyle/xml/UseUnderscoresInNumericLiterals.xml | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pmd-java/src/main/resources/category/java/codestyle.xml b/pmd-java/src/main/resources/category/java/codestyle.xml index 195418159e..8421462853 100644 --- a/pmd-java/src/main/resources/category/java/codestyle.xml +++ b/pmd-java/src/main/resources/category/java/codestyle.xml @@ -1407,8 +1407,12 @@ public class ClassInDefaultPackage { [ some $num in tokenize(@Image, "[dDfFlLeE+\-]") satisfies not( - string-length($num) <= $acceptableDecimalLength - and not(contains($num,"_")) + ( contains($num, ".") + and string-length(substring-before($num, ".")) <= $acceptableDecimalLength + and string-length(substring-after($num, ".")) <= $acceptableDecimalLength + or string-length($num) <= $acceptableDecimalLength + ) + and not(contains($num,"_")) or matches($num, "^[0-9]{1,3}(_[0-9]{3})*(\.([0-9]{3}_)*[0-9]{1,3})?$") ) ] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml index 0c19095512..bd1af8d293 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/UseUnderscoresInNumericLiterals.xml @@ -327,6 +327,9 @@ public class Foo { double value3 = -0.1; double value4 = -0.123_456; double value5 = +0.123_456; + + double valid1 = 0.3936; + double valid2 = 1000.0; } ]]> From 8692b95576cd3782d122ff981104490e2548db57 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 17:34:44 +0100 Subject: [PATCH 84/99] Update release notes, mention call for logo again --- docs/pages/release_notes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 8c9f42def8..fc13d63d78 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,6 +14,12 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy +#### Call For Logo + +We are still searching for a new logo for PMD for the next major release. + +Learn more about how to participate on [github issue 1663](https://github.com/pmd/pmd/issues/1663). + #### Quickstart Ruleset for Apex PMD provides now a quickstart ruleset for Salesforce.com Apex, which you can use as a base ruleset to From 43d415d8f9ea2d6568e5c6704d00c2ad9a96b0e1 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 17:35:00 +0100 Subject: [PATCH 85/99] Use released build-tools version 2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fa827d176a..c366d65a52 100644 --- a/pom.xml +++ b/pom.xml @@ -282,7 +282,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code -Xmx512m -Dfile.encoding=${project.build.sourceEncoding} - 1.5.0-SNAPSHOT + 2 6.12.0 From 039333c9b8acdf519fc25da91bc75c78240e1ff3 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 17:35:40 +0100 Subject: [PATCH 86/99] Update release process: quickstart rulesets should be updated as well --- do-release.sh | 3 +++ docs/pages/pmd/projectdocs/committers/releasing.md | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/do-release.sh b/do-release.sh index 6d397d964c..707c59ce8a 100755 --- a/do-release.sh +++ b/do-release.sh @@ -75,6 +75,9 @@ echo echo "* Ensure all the new rules are listed in the proper file:" echo " ${RELEASE_RULESET}" echo +echo "* Update **pmd-apex/src/main/resources/rulesets/apex/quickstart.xml** and" +echo " **pmd-java/src/main/resources/rulesets/java/quickstart.xml** with the new rules. +echo echo "* Update **docs/pages/next_major_development.md** with the API changes for" echo " the new release based on the release notes" echo diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index 034a2b68b7..35d1c09791 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -42,6 +42,10 @@ The release notes usual mention any new rules that have been added since the las Please double check the file `pmd-core/src/main/resources/rulesets/releases/.xml`, so that all new rules are listed. +Add the new rules as comments to the quickstart rulesets: +* `pmd-apex/src/main/resources/rulesets/apex/quickstart.xml` +* `pmd-java/src/main/resources/rulesets/java/quickstart.xml` + We maintain a documentation for the [next major release](pmd_next_major_development.html). Copy the API changes from the current release notes to this document: `docs/pages/next_major_development.md`. From f46870c5eccdecbdd4caa7e1ec61d51edaa1ce90 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 17:52:10 +0100 Subject: [PATCH 87/99] [plsql] use isKeyword --- pmd-plsql/etc/grammar/PldocAST.jjt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index bdd128f896..19b8548887 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -1537,10 +1537,10 @@ ASTSimpleExpression SimpleExpression() : | // Named Cursor: https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/named-cursor-attribute.html#GUID-CD8D8415-FF19-4D81-99BA-7825FD40CC96 LOOKAHEAD(3) - Column() { sb.append(token.image); } "%" ( LOOKAHEAD({getToken(1).image.equalsIgnoreCase("isopen")}) KEYWORD("ISOPEN") - | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("found")}) KEYWORD("FOUND") - | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("notfound")}) KEYWORD("NOTFOUND") - | LOOKAHEAD({getToken(1).image.equalsIgnoreCase("rowcount")}) KEYWORD("ROWCOUNT") + Column() { sb.append(token.image); } "%" ( LOOKAHEAD({isKeyword("isopen")}) KEYWORD("ISOPEN") + | LOOKAHEAD({isKeyword("found")}) KEYWORD("FOUND") + | LOOKAHEAD({isKeyword("notfound")}) KEYWORD("NOTFOUND") + | LOOKAHEAD({isKeyword("rowcount")}) KEYWORD("ROWCOUNT") ) { sb.append('%').append(token.image); } | LOOKAHEAD(2) From 87f6951f15478c6d0832dc2801db997166bd3fc6 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 18:11:29 +0100 Subject: [PATCH 88/99] Update generated rule documentation --- docs/pages/pmd/rules/java.md | 2 +- docs/pages/pmd/rules/java/codestyle.md | 12 ++-- docs/pages/pmd/rules/plsql.md | 2 + docs/pages/pmd/rules/plsql/codestyle.md | 72 +++++++++++++++++++++++- docs/pages/pmd/rules/plsql/design.md | 12 ++-- docs/pages/pmd/rules/plsql/errorprone.md | 16 +++--- 6 files changed, 95 insertions(+), 21 deletions(-) diff --git a/docs/pages/pmd/rules/java.md b/docs/pages/pmd/rules/java.md index 2b54ae187d..29d0669364 100644 --- a/docs/pages/pmd/rules/java.md +++ b/docs/pages/pmd/rules/java.md @@ -540,7 +540,7 @@ folder: pmd/rules It contains the following rules: - [AbstractClassWithoutAnyMethod](pmd_rules_java_design.html#abstractclasswithoutanymethod), [AssignmentInOperand](pmd_rules_java_errorprone.html#assignmentinoperand), [AssignmentToNonFinalStatic](pmd_rules_java_errorprone.html#assignmenttononfinalstatic), [AvoidAccessibilityAlteration](pmd_rules_java_errorprone.html#avoidaccessibilityalteration), [AvoidBranchingStatementAsLastInLoop](pmd_rules_java_errorprone.html#avoidbranchingstatementaslastinloop), [AvoidCatchingThrowable](pmd_rules_java_errorprone.html#avoidcatchingthrowable), [AvoidDecimalLiteralsInBigDecimalConstructor](pmd_rules_java_errorprone.html#avoiddecimalliteralsinbigdecimalconstructor), [AvoidDollarSigns](pmd_rules_java_codestyle.html#avoiddollarsigns), [AvoidInstanceofChecksInCatchClause](pmd_rules_java_errorprone.html#avoidinstanceofchecksincatchclause), [AvoidMultipleUnaryOperators](pmd_rules_java_errorprone.html#avoidmultipleunaryoperators), [AvoidProtectedFieldInFinalClass](pmd_rules_java_codestyle.html#avoidprotectedfieldinfinalclass), [AvoidProtectedMethodInFinalClassNotExtending](pmd_rules_java_codestyle.html#avoidprotectedmethodinfinalclassnotextending), [AvoidStringBufferField](pmd_rules_java_bestpractices.html#avoidstringbufferfield), [AvoidThreadGroup](pmd_rules_java_multithreading.html#avoidthreadgroup), [AvoidUsingHardCodedIP](pmd_rules_java_bestpractices.html#avoidusinghardcodedip), [AvoidUsingOctalValues](pmd_rules_java_errorprone.html#avoidusingoctalvalues), [AvoidUsingVolatile](pmd_rules_java_multithreading.html#avoidusingvolatile), [BadComparison](pmd_rules_java_errorprone.html#badcomparison), [BigIntegerInstantiation](pmd_rules_java_performance.html#bigintegerinstantiation), [BooleanInstantiation](pmd_rules_java_performance.html#booleaninstantiation), [BrokenNullCheck](pmd_rules_java_errorprone.html#brokennullcheck), [CheckResultSet](pmd_rules_java_bestpractices.html#checkresultset), [CheckSkipResult](pmd_rules_java_errorprone.html#checkskipresult), [ClassCastExceptionWithToArray](pmd_rules_java_errorprone.html#classcastexceptionwithtoarray), [ClassNamingConventions](pmd_rules_java_codestyle.html#classnamingconventions), [ClassWithOnlyPrivateConstructorsShouldBeFinal](pmd_rules_java_design.html#classwithonlyprivateconstructorsshouldbefinal), [CloneMethodMustBePublic](pmd_rules_java_errorprone.html#clonemethodmustbepublic), [CloneMethodMustImplementCloneable](pmd_rules_java_errorprone.html#clonemethodmustimplementcloneable), [CloneMethodReturnTypeMustMatchClassName](pmd_rules_java_errorprone.html#clonemethodreturntypemustmatchclassname), [CloneThrowsCloneNotSupportedException](pmd_rules_java_errorprone.html#clonethrowsclonenotsupportedexception), [CloseResource](pmd_rules_java_errorprone.html#closeresource), [CompareObjectsWithEquals](pmd_rules_java_errorprone.html#compareobjectswithequals), [ConstantsInInterface](pmd_rules_java_bestpractices.html#constantsininterface), [ControlStatementBraces](pmd_rules_java_codestyle.html#controlstatementbraces), [DefaultLabelNotLastInSwitchStmt](pmd_rules_java_bestpractices.html#defaultlabelnotlastinswitchstmt), [DoNotCallGarbageCollectionExplicitly](pmd_rules_java_errorprone.html#donotcallgarbagecollectionexplicitly), [DoNotExtendJavaLangError](pmd_rules_java_design.html#donotextendjavalangerror), [DoNotExtendJavaLangThrowable](pmd_rules_java_errorprone.html#donotextendjavalangthrowable), [DontCallThreadRun](pmd_rules_java_multithreading.html#dontcallthreadrun), [DontImportJavaLang](pmd_rules_java_codestyle.html#dontimportjavalang), [DontUseFloatTypeForLoopIndices](pmd_rules_java_errorprone.html#dontusefloattypeforloopindices), [DoubleCheckedLocking](pmd_rules_java_multithreading.html#doublecheckedlocking), [DuplicateImports](pmd_rules_java_codestyle.html#duplicateimports), [EmptyCatchBlock](pmd_rules_java_errorprone.html#emptycatchblock), [EmptyFinalizer](pmd_rules_java_errorprone.html#emptyfinalizer), [EmptyFinallyBlock](pmd_rules_java_errorprone.html#emptyfinallyblock), [EmptyIfStmt](pmd_rules_java_errorprone.html#emptyifstmt), [EmptyInitializer](pmd_rules_java_errorprone.html#emptyinitializer), [EmptyStatementBlock](pmd_rules_java_errorprone.html#emptystatementblock), [EmptyStatementNotInLoop](pmd_rules_java_errorprone.html#emptystatementnotinloop), [EmptySwitchStatements](pmd_rules_java_errorprone.html#emptyswitchstatements), [EmptySynchronizedBlock](pmd_rules_java_errorprone.html#emptysynchronizedblock), [EmptyTryBlock](pmd_rules_java_errorprone.html#emptytryblock), [EmptyWhileStmt](pmd_rules_java_errorprone.html#emptywhilestmt), [EqualsNull](pmd_rules_java_errorprone.html#equalsnull), [ExtendsObject](pmd_rules_java_codestyle.html#extendsobject), [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic), [ForLoopCanBeForeach](pmd_rules_java_bestpractices.html#forloopcanbeforeach), [ForLoopShouldBeWhileLoop](pmd_rules_java_codestyle.html#forloopshouldbewhileloop), [FormalParameterNamingConventions](pmd_rules_java_codestyle.html#formalparameternamingconventions), [GenericsNaming](pmd_rules_java_codestyle.html#genericsnaming), [GuardLogStatement](pmd_rules_java_bestpractices.html#guardlogstatement), [IdempotentOperations](pmd_rules_java_errorprone.html#idempotentoperations), [IdenticalCatchBranches](pmd_rules_java_codestyle.html#identicalcatchbranches), [ImportFromSamePackage](pmd_rules_java_errorprone.html#importfromsamepackage), [InstantiationToGetClass](pmd_rules_java_errorprone.html#instantiationtogetclass), [JumbledIncrementer](pmd_rules_java_errorprone.html#jumbledincrementer), [LocalVariableNamingConventions](pmd_rules_java_codestyle.html#localvariablenamingconventions), [LogicInversion](pmd_rules_java_design.html#logicinversion), [LooseCoupling](pmd_rules_java_bestpractices.html#loosecoupling), [MethodNamingConventions](pmd_rules_java_codestyle.html#methodnamingconventions), [MisplacedNullCheck](pmd_rules_java_errorprone.html#misplacednullcheck), [MissingBreakInSwitch](pmd_rules_java_errorprone.html#missingbreakinswitch), [MissingOverride](pmd_rules_java_bestpractices.html#missingoverride), [MissingStaticMethodInNonInstantiatableClass](pmd_rules_java_errorprone.html#missingstaticmethodinnoninstantiatableclass), [NonCaseLabelInSwitchStatement](pmd_rules_java_errorprone.html#noncaselabelinswitchstatement), [NonStaticInitializer](pmd_rules_java_errorprone.html#nonstaticinitializer), [NonThreadSafeSingleton](pmd_rules_java_multithreading.html#nonthreadsafesingleton), [NoPackage](pmd_rules_java_codestyle.html#nopackage), [OneDeclarationPerLine](pmd_rules_java_bestpractices.html#onedeclarationperline), [OptimizableToArrayCall](pmd_rules_java_performance.html#optimizabletoarraycall), [OverrideBothEqualsAndHashcode](pmd_rules_java_errorprone.html#overridebothequalsandhashcode), [PackageCase](pmd_rules_java_codestyle.html#packagecase), [PositionLiteralsFirstInCaseInsensitiveComparisons](pmd_rules_java_bestpractices.html#positionliteralsfirstincaseinsensitivecomparisons), [PositionLiteralsFirstInComparisons](pmd_rules_java_bestpractices.html#positionliteralsfirstincomparisons), [PreserveStackTrace](pmd_rules_java_bestpractices.html#preservestacktrace), [ProperCloneImplementation](pmd_rules_java_errorprone.html#propercloneimplementation), [ProperLogger](pmd_rules_java_errorprone.html#properlogger), [ReturnEmptyArrayRatherThanNull](pmd_rules_java_errorprone.html#returnemptyarrayratherthannull), [ReturnFromFinallyBlock](pmd_rules_java_errorprone.html#returnfromfinallyblock), [SimplifiedTernary](pmd_rules_java_design.html#simplifiedternary), [SimplifyBooleanReturns](pmd_rules_java_design.html#simplifybooleanreturns), [SimplifyConditional](pmd_rules_java_design.html#simplifyconditional), [SingleMethodSingleton](pmd_rules_java_errorprone.html#singlemethodsingleton), [SingletonClassReturningNewInstance](pmd_rules_java_errorprone.html#singletonclassreturningnewinstance), [SingularField](pmd_rules_java_design.html#singularfield), [SuspiciousEqualsMethodName](pmd_rules_java_errorprone.html#suspiciousequalsmethodname), [SuspiciousHashcodeMethodName](pmd_rules_java_errorprone.html#suspicioushashcodemethodname), [SuspiciousOctalEscape](pmd_rules_java_errorprone.html#suspiciousoctalescape), [SwitchStmtsShouldHaveDefault](pmd_rules_java_bestpractices.html#switchstmtsshouldhavedefault), [UncommentedEmptyConstructor](pmd_rules_java_documentation.html#uncommentedemptyconstructor), [UncommentedEmptyMethodBody](pmd_rules_java_documentation.html#uncommentedemptymethodbody), [UnconditionalIfStatement](pmd_rules_java_errorprone.html#unconditionalifstatement), [UnnecessaryAnnotationValueElement](pmd_rules_java_codestyle.html#unnecessaryannotationvalueelement), [UnnecessaryConstructor](pmd_rules_java_codestyle.html#unnecessaryconstructor), [UnnecessaryConversionTemporary](pmd_rules_java_errorprone.html#unnecessaryconversiontemporary), [UnnecessaryFullyQualifiedName](pmd_rules_java_codestyle.html#unnecessaryfullyqualifiedname), [UnnecessaryLocalBeforeReturn](pmd_rules_java_codestyle.html#unnecessarylocalbeforereturn), [UnnecessaryModifier](pmd_rules_java_codestyle.html#unnecessarymodifier), [UnnecessaryReturn](pmd_rules_java_codestyle.html#unnecessaryreturn), [UnsynchronizedStaticDateFormatter](pmd_rules_java_multithreading.html#unsynchronizedstaticdateformatter), [UnusedFormalParameter](pmd_rules_java_bestpractices.html#unusedformalparameter), [UnusedImports](pmd_rules_java_bestpractices.html#unusedimports), [UnusedLocalVariable](pmd_rules_java_bestpractices.html#unusedlocalvariable), [UnusedNullCheckInEquals](pmd_rules_java_errorprone.html#unusednullcheckinequals), [UnusedPrivateField](pmd_rules_java_bestpractices.html#unusedprivatefield), [UnusedPrivateMethod](pmd_rules_java_bestpractices.html#unusedprivatemethod), [UseAssertEqualsInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertequalsinsteadofasserttrue), [UseAssertNullInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertnullinsteadofasserttrue), [UseAssertSameInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertsameinsteadofasserttrue), [UseAssertTrueInsteadOfAssertEquals](pmd_rules_java_bestpractices.html#useasserttrueinsteadofassertequals), [UseCollectionIsEmpty](pmd_rules_java_bestpractices.html#usecollectionisempty), [UseEqualsToCompareStrings](pmd_rules_java_errorprone.html#useequalstocomparestrings), [UselessOperationOnImmutable](pmd_rules_java_errorprone.html#uselessoperationonimmutable), [UselessOverridingMethod](pmd_rules_java_design.html#uselessoverridingmethod), [UselessParentheses](pmd_rules_java_codestyle.html#uselessparentheses), [UselessQualifiedThis](pmd_rules_java_codestyle.html#uselessqualifiedthis), [UseLocaleWithCaseConversions](pmd_rules_java_errorprone.html#uselocalewithcaseconversions), [UseNotifyAllInsteadOfNotify](pmd_rules_java_multithreading.html#usenotifyallinsteadofnotify), [UseUtilityClass](pmd_rules_java_design.html#useutilityclass) + [AbstractClassWithoutAnyMethod](pmd_rules_java_design.html#abstractclasswithoutanymethod), [AssignmentInOperand](pmd_rules_java_errorprone.html#assignmentinoperand), [AssignmentToNonFinalStatic](pmd_rules_java_errorprone.html#assignmenttononfinalstatic), [AvoidAccessibilityAlteration](pmd_rules_java_errorprone.html#avoidaccessibilityalteration), [AvoidBranchingStatementAsLastInLoop](pmd_rules_java_errorprone.html#avoidbranchingstatementaslastinloop), [AvoidCatchingThrowable](pmd_rules_java_errorprone.html#avoidcatchingthrowable), [AvoidDecimalLiteralsInBigDecimalConstructor](pmd_rules_java_errorprone.html#avoiddecimalliteralsinbigdecimalconstructor), [AvoidDollarSigns](pmd_rules_java_codestyle.html#avoiddollarsigns), [AvoidInstanceofChecksInCatchClause](pmd_rules_java_errorprone.html#avoidinstanceofchecksincatchclause), [AvoidMultipleUnaryOperators](pmd_rules_java_errorprone.html#avoidmultipleunaryoperators), [AvoidProtectedFieldInFinalClass](pmd_rules_java_codestyle.html#avoidprotectedfieldinfinalclass), [AvoidProtectedMethodInFinalClassNotExtending](pmd_rules_java_codestyle.html#avoidprotectedmethodinfinalclassnotextending), [AvoidStringBufferField](pmd_rules_java_bestpractices.html#avoidstringbufferfield), [AvoidThreadGroup](pmd_rules_java_multithreading.html#avoidthreadgroup), [AvoidUsingHardCodedIP](pmd_rules_java_bestpractices.html#avoidusinghardcodedip), [AvoidUsingOctalValues](pmd_rules_java_errorprone.html#avoidusingoctalvalues), [AvoidUsingVolatile](pmd_rules_java_multithreading.html#avoidusingvolatile), [BadComparison](pmd_rules_java_errorprone.html#badcomparison), [BigIntegerInstantiation](pmd_rules_java_performance.html#bigintegerinstantiation), [BooleanInstantiation](pmd_rules_java_performance.html#booleaninstantiation), [BrokenNullCheck](pmd_rules_java_errorprone.html#brokennullcheck), [CheckResultSet](pmd_rules_java_bestpractices.html#checkresultset), [CheckSkipResult](pmd_rules_java_errorprone.html#checkskipresult), [ClassCastExceptionWithToArray](pmd_rules_java_errorprone.html#classcastexceptionwithtoarray), [ClassNamingConventions](pmd_rules_java_codestyle.html#classnamingconventions), [ClassWithOnlyPrivateConstructorsShouldBeFinal](pmd_rules_java_design.html#classwithonlyprivateconstructorsshouldbefinal), [CloneMethodMustBePublic](pmd_rules_java_errorprone.html#clonemethodmustbepublic), [CloneMethodMustImplementCloneable](pmd_rules_java_errorprone.html#clonemethodmustimplementcloneable), [CloneMethodReturnTypeMustMatchClassName](pmd_rules_java_errorprone.html#clonemethodreturntypemustmatchclassname), [CloneThrowsCloneNotSupportedException](pmd_rules_java_errorprone.html#clonethrowsclonenotsupportedexception), [CloseResource](pmd_rules_java_errorprone.html#closeresource), [CompareObjectsWithEquals](pmd_rules_java_errorprone.html#compareobjectswithequals), [ConstantsInInterface](pmd_rules_java_bestpractices.html#constantsininterface), [ControlStatementBraces](pmd_rules_java_codestyle.html#controlstatementbraces), [DefaultLabelNotLastInSwitchStmt](pmd_rules_java_bestpractices.html#defaultlabelnotlastinswitchstmt), [DoNotCallGarbageCollectionExplicitly](pmd_rules_java_errorprone.html#donotcallgarbagecollectionexplicitly), [DoNotExtendJavaLangError](pmd_rules_java_design.html#donotextendjavalangerror), [DoNotExtendJavaLangThrowable](pmd_rules_java_errorprone.html#donotextendjavalangthrowable), [DontCallThreadRun](pmd_rules_java_multithreading.html#dontcallthreadrun), [DontImportJavaLang](pmd_rules_java_codestyle.html#dontimportjavalang), [DontUseFloatTypeForLoopIndices](pmd_rules_java_errorprone.html#dontusefloattypeforloopindices), [DoubleCheckedLocking](pmd_rules_java_multithreading.html#doublecheckedlocking), [DuplicateImports](pmd_rules_java_codestyle.html#duplicateimports), [EmptyCatchBlock](pmd_rules_java_errorprone.html#emptycatchblock), [EmptyFinalizer](pmd_rules_java_errorprone.html#emptyfinalizer), [EmptyFinallyBlock](pmd_rules_java_errorprone.html#emptyfinallyblock), [EmptyIfStmt](pmd_rules_java_errorprone.html#emptyifstmt), [EmptyInitializer](pmd_rules_java_errorprone.html#emptyinitializer), [EmptyStatementBlock](pmd_rules_java_errorprone.html#emptystatementblock), [EmptyStatementNotInLoop](pmd_rules_java_errorprone.html#emptystatementnotinloop), [EmptySwitchStatements](pmd_rules_java_errorprone.html#emptyswitchstatements), [EmptySynchronizedBlock](pmd_rules_java_errorprone.html#emptysynchronizedblock), [EmptyTryBlock](pmd_rules_java_errorprone.html#emptytryblock), [EmptyWhileStmt](pmd_rules_java_errorprone.html#emptywhilestmt), [EqualsNull](pmd_rules_java_errorprone.html#equalsnull), [ExtendsObject](pmd_rules_java_codestyle.html#extendsobject), [FinalFieldCouldBeStatic](pmd_rules_java_design.html#finalfieldcouldbestatic), [ForLoopCanBeForeach](pmd_rules_java_bestpractices.html#forloopcanbeforeach), [ForLoopShouldBeWhileLoop](pmd_rules_java_codestyle.html#forloopshouldbewhileloop), [FormalParameterNamingConventions](pmd_rules_java_codestyle.html#formalparameternamingconventions), [GenericsNaming](pmd_rules_java_codestyle.html#genericsnaming), [GuardLogStatement](pmd_rules_java_bestpractices.html#guardlogstatement), [IdempotentOperations](pmd_rules_java_errorprone.html#idempotentoperations), [IdenticalCatchBranches](pmd_rules_java_codestyle.html#identicalcatchbranches), [ImportFromSamePackage](pmd_rules_java_errorprone.html#importfromsamepackage), [InstantiationToGetClass](pmd_rules_java_errorprone.html#instantiationtogetclass), [JumbledIncrementer](pmd_rules_java_errorprone.html#jumbledincrementer), [LocalVariableNamingConventions](pmd_rules_java_codestyle.html#localvariablenamingconventions), [LogicInversion](pmd_rules_java_design.html#logicinversion), [LooseCoupling](pmd_rules_java_bestpractices.html#loosecoupling), [MethodNamingConventions](pmd_rules_java_codestyle.html#methodnamingconventions), [MisplacedNullCheck](pmd_rules_java_errorprone.html#misplacednullcheck), [MissingBreakInSwitch](pmd_rules_java_errorprone.html#missingbreakinswitch), [MissingOverride](pmd_rules_java_bestpractices.html#missingoverride), [MissingStaticMethodInNonInstantiatableClass](pmd_rules_java_errorprone.html#missingstaticmethodinnoninstantiatableclass), [NonCaseLabelInSwitchStatement](pmd_rules_java_errorprone.html#noncaselabelinswitchstatement), [NonStaticInitializer](pmd_rules_java_errorprone.html#nonstaticinitializer), [NonThreadSafeSingleton](pmd_rules_java_multithreading.html#nonthreadsafesingleton), [NoPackage](pmd_rules_java_codestyle.html#nopackage), [OneDeclarationPerLine](pmd_rules_java_bestpractices.html#onedeclarationperline), [OptimizableToArrayCall](pmd_rules_java_performance.html#optimizabletoarraycall), [OverrideBothEqualsAndHashcode](pmd_rules_java_errorprone.html#overridebothequalsandhashcode), [PackageCase](pmd_rules_java_codestyle.html#packagecase), [PositionLiteralsFirstInCaseInsensitiveComparisons](pmd_rules_java_bestpractices.html#positionliteralsfirstincaseinsensitivecomparisons), [PositionLiteralsFirstInComparisons](pmd_rules_java_bestpractices.html#positionliteralsfirstincomparisons), [PreserveStackTrace](pmd_rules_java_bestpractices.html#preservestacktrace), [ProperCloneImplementation](pmd_rules_java_errorprone.html#propercloneimplementation), [ProperLogger](pmd_rules_java_errorprone.html#properlogger), [ReturnEmptyArrayRatherThanNull](pmd_rules_java_errorprone.html#returnemptyarrayratherthannull), [ReturnFromFinallyBlock](pmd_rules_java_errorprone.html#returnfromfinallyblock), [SimplifiedTernary](pmd_rules_java_design.html#simplifiedternary), [SimplifyBooleanReturns](pmd_rules_java_design.html#simplifybooleanreturns), [SimplifyConditional](pmd_rules_java_design.html#simplifyconditional), [SingleMethodSingleton](pmd_rules_java_errorprone.html#singlemethodsingleton), [SingletonClassReturningNewInstance](pmd_rules_java_errorprone.html#singletonclassreturningnewinstance), [SingularField](pmd_rules_java_design.html#singularfield), [SuspiciousEqualsMethodName](pmd_rules_java_errorprone.html#suspiciousequalsmethodname), [SuspiciousHashcodeMethodName](pmd_rules_java_errorprone.html#suspicioushashcodemethodname), [SuspiciousOctalEscape](pmd_rules_java_errorprone.html#suspiciousoctalescape), [SwitchStmtsShouldHaveDefault](pmd_rules_java_bestpractices.html#switchstmtsshouldhavedefault), [UncommentedEmptyConstructor](pmd_rules_java_documentation.html#uncommentedemptyconstructor), [UncommentedEmptyMethodBody](pmd_rules_java_documentation.html#uncommentedemptymethodbody), [UnconditionalIfStatement](pmd_rules_java_errorprone.html#unconditionalifstatement), [UnnecessaryAnnotationValueElement](pmd_rules_java_codestyle.html#unnecessaryannotationvalueelement), [UnnecessaryConstructor](pmd_rules_java_codestyle.html#unnecessaryconstructor), [UnnecessaryConversionTemporary](pmd_rules_java_errorprone.html#unnecessaryconversiontemporary), [UnnecessaryFullyQualifiedName](pmd_rules_java_codestyle.html#unnecessaryfullyqualifiedname), [UnnecessaryLocalBeforeReturn](pmd_rules_java_codestyle.html#unnecessarylocalbeforereturn), [UnnecessaryModifier](pmd_rules_java_codestyle.html#unnecessarymodifier), [UnnecessaryReturn](pmd_rules_java_codestyle.html#unnecessaryreturn), [UnsynchronizedStaticFormatter](pmd_rules_java_multithreading.html#unsynchronizedstaticformatter), [UnusedFormalParameter](pmd_rules_java_bestpractices.html#unusedformalparameter), [UnusedImports](pmd_rules_java_bestpractices.html#unusedimports), [UnusedLocalVariable](pmd_rules_java_bestpractices.html#unusedlocalvariable), [UnusedNullCheckInEquals](pmd_rules_java_errorprone.html#unusednullcheckinequals), [UnusedPrivateField](pmd_rules_java_bestpractices.html#unusedprivatefield), [UnusedPrivateMethod](pmd_rules_java_bestpractices.html#unusedprivatemethod), [UseAssertEqualsInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertequalsinsteadofasserttrue), [UseAssertNullInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertnullinsteadofasserttrue), [UseAssertSameInsteadOfAssertTrue](pmd_rules_java_bestpractices.html#useassertsameinsteadofasserttrue), [UseAssertTrueInsteadOfAssertEquals](pmd_rules_java_bestpractices.html#useasserttrueinsteadofassertequals), [UseCollectionIsEmpty](pmd_rules_java_bestpractices.html#usecollectionisempty), [UseEqualsToCompareStrings](pmd_rules_java_errorprone.html#useequalstocomparestrings), [UselessOperationOnImmutable](pmd_rules_java_errorprone.html#uselessoperationonimmutable), [UselessOverridingMethod](pmd_rules_java_design.html#uselessoverridingmethod), [UselessParentheses](pmd_rules_java_codestyle.html#uselessparentheses), [UselessQualifiedThis](pmd_rules_java_codestyle.html#uselessqualifiedthis), [UseLocaleWithCaseConversions](pmd_rules_java_errorprone.html#uselocalewithcaseconversions), [UseNotifyAllInsteadOfNotify](pmd_rules_java_multithreading.html#usenotifyallinsteadofnotify), [UseUtilityClass](pmd_rules_java_design.html#useutilityclass) * Security Code Guidelines (`rulesets/java/sunsecure.xml`): diff --git a/docs/pages/pmd/rules/java/codestyle.md b/docs/pages/pmd/rules/java/codestyle.md index 45e9c7f000..1e267004bc 100644 --- a/docs/pages/pmd/rules/java/codestyle.md +++ b/docs/pages/pmd/rules/java/codestyle.md @@ -2527,11 +2527,15 @@ that are misplaced (not making groups of 3 digits) are reported. (: Filter out ignored field name :) [not(ancestor::VariableDeclarator[1][@Name = 'serialVersionUID'])] [ - some $num in tokenize(@Image, "[.dDfFlLeE+\-]") + some $num in tokenize(@Image, "[dDfFlLeE+\-]") satisfies not( - string-length($num) <= $acceptableDecimalLength - and not(contains($num,"_")) - or matches($num, "^[0-9]{1,3}(_[0-9]{3})*$") + ( contains($num, ".") + and string-length(substring-before($num, ".")) <= $acceptableDecimalLength + and string-length(substring-after($num, ".")) <= $acceptableDecimalLength + or string-length($num) <= $acceptableDecimalLength + ) + and not(contains($num,"_")) + or matches($num, "^[0-9]{1,3}(_[0-9]{3})*(\.([0-9]{3}_)*[0-9]{1,3})?$") ) ] ``` diff --git a/docs/pages/pmd/rules/plsql.md b/docs/pages/pmd/rules/plsql.md index 151a6cdf1b..ca067191d1 100644 --- a/docs/pages/pmd/rules/plsql.md +++ b/docs/pages/pmd/rules/plsql.md @@ -17,8 +17,10 @@ folder: pmd/rules {% include callout.html content="Rules which enforce a specific coding style." %} +* [AvoidTabCharacter](pmd_rules_plsql_codestyle.html#avoidtabcharacter): This rule checks, that there are no tab characters ('\t') in the source file.It reports only the ... * [CodeFormat](pmd_rules_plsql_codestyle.html#codeformat): This rule verifies that the PLSQL code is properly formatted. The following checks are executed:S... * [ForLoopNaming](pmd_rules_plsql_codestyle.html#forloopnaming): In case you have loops please name the loop variables more meaningful. +* [LineLength](pmd_rules_plsql_codestyle.html#linelength): This rule checks for long lines. Please note that comments are not ignored.This rule is the PMD e... * [MisplacedPragma](pmd_rules_plsql_codestyle.html#misplacedpragma): Oracle states that the PRAQMA AUTONOMOUS_TRANSACTION must be in the declaration block,but the cod... ## Design diff --git a/docs/pages/pmd/rules/plsql/codestyle.md b/docs/pages/pmd/rules/plsql/codestyle.md index 195199aba7..949599d55b 100644 --- a/docs/pages/pmd/rules/plsql/codestyle.md +++ b/docs/pages/pmd/rules/plsql/codestyle.md @@ -5,10 +5,46 @@ permalink: pmd_rules_plsql_codestyle.html folder: pmd/rules/plsql sidebaractiveurl: /pmd_rules_plsql.html editmepath: ../pmd-plsql/src/main/resources/category/plsql/codestyle.xml -keywords: Code Style, CodeFormat, MisplacedPragma, ForLoopNaming +keywords: Code Style, AvoidTabCharacter, CodeFormat, MisplacedPragma, ForLoopNaming, LineLength language: PLSQL --- +## AvoidTabCharacter + +**Since:** PMD 6.13.0 + +**Priority:** Medium (3) + +This rule checks, that there are no tab characters (`\t`) in the source file. +It reports only the first occurrence per file. + +Using tab characters for indentation is not recommended, since this requires that every developer +uses the same tab with in their editor. + +This rule is the PMD equivalent of checkstyle's [FileTabCharacter](http://checkstyle.sourceforge.net/config_whitespace.html#FileTabCharacter) check. + +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codestyle.AvoidTabCharacterRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/AvoidTabCharacterRule.java) + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|eachLine|false|Whether to report each line with a tab character or only the first line|no| + +**Use this rule with the default properties by just referencing it:** +``` xml + +``` + +**Use this rule and customize it:** +``` xml + + + + + +``` + ## CodeFormat **Since:** PMD 6.9.0 @@ -170,6 +206,40 @@ END; ``` +## LineLength + +**Since:** PMD 6.13.0 + +**Priority:** Medium (3) + +This rule checks for long lines. Please note that comments are not ignored. + +This rule is the PMD equivalent of checkstyle's [LineLength](http://checkstyle.sourceforge.net/config_sizes.html#LineLength) check. + +**This rule is defined by the following Java class:** [net.sourceforge.pmd.lang.plsql.rule.codestyle.LineLengthRule](https://github.com/pmd/pmd/blob/master/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/rule/codestyle/LineLengthRule.java) + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|maxLineLength|80|The maximum allowed line length|no| +|eachLine|false|Whether to report each line that is longer only the first line|no| + +**Use this rule with the default properties by just referencing it:** +``` xml + +``` + +**Use this rule and customize it:** +``` xml + + + + + + +``` + ## MisplacedPragma **Since:** PMD 5.5.2 diff --git a/docs/pages/pmd/rules/plsql/design.md b/docs/pages/pmd/rules/plsql/design.md index d44c48ce3b..b1f6ff27f7 100644 --- a/docs/pages/pmd/rules/plsql/design.md +++ b/docs/pages/pmd/rules/plsql/design.md @@ -706,22 +706,22 @@ have more fine grained objects. ( count(/descendant::ProgramUnit[ not ( - starts-with(@Image,'get') + starts-with(@Name,'get') or - starts-with(@Image,'set') + starts-with(@Name,'set') or - starts-with(@Image,'is') + starts-with(@Name,'is') ) ] ) + count(/descendant::TypeMethod[ not ( - starts-with(@Image,'get') + starts-with(@Name,'get') or - starts-with(@Image,'set') + starts-with(@Name,'set') or - starts-with(@Image,'is') + starts-with(@Name,'is') ) ] ) diff --git a/docs/pages/pmd/rules/plsql/errorprone.md b/docs/pages/pmd/rules/plsql/errorprone.md index 08504e4f2a..92385aacf9 100644 --- a/docs/pages/pmd/rules/plsql/errorprone.md +++ b/docs/pages/pmd/rules/plsql/errorprone.md @@ -19,13 +19,9 @@ TO_DATE(TO_CHAR(date-variable)) used to remove time component - use TRUNC(date-v **This rule is defined by the following XPath expression:** ``` xpath -//PrimaryExpression - [PrimaryPrefix/Name/@Image='TO_DATE'] - [count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1] - [.//PrimaryExpression - [PrimaryPrefix/Name/@Image='TO_CHAR'] - [count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1] - ] +//FunctionCall[@Image='TO_DATE'] + [count(Arguments/ArgumentList/Argument) = 1] + [Arguments/ArgumentList/Argument//FunctionCall[@Image='TO_CHAR']] ``` **Example(s):** @@ -61,7 +57,8 @@ TO_DATE without date format- use TO_DATE(expression, date-format) **This rule is defined by the following XPath expression:** ``` xpath -//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_DATE' and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 ] +//FunctionCall[@Image='TO_DATE'] + [count(Arguments/ArgumentList/Argument) = 1] ``` **Example(s):** @@ -110,7 +107,8 @@ TO_TIMESTAMP without date format- use TO_TIMESTAMP(expression, date-format) **This rule is defined by the following XPath expression:** ``` xpath -//PrimaryExpression[PrimaryPrefix/Name/@Image='TO_TIMESTAMP' and count(PrimarySuffix/Arguments/ArgumentList/Argument) = 1 ] +//FunctionCall[@Image='TO_TIMESTAMP'] + [count(Arguments/ArgumentList/Argument) = 1] ``` **Example(s):** From 916d55107c328cc27dde4522dc21345d143e9f61 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 18:49:51 +0100 Subject: [PATCH 89/99] [ci] Sign also snapshot builds to test the release signing key --- .travis/build-deploy.sh | 4 ++-- pom.xml | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis/build-deploy.sh b/.travis/build-deploy.sh index 1d470fe10f..8d26b44b08 100755 --- a/.travis/build-deploy.sh +++ b/.travis/build-deploy.sh @@ -71,10 +71,10 @@ elif travis_isPush; then echo -e "\n\n" log_info "This is a release build for tag ${TRAVIS_TAG}" echo -e "\n\n" - ./mvnw deploy -Possrh,pmd-release $MVN_BUILD_FLAGS + ./mvnw deploy -Possrh,sign,pmd-release $MVN_BUILD_FLAGS elif [[ "${VERSION}" == *-SNAPSHOT ]]; then log_info "This is a snapshot build" - ./mvnw deploy -Possrh $MVN_BUILD_FLAGS + ./mvnw deploy -Possrh,sign $MVN_BUILD_FLAGS push_docs else # other build. Can happen during release: the commit with a non snapshot version is built, but not from the tag. diff --git a/pom.xml b/pom.xml index c366d65a52..435db8201b 100644 --- a/pom.xml +++ b/pom.xml @@ -326,7 +326,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code maven-release-plugin 2.5.3 - pmd-release + pmd-release,sign true true true @@ -1017,6 +1017,9 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code https://pmd.github.io/pmd-${project.version} + + + sign From bb071d68e24ac1cad784af18b60ee1af0effb9c9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sat, 30 Mar 2019 18:56:59 +0100 Subject: [PATCH 90/99] [ci] Update release signing key --- .travis/secrets.tar.enc | Bin 10256 -> 20496 bytes .travis/setup-secrets.sh | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis/secrets.tar.enc b/.travis/secrets.tar.enc index af507713481ccf5f8882dceae4d8261ac4a2ed3a..7235c1212122bbc3cdf396a3a96ebb68d7f2720f 100644 GIT binary patch literal 20496 zcmV(zK<2-PFE@s!k|1qRuO53f#RMWGGTAPWr>&fj zPF|U7ILqpFY6B6@K>f2;9sG7e%Im9h70U z(n?2D!Z1Ge*pc(w((ne0aE$#Afp8dhTeK`dgF_meIPF1b1{H%bHogAT7{lv|9M6$i z1xo+3{+h^ZaN~w3>rK`moK|l(Qh-)k4YL4p0-sJowl20rqI?@7TL8 z6s&&QTuiqZ`KK(|^YL4?3PmQ%RKa|g$2Y&2+R0%VWn#wgKQRF42n9uO7UCpsMv2o# z)+SW=RRZU~WOX~A4UptQ5E_X8U#y-us%b`1KHV3~=2NKcnQ zou*xMfmg;M6tAt3LqhqBo)&-uy|WjG&UsRnz2w#8S>S0vdkiVENiyy{?5L~0WbuFy zo~KJ&$S-3N4>u(qiWm&5)XZ3q5~4_C!INh@>XQLqK5C-uS^O4agiGEyrBzI(YFByl ztWu;ZKHv|fcb(%kU{d=U3$_tef99q0;ZuNDK!(&AmK4o7qV;26m84I#ff_D!vdRmg z1#0UwT)*)fggSV9tD75c7t} zkeDb$6kaQi;%eS$C zb&MwtSY>O9a`I?#eI?g906|4j!VlbpKnn_BOj!9lV>zEqtZrgISOaax<+rEuCrH)p zlcy$Qr)mYs|50Roa!TkPJ}Jc$EF4#9C_}d_xSP~=8DMys$;T_gh`6f;^@IM&7b@@L zYwhk9(AkOOWbczpNyXqYnCGO$9l+Fk{>J-aYengkrob1B0EFzN6#jd#lZG%Bm_6e9 za|)&aAh-b&oYHhKwh8b6-q}(PXo>YUrH5Opg2iqn(_j{@OPAU9b&EnrJzetJR%Pwv3G-@}P}zkKK#PzYMI&lhqhrVG zK_6`v*&P5q<(NMzCrONXGWoEnkD>z~3fHL8FW@M7yaEkj4bioO9e$C#-afy80px2N z7WPT*KZ+uTLgYV%y6XNBPbqO9d8_D$=i{#Kd1#?j(O37P+b5;$2o>5=q(~{NX5CSy zYsUC@nf-t7L?QMtnqcL!b`#`M3oz5Y>F1BL`P%njNe?oL%qFi35O#ABgl-f~Rf1N6 z+1N`^t27nRfL^g*%)NZ?Az6G)fqIT8 zqOdlr3SD`2JD)zWs71F&8?8$88}9us<$~2jM}{9c55eiy+VByu$EkxN&n)8G&4edJ^SRi^R+C#h z0i>vI0FV}5u0kU5gAuuw^~Lq$``1Z9d(WM=XCkjpTdW!>*;BJs0`;Br3qG=z$Z1SM zJghzeK!Zj<Df!Z7v9)U+Mg-6W&&Vo@=& zv+OEPQj>f~ZSPc?=2D41+RE({4nj03ATH!Hs<;bn=kHu4K~5K4%4{LXX){S1lE2|b zAJI!S+e;?B89)_)nhGD{ zLS9$uJu(&zg?)f-afo89Ir3wFalTVJh`|5yD9_|dXWv0m(JY00!qt-wXw%_B{Un;x zTQ0|xLC#H1tXXgU&or2>-eUriCKJcg-_aH6g^Pj7&^o;9o}N=Zw>Kk;0B)@!Ob|pm znc+OQ2&%!@&ni@$a~R{mT>{cyv&q<<*+Ydny@#I+eW|_B_;#C~^a82>7@r`3y=1H~ z9bOQlI>9kWhO|EnBcM*XZoe60HUlQi12fOtSDCiww^Dhc0E+BxkNy^HS{4pF9ITr_ z`W%2?89hJG#Yah#YtOb-thW$sUD>B$BJ+F(V_tRyi-zP~5Joq;=rBE)2+xrvtfrqF zQjno^-kt3?S1QSGgRjV*RfWXWM4(>k`UJ0IL_n~r@9Mp@#I7y(v)V7uycOhchi#K8 z)GO`>v%5GI5IxnjCXQIgUnk@(nTwoE+>JRf2nYJGb@CnLKX`O8a%Q;BNXv|bx|`Ct z*6bvBiY*ejg)!Fe^dVUdC|Q_xr=?{U1Y5VS!UIsR*kt5j{-$4!Pe50=oTZo8>imJp zlJQ$&hay6#mhcpr?Y-P;^z%WMDOVi5bJU*jxC8Ceq&K!S#J!)d3<1k1n#;QqTJOqO zaM|YoOrRD!zIn5?E;3Ng*al*tpz5+3#4_4cKBBOnw77iD>pTTrutLhP! z8EM%sN!VMMnLKR;M1sgj!YYFL-(#a;4ngvZ)Is<>RUr}&q$xJs{}3Lm=vNYPf} zdi2c_P>~m=b@L$L4`~aI*FdW1U^ve6weDs16O+D@ClX@b4$tEL&Ruo34Da_D8X&-Z zWkd?jC!i!^g-1zPLuUo@PfR1xTjijH$Hym0bz(hDF7#ht@Nu!1^!Qtx+oQi3kJG%B z7jj4?p-%o9yY0P=uW+1T230#4nx^$5nd}}Q$+NpmQl;~g1+suiweN0iSXz#0*6~Qa z?YuQi1V@KHvPmhW!;3_lNKGqRZwglG1ljew(ys>2tAJV{s3RE!+Z^DhG_q4Kg=K* zS2!fNc=~hYAXf^44!f}T1zyd6gm86%`wvd_uQCVi#j({V$lne9N z81UAEK8#3gWG~nJ)rW&JzLOjZJPvA0s}hba5{&goo9ITXOS9NNeYm<@mso@%W)h?M z<&@_RO{H&cBB)$6{NoCAc0h&z=e%c+nV!!Su zl9vB3NDHV%ipuCTZzyDL{OM5+xd|WvX(hR1Icg?dV`D&kPt515CeN)UQpkYt>Yj!z zpe>?gh6aVcZ8&J;1Gd{PlVw+`z@Gh0KCAtz5Xly3OWKBf*FF;1y9?+3Ht7?_GJPaK z!O4l|C)|8zMrkRNruyJJt7_Z&>XwMO( zR50S`zq@BPI7jScExnTGJ*e_(!Qc-g8 z|5e-F2|6*VYhhEMIiKRf<=KB%sN|$H1;$7v8b`#tK~w0a8+)D;pt*KSF(PYMQzP-J z3X+^vVPaT3uponoT~W)@ z*2t_>orMMRN{`B?nlH4<@Rz^8K5g`Kffi>O#apWFEqT`<77XoUFk?_)gd_Quu;~tP zKTBV}mA@pXFukXl%0ks)wRvu!utf*!#k6&sLUdOU7e#ozgS|tU7-WV%7HYH4Mx5W< z>&D~}lkch_aA>sTdU#4pvY%d|`)dZ4@K0f*mFap@!0}xL)W7aM+O0c6NQyIT=o-xR z*o*s%p~3I|X~s+?_+{L2fzOQilAj#JR|Es*{R(hD4&MB#dAHb!g7P6SxlD>g`6?<> zo~1a|^RUnY#$sHuaUKZH7cAmA_+sqUSoBp4_6Wmn4!d`NOK2ZqEhuyK=5a?!J-Bq` z1IK|Jhx_p*jHsAm8_NQXu_^Fgo+}FXq^OD8tz&%pi%2Iv-E%njik4S;Fk_W01PKYD zKiKg_RB>_do#pHbk8uQotsGk&UCSGSt5k~~jB4ok8=+_^Sg8`pUtx%A1nY%(L+l)x zg(9UrRM~&W=+h+&Z2kB3tP+l26*(Zf#lyldann){6^o*A{IA=3-~0ukz;nJZexx26 zA{#Y!T%7B`6CVO{pw0M<8afRHs~FdPsE*)|=4M7_+6V4c-Du;~YlZ)mU$+pMa*vfj z{}@*;JNurHTM(b_Ds$uK%)`&!^(S?~qE`?Mocq+p|19z5%%!(viHxK{p=V~IA^1Jr z=H;AeYI1paijMZ#!t#0N?jL!cA7}R?i6dU=-_tF!`f(-4*IRVB0d;PSlyU3!M?`QFH`T6j`82kDQugMS~X}yvbCnyLEqVz`M+b5S6Gz&-5x|dY4`Ja_#FY2 z-DQ$MM6sqrokH*CXPdo#63oO>^yMSu&9)k;z2=}JlPeGn02gFIm_24CpSFrL; zQ#7ho`p^mt#3f>hP6)IzueQqx#TyCs zM?oY~=B(7{YoC8mw^LgLxj(x^Ig}j4rwnL~bY(k9-WI|E$=kF+|Iga7vLG8P?eH*z zX{d4hP4IW+ibE|g7Pd<6rVmk`N zYyJ8WPb@96%57M|;1Cl0>OZ)+8tQ(y_9YHq6dgohrs30-{d)jc?D#FGaqwN=yBY2t z;=U<^m@L_Mlyq?v#}u)n<4qPrCo%L+bPwg9&t`Q-?zXjtV_lT_oKKSZN%k0`+#Ms6`j_q+L5&Edgf10NY$r-18_hOZ`?3PnQfJSa=kFpuE0!)J(|j~ds6sH^8y8g3 z0k5e&?xTENpdj}hn8bub1dZ24jb?p^nr>GOD={84OqJpyu3?J$iQW=eaA0dD!+DI6 z1!JV0LRA;R@}`<2qxzA8w!X-+sk61qLR2)~$ehF!xEFEtLm`qsK-nC9nDxYmyFGl< zaxcQ2{X5d_1V3|7^e!pto-^YUWI`CYFrm-)OO_&=9S3eu_c2egOL?^B!1Bm2Bb;1c zX@N%2WU)=sPEOWF?^P}u+9t=2-ga7d==lh|4Eo(+H#upVHO(d4``gPAp|WSv$*JRc>>tnl^YYbZ8yLq5_SjJ#Q3=<_cBa>3FP4y+cfEsuv;47^ z7aJ(JN>8C#R77jyr?%4NfFrX2?XJ*4u{;Bm+0piL;*0cMg|4VnC7T6)IFw@{W?%GL&8`|*I zE*XhtN7c_AAXOP>nEVGhJd>d(u8m&=IQ)G1eDYSRFV%yOD42btm!Xm%)Hout@nEHM zmit3!ic5ibdsEXdGvQ@`=1X=sf^+YMxIE>0vE*~_!uS~?;>i+j_p(XK$$M7is2c6d&)1qRFA@`M=F-YzH4>4@>o@g5)D z=MZLT5@D8^7QzDo7RZ(u1Vc8}nINSCKBv5>f!#*qJ)ipe&HE<>KzKzY**sqyU?o2k z!+Qk7lt|eHb5e+GvP{s2z1$G6X{ZLWBgzyeob4=rU&Z~r4ntH2BB2o|J*QTBz`_Zo zX0Li(XHA0-7IOtBF8Bx)``CHh;AmH9gn3W|v4eK7fcB(LbjTqJ+>T64@gR@D6FY*Ql z(p1;ts2a7oe4s$OmdM+${1D)?HYHeXJKZ(~v1=}@e9>Bvy!uhV1%FArl6Z|u-@v#e z)$$TD$cf;>%|d+BYxX(J3^FROF><|1AZ{G-rj24CD%6ce{+8cuj&0l-TQ*_&A!K=|y z`Q^p&(^$PKvUok9N|QVheB~hR5SR6uty4#bUj|dZKK_Z93rC`;d+55kI^p^V?K0iL>Bj8=aEd7kRodjz{&#)C`16kqsju>^g$|WGkKk z+qE2vuzJ`I67oPChjV0pYo{Hn4)qhm-U-wT?=I!Hfl7IeS#d*06$C(ScS0`5Fn&}t z)0w-wG?9cajwZ!a1PlEZjc=Ny>)#TDGmblXnyk~Uzfr|PSXpF;+wNkPo(5OmBI-%) ze(@ESNjNwBiwj?OGJeAa{7>(k-L+hjP_gI zcB|>}N3b-Dm!tx4$Gc11nTRpAq2M8go&HBL9();2T%7!O;TU((ML3J1a24B}{4M;yY` znYW31pWa3k2FH+;4K>lo+~wwk5NO+pHcyE6mc1%TGJuIag2Nhuh$gpZX#1?vj@#c4 zO5ct=Ny5?ncOEvcTP+y1d@@DkE#iqkCT|Ii2N0)z(x%X{6wmBdmukynAA>92%b%j5 zy*P3vaKaC-;Pv+S+VXyerAEMO=8|%`S}Zd=$SGW^IAc z5hU85=qas2Q1;hiQYJau;$p_FB&Li@6s0guf;Uk2t?jVkeqjm0%)sC9n0o}#$3J2L zw~5lb0U_jd2%WZ-!!G~#&g|+g%*_B!XF4(Kr>po?*rWfh0zYomBRmZxCIwG_8u>tv zCV4gTi{haQ8A3yjijPs9g++D-l9%H%KLc?w(D~b6l?wz)Q`-#^l|eQAKl6LQ%E$SS zP86SRnBNZN$dtuZBP}eBM6>IN5ri{xmAKtxd5h$DmwW?8)Z(G?Xtg*U)Sg@Q8Y>#0 zc)tqz1(QRSx3cNo6&DQ-09OV7V-S>~2`WioDTDm;N#~;G0P|;x;~Xc-+a|u!K^3 zc#)(D_M|n+--d%sN${C(@HyAK1?{X`*3PTH|}4&_v^I zwa-_(O9ug_j;+e2!@vqAl?hy;pRfSFZr?uK9gF*xiA|XF8tHd`UV-e%E=ZAwn1D~0 zzFog)ESL%8w(|zHzeAz-|F4o-?KtAR3AeW@b=ei+Mjr#{>q?>oh9txdn5=_B8aLS( zc)+jM&~U`tCh5Q_@@iu)o1VkiC*^8um5HYon>M^QogLEKBt6UWJqI68?dQ$=M;mT@ zaCJC-EydZSzNhiQH6xR>+|}76rh!QMx~(jg?hd`5;BcIv`(uEijaP`p_COl(uO7Ex zj;le)f6+Hsce;(Hhi@8cP2>(5;sR%-<`>#GeE$(XLlkN_n18Ped?ag@Z}+ZtJF6&a z8GxYBtMyTF_Qcl6FQz2z2nF-jG^kAz3_q0@Bcz-~6s{3TqF{Rz9A05@8}2x+1@-ba zP$|C6$^OxO9?3aPLqq}Z!tj=A6?!hKqR7gT7z{6qQooUl$-K2jgC&Gxl7`7|cK6Cb zBaPMplC|>{nQH+1{p?E8XfvQ3uk@`Av3J1@AE-g77EcEl zGY$zK8_MuI%%|@pwN2p&!5hz}?9*bX2FypgzhO$jg_NMF&>3zRw=KJVgs5{YsP-YN zhIie_Q+i`v+y_cU{Ato)4%0{h-z@x={Z?|PX-QL8J$JEY*SrOfBl+=>n0oUV1?NXO zDIV6WwsFb$g*`AG4>|?Zsgu{CPkDtTNlzd&Hv&a4YN1=@Gal>b_=yZ(VV~$s-hK|Z*0C%U3jcDk_jpz%;6BlcH1T@+3 zDOxGG&U+4?vxdAz=V1){!#g~d2+WO0jOKY6+#_;uoFv~VGGS$WNrHL?+VX^>mUCuL zb54;7`cX4#avNB^TIEd7sEUsLnQRu0que1Y$uuSszU= zTXo1;gybMgns<@Rqh@=C2k}}eH&=zL#1HIbRPGz*{4z40^nE=5OW%`5NT{!FY6MLz zUA6(}W5eH#2i{4`UlK|ZWXI;WWZJ9U&@eZzg*R-=g32%D8%^5)Gx>34`(B0pV~$alqfI74cPSN|L(e(KKrCh1|W+H%qjHE*g@wu+-pqA6xKfBSnnuuDp3o8 zsXvOJJFQ}wk}h4k!m@MjGib->LtlsU0fj&dZ!e#@LUB6D+30NPsD0@xc^r;4ULYD> zpAuXrkDwoK74e?n{l7ZuJD!8hm-D>&$;9TB%K&Pzt z8%F%$vbZS?l*kS(72?TH{@^K^K;lnqInuQ}mj+0o>f!R6WU4)IdYMi%4SUJwiw)^$ zd*+g|fG_{_uKYWG=>1jZnODB;m1U=;Yb0@KZ8OS97YN2~q~Nn~tBx^chI~xoiROAj zOn1C`1Vl`G=W0UZ3k4)KB;d9THG}_rfz$W@(>j=oJtM)e!&kgt)^(Cy$$)pAAD0cV ztu^f!#MFnwTl>i*FKGsB_4MH@U~seibW4veyX=U{+zO=q>#wNp0DT&wKh#B z3iUQB+tbJ9GJ#%iidp6iTCNV+DSOl9GbD_E83*mn<>#Hq6)!I0%t>-a7b@nfyN5{s zv317GnjEYac;>uh@)~uxt!HM47%#v09iUW8un238j(v5`$pQx-gT6 zY{bz-Po_~}3!yG|zhNZIlH^lhbp?yL=2-4n>hb&~(SaQASP0SZYv_JF&vy$_+rW>! zcUyCbm@^-X2z3$|{yDP-22#>17`8+HSEd`n(mHreewsbRmg;*9=%JCouepULP1D%= zshY8oEn`$y3HG7otc;J(D?=SAB~BdzG*v37!sh2%*l&$kKB=$Ju+c2UN4|xsib9k* zCqFe3$THql>ZAfGLaq6KY8EgE#v)Q;SR^b`&mLxLOkw8I3oqHt?X(35;HG{gU+PCB zqF*91SA>N(=X0GBaY92}W1KRM*oC__x!iDu0FheLqZj$-SKShxIkeP_5z- zC(?I~r&(C5j#0w`PYt&x9Qh{RpHeTG80a-y=+_I0g{Mxy`KlPW@C=tDK&gZdMpD{* zR=kGWT1J}_Yr4_(<@YWPVOvtv7zPIZIuP8>wV8(^f8?m(5gc^~ z74-Hr?9rcfC7?Rm8Vp$+Bb+o4scisHe@UV$b7YD&{p*;sAn!pT3q+8RNwCyIX!B1Q z)jy@H6;enNg7iX!TL)P<+gnKi9Av67pBmVyjbad#o$5~3V#(?C4bOtvp3Zn(#eyP* zB?D#V%G2M`vli$bm}3TNVHh^)vPmhwDj|bXEj_!lhRyw za(!IP4nk=HSZwGbUvdW3l9{1)C(7=*3>kjMrhF{KDsP~rkxv?m8M(hqu+Ar6aC^nr z+#Gq6_v6NhE-Z&nUomQOGp2~3U-u?J8zZy-tuPwT)#$JbOAByMsW!8NY~=+XP2M|< zN*pFC7j~?OFd+hTSb$9vo+3udSM4XXeBJ*fHqyxAs*@|_nffcb1HLo0NT3a|+~9sl z`HX_mF%}|gPD~@lE&sBBI;|&cOBquUI}rZ(Dut_S>k6$^$xcdPe`fDClhGIFvOcF- z@sI4RbdMW<+GP|L4iji3^di~!m$2!5pC`4#jnA(SFOd;&8kH?uDHp@dy;?LEryFfR zxetX4aUi$t)x7T^!AbmHv(`LStwzXIzqAq?Y-5)aIUmN~+~*|4XG}d9Mhj#Q;&kTT zFGfu*GaFf|nNW5fi;*1Vz?A!G+oGYDwyOTf#s|szzQ#)m&<3&Nx8(vO1B{~jl9xx7JLr)>F0+WnZ}x_zyT0u4ChoCo4nuD4Jl z5oT4U_L~H{MG*6V%TswktSj7%4VUN$jxPJ({93o)ANGhQ>Qdu#2nVAz8N%ksUSsUa z94YJ7<;J6_i;YQ|G9s+!}uZbpq0I5t*R zk1XXp! zaT=`UDhbzZUY>;;M0O8{9u(2O+x(u4Tx)8iaSKQ(KMX8}L%%%P#Fk+@%TyJ}a0qJA zq#ZQHb2M4k1Ss?;R-0_uhx$ zZb3PEH2KZ1-RR_>H1Tv057jVq)L?L6$FDY_h|V=4zT#Ni`DZW$#Encc5krnV$;M?% zX5B>hlkUT8yAElTPh>9}9B(y&ryv)eL$fC3AeE?-o6}GpG5>U#Q(F@mDSzAQyh+)ocXVYcrH98?B z2{&>|eYdfLo+m(mCSRP}cfht6^SD)Zg*;Sk+Pyji+sQb@4Eh$oj6kszgb`Hen`#qC zl?l;ga=os$8;U*J13zC6Ea+*OddkRdDXV&5laNHk{cfehJTOP{N~nY{RBf)RK)_$J zSH4a4cN@`j-^YZ2Uj1;WU2bPt+$`zY~ zL-Le>!Al5kNZGnF-}4gNCsx{&!<+(9|Lqu!g8KiQQnXyw)>NG1`rI)TexPRUS7XBfMj3z-)@!$J|8TnU2|o6j7ow?IXC8q^Y3Z{~S=Zh4P3IG6 zEyZ_!jk;e@mZ1WSY22dfCS2%|sLmmHF-W&|I$We;9iQY@VY`{bOLFB$XqlSgF?Nm! ziC8ZY&6Kf2o)|>7-MOS**>H&7O%osZn5>|FOSg5}~woYHj>?X6TFS}Xt)V=G06UY)LU24bEDHQFGlL|k|m;S>}C4Vr_OefLkY zkn{9n5@T7uhX6S-%q5u#{v!D5E`OX>Z*nLr!^oz|zOZ5mh7#b)5-ebUb06Aw5ou@F zalqZ`bh)x_#zY6Wgh$Ex^9oqU=Xr+DIXQa#o z^y;x4&{~-M^iY5Iv04me6C>)TH2)r?jFl)90_&Baym2(vQ9Y*C1>qU>qbLO1#(}$= z-k_t8?UXoEj9zPFtVyeAQJW6Joi#h#>(m zXebZ+Q)W@tS|;K#zQ?d+jh?$*3mG?qP1?I)$BP*~J7?_TEqsL5vc({{PMu^YP3yS9 z;(DD0psPOZ<*NU?bxP0LeX20|>GTSh#vbrwK^xTe>tU)}U+)db z_~DnGHB}(p9|&Q^%oX??#Hs^rh*CW8^I$7TL6c!Q&Qo|0e(D=cu4Xh`AEk>JiwsWzge7~ne1=2RTIk-IzRFf+ATmhm#RQs+U$?|(!Y3`LsF zqk`dW>}R4C zx*qEZKn-xvM{eR6;$H*;dSuvhld_$E1|^f%(Mm{C`5-ushkFiTL@W_CxC5HI@H(%t zKE_Xf=|IKEEJOukXMloa@H~C;Jfpj0&uSbHtU-(g#o==^=m0c-RCY*>&}}lA9G)V; z?uxpt(@Ao}*#D&c3FmreRN7yT+_22)A@oDn>UMf@iD3XNks<0I=o8;LjgU;U%QZm* z^zm3oTFzj>s;dKQ%<5o9vtzp^WG5QK*nJn8Q6cE}>LH9-q#NOXu2$M9bQG@)&$VIR@D6TIN*2 zbd66G=?O3y=1!#7?7{-4f8$F|S2U7ce%*HbX2zamV5&b1L00SWclWGuFCUBz4B^pO z`T+bEhd_1Y4Bn-CHqv&#{yZ7LQI&+kE}O`_9*cKQZu%rCUv-s}9m{P$vK%c?Wz~7k zr2n}lPsC{DV8g6&5dh9W_os`%WLQ1RIq=Z3+-}mbwOn@;>!VLd*7`&qy9??A`IQY; zk5K5%5Q*dS*BZ8OyPDV2sSfOl1${k}_TT(7c;6j=b`D~|Dq65`m_ zo0hs3&1breUOOr=!ff~vJ0zegnjiuYoU~c8K(Lb`C_uU8HBx4q`WM36hOm>~XIvBs z=LK!R1I=GoZ0~{aGGwXs7a|LND%2w#A&>ae6~A%iTA|&cBlr)rnqz%2Ar9K*;b!u5 zHfU7!S&mwPn(n5xDskRt3Cz#3!}Jii%1KuHf%NDk9Ry-^znwN?U!ZXDTHkR15oa(4tb zH(3(NSR*v|x>D;0y?`pTR-UOzjmQAq@WL+lXBWdIHse3o8W*quraG%Kbi;O=rFHQh z)}eW}a>-0`A`o)gZ{=gj#INY>Y-AXVAw2nN+40J^Fm`MXd-akz*+^ zhip}uf~mP2wF$SiEGZtSlMy{Bya;h+=o{`^4utALO%Tva4%6rFHkZ6iWl`cnzIhJO zeTmFOPcVAfg`&oW&7nRGMkzGHEE^|<| zl?}24z2LC>#V$@wu%cOTwdmzt>8rMY?x&lrI}A&U6hBo%kZpU+r}ht-PsXyd7|Foz zK;(ZATfJ^72c&J&q&!ctt{XZgW=+G->P4hUYK}CY*~~hfeRGF~T!<+$kk4 zS{kQaymnRyG=B9M=RrNlBFfTtd^kL$7%iu?ueCDk+CYNVd>OjT17AK%s{X_%TQN4f zji`qakG|m0)xjM!Uou!QU$SJ7naw-gsS3!-T&)aEA#mY$3@XL5+SL_F8N&yY`0R1j z>cXDQ*pNKv5h`I&+BwifX)_(RH}|`X$1!Q3Y2WY3hrVUq!wrzs1uWMs8rg-6=$|Ir zaz~yb^wM6(Y5(xpyC%mO42Lt$A+hL^s%Qg0U(Y?uAS4PcTw4 z4PZUNYp>axtR%1%U4aG&mKP{h!m+8iqdzIS`~XJHj&$1vr&V6A4t*qtnSzB@fj;ls z?`B%D0q3+p)Lf(+7O3MIC5d@EpHwz6FzL*6`~L(mzv%afl)_tdn4RN=d&=s2x2&?+ zP)T_y4Q_Rm!iU*6v4o;eSgT$+oQa^t0EQaV27;{vx{`TGV0=-uVat*&P>TfHm+bzC zX4kAXh#6Mjl^e4hMhQwf3AHM6xXDR3s>xxVJPnJ->^#I)ueCND&0jg3q=L;GK0|dx zQVrbQEYuUlj7=~zBp-ciIKdMQ4k{|ozYY;MP`}DWEQ%B;;u#H@5*O)K&e2^kIspv@ znrLr#PEUT5BN&UnatdEhInJG@k1{W}uiN!8r0eM=tIG`6VA{4uH0R~H9R!CziFjB}`9C5*ehb&9YAh23ejpWI9;6DD1zI=DE%W88 zdd^8>Omw?^xeIn+u`#p{(h;etKb&5Hj54utS^_j=u}QR^*ZA7AW5(}~Zu@z%AAELv zWM`w`E67Vb6x*}R{KQt1s=4&YDNgJv1YMpvl}}H6W%`_$cr81RJW(0f4=3CY>z|Ip zA;ylr?Xv#9Fc(IUwKC6KvQw)GelbT8Uhfa~$?m|7uo=m^WoDCUB4}%|&GV$=q}lY3 z6Z^rdvX2fdaft{yop_-xgW{i;%-vdF5AermS9@s-UIwwF_Ct~Y$lI4X8>rzcT;raK zA5r%hI{dT-e9KD)jru>A$R|l3y56%=dI~8;4B*r-;eV)Q!M^RQx zrT9eu`6EIRi)6VFErA!&m}^_w8a*y6`xjmv;`2sls=(EXh&I1CNU&Q9WzdK(bE7BR zENcf_2Btv zDOS3s40Gd0>wNh`E2<8TFyMw_eoFQ9Ce-_f9e9RYM z8=g2!gw+!*KUmwjq=~K@CdZogT;oe0$!@F0te=mE3MrgvMLaNHkKc+Tp;Im8x(|NP zp%p%o@$tlLQG@Y3iKQT5!*Vj19AsbtHj9#RQTG~3wPbtdyZ)Bg`nno16a>|fs_z{E zCanPVIh9D#?m;!gVPTdZxq8(6A7*mOM=s+iU;VAW9x7{e=0%7yy@|;}O|lDAAD-Xw z~JCy?n5Q=bAIr?a3u`+m>Q@npCT zjlYwA%G*i@{#?>-loSXt&3+j$6wA8`!^p=ZUslVA@f|w9A$7X19fa?m8e5+7Mk4SG zqYY55fxyq4mf1YbmUM_01!ul_B}6OUAgtU|S&0_FmLjX)>bIf{( zHq6`ipojloaZXUgMm6c%2F!8WMkV<4)#w6&88gU6PLfxUC0S1t;@Q}0{74NvJDLTI zMg;}i;|*37(mGkLfJGsbOpDGfCqJ8@!H>k}ccg0OF(8*+A0`ZqOp#c7z(hCCz5Ex` ze9ZFJv0mJ+nX2`yYsYw+*cZRam1MvboBN+k3b0%SHJ18&=j(_4=;r(tQg|O`U#3=+oA%Xr$CvKG3{sVB)%l;%_Kx*48hhll&OtG)Vgi|IIq*=B7(Z`B0 zy!vf-_jHtCucyLUavq}(!;9L9s;3=k$=h`b_kS8Cy3;c@^&kSiIX}C ze-n=~bKZsm=irMvIdjB)Ra#GQY|Fz9nfkE88lhHgdn6YazDm5h*0$R;=1k&#sX0(3_n@*nny(lLjid%?l0rw9G@QS~-RtyuAEA2cA zskN&H@q2E-Ccv_^co=<|_{-AuO|*5Lzd2S;h-N@9e$Ya!N2U_7`i z{uHRP%bvH!NUjAF0?!&64};_&r4Jz^`5JMkX9UVBJM;0qfKOiVZk_SD@n3C$QgDHT^vl;5BLq@sy~2`7S9i4dFo?vxJWPlt z91jzscCw8`QTeVLU*dA8jrYqjD=9a25z<-Eq+Y?B zlr=TFH&*9ba{0H92YE{v{E0P)EB@mZ@DfR`7oqW@#2KaM=&VkVPREh}XB^)yiP9S# z0B40&y7PY6=qho_V7Nw~3PUULoX*=eGZc(x%WYHWN&HXq)a%yTMdmbk`R=1(Nxq_> z)M}iB`^fMZ&%l<0CfZq`5MrQp1ATo9@bc4=v?Q5{iGn?oE;3a9yu?i8{QiW=(lhh! zr6>0gqJ3r*s{kU2)6(4~cg`6O0Pp29GwQN}u;_3v*~fFe(BoPlC)2bt3j9WUfN6!) ziVUmnVFoqI$8eVTW`0l$++=^V)p&jnA*QJ_5=#oz)Kam850yDYUPzON&*n<5rfGi2 zT0cJS33z;-B}#+#I}=JbIUbRzU>qKA0F;G2PPL?svj7Sx#Tx<*cZjn@(Q_&Ohmt*%m+bEaIn+D>X^Ks>wp5DKi&bUCZptaye5TLpqTWfA^*%@^V0>FsWQ&naG zPXtBnK?f-?=B>u%+#gSIWS(+iHnEt=MChv){iS!VLh_2;#lAo?FxtBMe?kL_jVPqb zoZHA{cJJ9IzBaAz$)ZjbN04IM12n`p$%+O>GSbMcrPqMu4Zkz0FydTGojRQFT}TiWb$jc`s64RRuW+ zs*57XnB1wJN<%wbB0<~sa{7T5V&+DRVd&Qhi*M%dQQ6?ivOXi3`((WcYxMqT5At1z?qOW@EQAbK7*}f#4mVHq zNkKJVdCnz7y*o^EdikOrxj+89sb zjDus-{Mw6IZ2tHnDUH<1#sYWoPB zJFa}xG?hXq&1`OLgx|AlHXJo^-?tM!JG(|pkVM0V_;98rHrQaHS-Z!fwP*tQpajo3 z^MKbFavbW_+V)OJBu{uXgF;aFqYv<`0DjMJqnCfM!YJWwOk!;7P&COJtj>H!u~kh| z{8az~*UBj2q1_dFWFZYPw-{XHagLtn8zRI1=>y+4l?_Bq2FIgC(DX>E=;johUH`p)iTMAOw z$BN$ZifnI5GE^$ea=%`G&Z!yc8lc|nlj&tC+?sc06Zolpi~r)_P~+M$cSU$bLGtGi ze>mH=27}%{Om@v}&|d22#b3=-s*wf;RxZrQ3bN?;?~CiAlcO>}{gt;lPW-A3IQE#2 zv)?Vpnt*i>B|&8QoD7*O;kMl;v6KelW@3i`=06TZL;iua=z~LyXNs00>6-tB@0-&A z8$~`haHMiG?-K0|p_7?hn0}sQXUYn9#dRK{!m)2+gZkA`Z7h1X_bo)Sp+&eRy zAairJj%DP{Kha1NL#qC>)?PKT5+MG9Ku_w=Qo2SjfochZ7!CiYWS`~mb032C$`{z02&jzs?bhLiavwDa)#L;B({~)IW3gSML9Vp!N#R zCO-dBi7L6{1&@R zI8|gqqvQb0OM@VA+$_JtbR}0foy}w4(j^5uLODUmaRo94HfP>Z@OYkkxs0Hv2X9AL zQYC-qEST!4;q1w@!$Bq*VVUgesR2@7{_0b5Vd(VHgF2JRSkHArwqnP8eE6LE_=h9{ z@p*oU`4_i>3u-rIZKzAUB?h^p!R zn*|Rr(r?xDSEzVC%4S`Y?um-a`0)=a{5P^ww@I?Bc;`)irPBFkQ7arnd76(dDQFT` zDF6xBt>g|14(i8C^035OfU|5s%~uw%8cmZxt8IVQ6QC}f`( zXF5Rk)w}|~ZNGN}fQNuU_R87G2->LaLZAd$teLTMJ<~=e5I}HnPQRR3ozcCl_u)qH zzTzWnn2l|c;zU~(YDm9vQ1TCX=$>X$%uuqRd$|83edih-J|KtG>zn=>bV~&02L4>j zjuR%IZ7Wla?ZA!I;Ljeu9aGDA9@B%XL@4ImhsTUw6%znYVYkK6^;B)7iRLaE=OR$t^0Ix958? z`q(XW&pIlyn-8ADW*!Bje;x1F{ryiMhI^G&9n6jiGyGgNka5^yDmm;!%|Whv&K&vMc)9dyI$B|_|fWa>!|R~rpVadF3LCjw|uIOx(s{EXyOHAOI6`MRw7(o9#XPl6X%8-DCC3S=CwqDLSb zf2{HeV^>qLZJIy`0A}Y*Fz+|LR_7ufIMk;^%^DD|En6rJDhD6f!*!JYQh&=%CXUHZ zf|ETTn%z*)LrjP0GY0+iNK?%&e;AY`Ye>F2i*!zhu!tUR|#TIExV$fS*Arc8JhDxHSU(CmT4zcItj~wb#ypakp!X$pP zrlFo3Y`Kps2nJAb*-t6jxf5~4H>OZWct=l7ZGq!s-QY9bMSd~|&cZ_;!lT8@tw?JN zN_%sGYI;jp4spjf7Y0pM!BQWnqK;ulp&zyL#Vn^y*%Cu*D|uN`P1W6lo)dSwftPwM z0hX61xgt=-4AOCd5o#$nK$|aa-DB?d%4|0DhzI1#m+)cMQKgt6|uvSY}i4 z{A#XM7gEppu&csgKWL9}GF0A?)+-+i(-K;Wu|j5&cZ75tTeB7FhJuCXs>s8ZXAejg z>yXb|lUJeF_ib4!_+gM%hu2VxNC0hRd>H9t`+MeIYV^u3{Qp`(X8o=62sj4! z0^{s}5HMNd`_lC5J&<|m+x}CLUOAm8I7+iIHIpGE3*aie-f_?Au9t^A?jebOE%d%L zOwAMue4KYrO@!z2#(^>fYKVU|;4(R*w02e};hn1ZXT>VqCzzIE?<~LB)|ALSnaj&N zxIkeqy|PFM8H&eD&oa%vFJCVLFKM|0ur~>0F^i(v01yWslmimA8kP?kPh0I`zGxuv z=?stOA5qRP`=BBX`PahE-N;v}bYRt8N>JmW$-B{m>9bpTZE!FczdHvf*?5_me(Ln zAghrhbo*hCkYI?c{0fPPG7g^>b@)}DL1)Z)x-E0I-?Nirx6p+kQfKVCS89Yt07&z& ziaFbGWe;S`lI^gC!irS%jt1bCq_7<#Kckd*8CjS@XX{ZiTb6QSam2~F_XI$YzP@Jm zqXF{*`nVa$B8*{1U~OBjB{dHrpYya_(w|%mKR|dyzt=7asfjc3IAuQl;7eD%kNj<& XHySC*i`zF@wLnKto-#Z3($C+B_DG|J literal 10256 zcmV+rDDT%tjTq`axc>9@iJ~rO(LorWlGnzEwWQA0y`8ewRO?Ox+@sSLvX?-|X|rcw zD+XHs{l+JR?xDWt>S+omJ|s47l$5z5-bAd(RGE>t>c(oBUK74Buc52zVON2O0OS-k z@znm@?m5%}Kyd+Zh_7%->j_Wy28u(i>No4^KTikGt52n@jcxt@Q0&j&;{4w$w4xaj zp0n9jW#$Z+k<=rpfmUyP-qgSz?@IimYt2phd=1J9jqJyp|}Go3#9SZ4XXq^!F+HYrZ4-IR*}ME z&zQuPP?8K8v_w;QO>T(QJX&{4-~yD@pBGMVH$fd2O_ZeQLR)g3q(2H;t2ELqcB&%Bc?)B zG7VAs-+;g$VXDKDrK^Yf_HY9^wc73lhpW7lZ$h3TZu0T?vx=oU$wY<8>XP{m$q-)qTJTW-|(CCvz2Eh)etRuQgW zP#VNptPorGz>=8Pkh0dkbfHh!Uf{fp@t6pB@$GMPJDK=D6mvi~5CBg4Z4li{-#i47 zDo9(lvVz`<6rU(%i{FJ|4#q3;??M-^bPTlvG_A6$5sMg+0M^F)DFAcVXc9|mi*c-v zh$t2EH8+f01MD;`?d8H`O^UpTXQcC&qH1t_uRNxxnpoaq?t(L{tSXz7614#CR_s?W=UY&g8_37u zWyA-QaNuGzmjT(hx*=H-)B@_ZM1+BBQJPoz2=zOE*zOzluJ$wi8aX-_)t;2|B%)Kk z_RMYvo0m^*lqBl;3@BVe4|yhONN8^HjYm>lr5zHxfn*=eU)S2{aO9jyOL9Vv`&J;3 z3pv20iYbAR^`I{y~GJ&WmEAw{E;%ciGmhFA{YTs}hYlMep@!5&~>dLD?_0 zLpY!v)|+kN&>bn+)6!k8Vg4rGT*GSLySij_u^l+6fF00Les}w$5hqj#+X{igmE6fI zlQX_ZQD)IUe1th^eC4~hArd)&K)vMQYD_fl@)+ybO(%tJL38$i8vX^r#M zICrI>&?0a;{C@m)iz=4DC5p`SBB0ZB*6V31`h&J-4T_(Nj6kG)5r4g*M^s%S;Zm~bE`kG?Al5U`jRT9S{pm7vb&5xox2=1BK zEtyJT;JP`)Ena#D5P1S36eE|6xig#Su- z6SJQMX`7$yo9*mhe9<3DBAJ#iHcSpvVgT)OCOlzsq1i}R%H%V5yw3C!(XXMufXqh% z-(ub^wI!KKv^uSm7IIdk)|SL<N5M)6^-ZD|Ok5Sb3 zR&&7Hhui_W^I0E$`mZv=7_kUcX04@dp%o6Dj^{0vjdUe-40O+L0vJ-7(2}Xsk=3s! z9WR4c_(s{3oU-r*EJ&PK#OJcxthn8S)`|%sZSytjovKa4P@5*^B*VYysQ6VT^6weq z57w>FcouZsqCeQggrNpvfRaWrMtH&LA=GpgNtq*frOIO3t{BMaXZ8&Ss&m%K)YbL( zjAJn!j1{8^YeWs52ADSbnk-BwNr*{I?6*-sewUB9SV}2J&Zs!Wng<(t!a@U&Jux0$@6XR2ibjq(=JHrx-?z zFnJBK{?(2MNeS0&n9YE;y_NOY3Mv}d`A~6I{`3KW^mJGR8nc_v5;{R%yz|@uG0cN= zvko|7hQ|kizP)_cq2KnG_#$XzhBT#5Cnsbtx{153?W-eD_HYw`8cFFXnLNGJf8iiA zJ=b3h!HJ+H$?~-KRaBE=oMs-)@6u-VFUn4}BR=$39@d$XxE7W1xcP%^dCLK>h0sz@ z2SooFZbyMehbH9aM7`$RGtY`RCt<}jzfY1zz`IjRXfQgx@((uTv2v%0XQ0K0W`D#C(x$Q0$ibR5WvwPr-nD{MqGW6Sva5&fT zNke!Jk*mEf7VVTH#zkNnIhnu|0M9AZ!t54W;fhA8L^B#`Ee?pT2jJ$!9AC?Rs8Ues zJN0pCQ-|Vg#Fb8r7!h-}L)_zC0-7Nwq=E@J{9Z#X;;kn?TQBRR1d-rC+r?xRimz0}K z&%KFifzAs)ImH=M-}~Z>LE@V&B_E4sghESFta&OffLYYSgeQgX?UG10OsXzDJu7h6 z>BU0u8%K!VT&?-+>BpY}aVFlKFo$3yR_TyHM>K{bSRuKAfGjwythpgAb%7A2%I zSmcjTrJaL z#)p&C)}t_yj=d!zyD|smzJwTzycnamPl0q)(mwz+00$El*x$xz`V5n_QD@@n)d;s! zrYjz9(YsK+YW}vsBs~P{iCG2Qe7+Unhn3H#Bj;gmALc&=di|cH`l*Fa$mT=8ztPhd zFn=qJ>Zo=;yKCgWAP8Qkz@n~$1va=HO{J zax#L-KwsBfdrzGttYmS06nD9>SNH+<(A_Fz@*P#f@^b&=Ail%(f*sW9-y;XLUDn5D zBM5Vop8J!Y?M1oJmEpT5TH&hJgr=;K2+YB{xhHhbCT|pn)mv=QzXJ!Ap zOp21mcF8}ZI`Vq(FZ5|U*{yY3Q5etJAb|PtQEhD3=GI%m-o*8)YKj$30=l>8afE%^ z4fO7aUu+RF>RBT0#+JtG3N%&kU+VkUL~g_-O`bW{&i$GC(>t{&9KE4qo& zC<62oV6tg{mP1kj8T^4wRHf#ZAcJ|KGi8}i7E zP}r_!b%BVKXmYcabf#(%l@Np+W$PqZ3W6{7t4?xf9& zWhn*b9QKX7dl2_+5f7xZ5n=%P!?e+ncyV>tb;Fcvkz*tL+LPolL$>;-C+?|q$uTGN z^Pk+k4z5h`D4lE5DKlIKY7cj||Uzlp}3KV4cg>;aO&Ol4=WDf^k&xD4^st)a8g zEDNa5b@E10Rb1ju+jI)nXvlj1w($)LSn36*H5K)g+GcbyJlubg!pB%e3gC$8?RPM1yIugx=UDp-D zN*i7rvNE9?MBdLoPVSsNT>(OQHz696V3?4T5m?}-(9fXoG(sn1=JN+|z5>Th+M6~J zn6I5rm&(y;(ET=xK@$&Wh?zsBiM*7NbT10XoPF>mx_BX8W;j}I4jdEIg;E)P92uu< zAw8x9K1UkGndN$fxU^lXTb+tLga+J@GJw)Ienv4C%|zggs7?8{%=4zS7275ovBg&8 zvt<_G6Wft{!dWIoZ4LLBk%sqi2cAtnc{@D({@C`qEG~M*w(pMJCc@}P=&E?k!WmW-(z690a3;#9kbkI13EY2)a){D>i;=t|icNNRW<+o^Kh+WWTlT!5`W^QZKm z@CkOaw&BSlWyGQrND`p^ugaf6Aa?52ywVzzo4&^q0ulySG;q~(+6qq-H($nLP-3nB z5rst0(=zCfVK7KyU-iT(TKvl&lTj`8(&nEO`)a!BcpeESfA5q*+f3vFCTnbuX#kbQ!k)W)|QX zWzFeiy>|V6CVR`L{W2^f1qV?6;^P*ccaJW>Xgp{wFp2V)Nq6y+0P^dI#D;{muDCAn zta;KikE#ecQWs|INAGUbsKlSIY%smU18uLC8<6fw#$3$7(56GNw-Y-kQ=|&u} zd&9uNF#iQgI#j(OvH!13_4l4JaJr4P&gy# zU&w0@6sbM(qN{i^P5FS^(ez&_ECwEF>>2lR;x5{AD8A04EDdWXsY~4ieN6*d^?Ge) zbC3DRwLHlzW35?yk}hHgHIR?Puf2APB%{6LAjp0YU*Klyz>2Dtaz56S$y`1=RJZtV zZ;syVV*P~oab}I|%B|(2vkuD^Z8 z+eXX!drGPTd0MYpqJv|F9_q^RId}>z>|;;7|I)SQdo4KM^^Dz8Ld8+3S&-?=>x0&T z(16-ijKqNd9Y#{nCh`nwl8CtRCA9irVIeU0KL#WgS_{v6QP@T|MN^;ZQ*4~2&Q?=d zxx1>G7l>zLzooHiwH<4BNg!gpM}R4NHKyE~FtVQ8IZ?`DANBj@3M=mbeSdh>)ek8b z%4#lIuZ<0IbPWfyNU#G2guj>v+6weKbdaNKl z)(QH+ceur3@~}36f*s<^mF;~g4OxC)J2m}WgPyKq0asuGRpF{LhkLiliIHLjOp_n( z0R-5p@iXD43hj_r4O`~wWrvoCHj!^UAFa!MpMnM_uNSa}Cd?te9W`r_vZ;rR7=|&- zKW~pZPISl;bllnikWtUPk}8%OIwe$!iQ=Lm!qh}UX0czZ#wjmX4bnKE%&<$>o4av; z#d|ePr!d`yEG7KP%UpWR624?MpvNW@rO^I??&g+@yCGjKd^!Vg59;4G(`VC*kpwy8 zRoamZ5&|CcBw<_e@atTG4wdm7i6zB;yVt@qc*h|PQ2h~r#g`u#k5e{4$}G%P54N;5 z0A|T?Q7MnQsPw~SsZm4bB`=d_+HczrLju-=oXoy&OxwRfOSOt#WnR%FvsHyb)C5i( zOnZ=S0?Bvocu^>w0@*3nUWDf1FE-iR??6>ed7gq*Sx_+;Sb0}G?<2!nz7oYx+0D}~ zvyJYGG=jEPz~FtNL9Ke*sTO&1$EiD^Pc#EHel^-+pLDVDRpQY^%9d$!I8oqrla}sM zU{^9PlIqt>E%LbSbXCoJt@H@Ef}E})S*ut9QQ=|1rYR09co|y=Yy)jGl$U((^d-X0 zS{Kp3uQJSCYH8#G=yu2=0bPkU;of%hZ%uf$Igl7(HirZR6L0|jfjQ94e$nU1hy>DN z$jklHlj;a?J$Nb7RtwFNLatDJDAee|x5x9CV^t~4>}TSJWF$3M(*rTlK2?+{n) z!R8)KIrhn-gv;?mjCX9uGGL#mtp#of3sN4oD_swfkaQO}Wx|5{hmc;G+)w|Jb73)O+)`YE(N_jR8D~Y-h#;+Hfs2ixi<*UI2arB;r$A z*QiSK8)d>VLG6NwnhFhCQ@H$KcTF6()7`Z`O~s8{7D5)pu;|iP7Jp6~8>9{KF1UPV zsic*8(IO``R@*E+1=OkD0BMex{&!r0o%)A7)HYI6Zl9C1HeTk@Od8OgbsctlVSXhm zj3m!##1hfHSulYBn;Iv4+luU_XmFVGLNQu7Uir{K%=@mX_>hu~@>wtz>Msu4E?F7? z@Ah)8+VJSc=gvt43h>V3+7Xf)&V-N*R7QiJ(+zgz(Ww_rxm(MA91*`PcQ;wAr)Tk& zFuv_}Tk(hIO*V5!n}F$!Qfh?8w%Y6&pmw#oqPAnr*D;}e7-B+D|wY3mqy`=8Q_S&#&i;LmtRG*G_SA>*y1LO<-5c0uK0J-o;CWL&OG;@?R z*HDDZisJ|t2+MlMEY`WYs6HVKd++j*b0F@W>-5Pl zpu1ob(;{(451@t;CZZVz=DL7#@m&QU?maC%(P}ORwo(;{HDq|0Wuh$1+<#Tx|F+Bp zJ^gO1pAXepf-;2-2`9Gt_|)^K0aYnqLwqGIz~mD`1?43=b(%#_pMoNVm3NLJ>y546 zM6-p=1^qkI!S5EMP*Y)$k7{Oo?GH#3!=v|duka)HL{;zOj&|XVhAb|TV$WB~&RzSx zf5u8)%u2@ivrmOO5jID9P2Wh-7;EOPhR3EhS&W@i$fnF6-Tzq9$bG3#s?dL61tV?_ zkaM}Xm5t>aKh}_yg)04fylNY*JxVNKFRVP_PLECaGj9#6@E(L%Wv*o`2G)@N>)$TYCd4N7}8hi(BZ1hn&mHR}|Vzynz#5tvOcD zDfGLBjBX0W+cE(9X5q`TbBWDEbe5qm`#Uf>j}s4$@MxJ*7dcq^XE*YOPJn_ID_dxb!iNhxI=+732V|>i_+kK(hsw_x|R@p zn<3zthhnH<^8a(7Tk4zXP}#(l8*PbpKfk{oT{V6l;#4A;Aak##iA#Q`#>)Px75O_J zD3zQS!PA-RREhs^Rk0UAcZ{)=3h6P_{ru84=KLQ2F!fry4Wr&C;fHrhpcQ z5MHE%<8y8u8wpn@V*^F;GQ!zVE5d$_-uI3IF$G(g>f>-rc~2jcov>u|LG^_r1_9Uj zo*p3+g}vEQDy$j_>K^eNXV;`Uu*lt-@QBeyi;wnC*iGse_N9StPG9bnDj&FuD&rUs zFdb2n(o8XBnT*NIUG5*Xt@#nUx367rlWgN=SFG{sM(O)pr|7_oXtl_O)n?RIp62X5 ztPPg1M@Lg|wL>Z^Nh9J2MqzE93TH3B>x5rx-prP+tsayKAR*)CF!%+VlrAlS)=5fy zIn~R4J0TswTP^$`Oq5Hz+-yM-5pvX}OqSxgWn_`;X4%^VROw-rO8T!D!ksCXPp{~_ z2%ko_U>3)cDmk_ZO!`*`ZqAHCHwObsODimd%ACJ|5dpaH92)K#FpNksS>D|#qMD`>x1rNaa4?=fw6N=GKgYt&hiG}wePZeX=_Xm zX0`{sE}}+{tTf50T7Z);VrUywYo|Y@KG+~^;U_gv!y7r`^ERrRXy0&(3c+n9zOUkK z8<~;)CJ$x%37w}8<9s4tK{bx&+wH~6Yg)Il0`B%Fu_-72qA`C9(vaoO`PEkX zkbtcs&vbsC5%%~CWbcwy6S${_`j$>hes5#S`H+5*XX0M;ERyfQJcs;-IKeTRtrCAJ z0}C9C9KJ%#Er?7jo;EiQSWRHTQbp3^f?D^SHcb7Q>&ISPFooTO$|EMaCgAhB4txi?auc{e_&O$@9=!eaV+l!Svv!!)j8t1{oqFA@%6#FWNPb-CY>OujrP) z3VJh|y(%9;b&p9*lNY07C0?sG0bLuVk~TIQ$aoVq66Q7zEYrq=-)Jg?AMWK&csMI- z`*P;n82?y|&s$=*@QuO$lX7#nyrgkM3KfPOVm1z52~NtyMD-C_he)|}heb6g(3g*eOU z4-wLpdoCY1R&0$GKaqqT@w6vw8jt1^vZiaZ{p@6_ zYl+P-k?spCE8~s1(py{me4U;Axn2@*0GzB>t$giy52>s_Y~~aeQ>+8J96Oz_xJR$-A(52v3TL3v}cSkQH3Lcps%&zlaigkn&{!@ z1m558lL_oz>IIuB1b%$VW7?G1wGAMw2T2x)#NgP~vT=?EYIZY}oZ5aSn58<7Q+Jcj zF}=f^k6qQeE=S#qdq8sQ&{r%=)fhtbbrd;GF-PypLkFa0B8CzPsb8$BHWW)9A zAYhSF$}b~W+YIrQN zJ8*%JHwGqq=?Y-}G$ccR#3bmvJpK@f&6g>459H)cqlt^`enwW(`N6+KF( zJtA3zJ)WO>dMH$I@yC}bP;r9RLdHf~PtIyh!rkyZn%P_o1+On}=$w&-Ytoq+!QPp$ z~>tjPYJ8)_wNchm+#ztjgVnjQT0PS2taP@=#qTpuY^(2(Iw7Kyw8%T z&;=sOTN&mVi_;98gp~;i##>Y+Xv&yJatl)Q0qm84bE{zkE;@dvcaHh=!cGGuEIj>N zM&zjql~(vq8b!oojD0_Tff6q>N1cbsf7yia1BZx(&LX2l$yD7r-ncO#di9#=w466T?RbC@Szp5rk2C9kv-4MJBM7VBpw#N8#+- z(n@0=ehIyvMk5=f7E=s`05B{jUB5E+W4+yds79NITr3$MG>!u%b^q}svqsPLqQF5J zt-kmAm|ryd@9FG}TVnd)a-u1kb{T$0t~b$T5o+q}b~Tj5joX%^5VZ)ymnl=DyD|ai zVUM}^3ABVWZ9o&FYx*^h!-yEql5MqxAQXq0k!mY_TNXJx++vag*71o(hj2Qz2k~>{#aTTmWs)Yh&w?%=7Lh$# zu4`NnnSrlX_)(Ve4>~|<-s1Zuv`zM3Xzf$gjUhp;_o;O2Cs7jgfA5Z@7949mqc6{| z^F~EEo9uHfJ$v=~f`%|Vl@km$sqx_;lZKdk;#-0P0+V4$YE$2Yb9EZsmi-)ykIS=9 z5XGJdRs&G!gI+$x#cimJJdWO=XJ9-H!m-C;e^ zS9V=Z)$6%U)-yr3Lc6Nk8!|nN9>HbcGMTcO#vw8ssISowI-@3$!rqVij;)?OwvKV@ zh`mDRs}HxQ8Tu}KF1V6p>7wp?IK}&DvKIh)4`iL=aEKj@eMCszuQQs7kTnUqWCOVl&@M|rMjHC=Q zluBuuU?~{M4h%5pHVD{k>!vN@XM<$AN2Qp1iZ{>rp!$(RC}gA6Kt-dWs@6T@Y)Pv_ zuO}G3aifIGr&M0r;YO#HVvda*cJMr$*?aBeAs@eKGm`^);|{W=wJ9A%s2CIAo39&b z4ib9S!|uD%CcBp?mn&0KmE~k{*Q&(kZ@5|F+Ab6($frTYVlH$lD7~O2YHIr&8`Ch^ zsado)p^OOE*$`L!@>KEy1^`YMi;j{;Xk${@Bk*#;v&clqJEF%0*30S_6h_&o>d}$R z-_aV$x*l$`PCb19?na0hN=&HOR=q2q^-V>_RAnK=5hB=20Wr90*P$cZ*@;^|K=t3uvva|>pc*yLS&;(H`W6swWhbrCrkE=Szgqre)0#hxD#R|q! z?!5ZHY3oaw8|J1Tj~&ZZMAFywFsa3*H*GTdq3YS}#)N`E*ROcdYLPV)Oh}s*^hS(+hS{%wSsU6{*Tk z)?_F3FhLHxspks5_7me>s$Bh!8@ Date: Sun, 31 Mar 2019 00:21:34 +0100 Subject: [PATCH 91/99] [java] Add SwitchLabeledRule interface, remove SwitchBlockGroup --- pmd-java/etc/grammar/Java.jjt | 51 ++++++++++--------- .../lang/java/ast/ASTSwitchBlockGroup.java | 42 --------------- .../lang/java/ast/ASTSwitchLabeledBlock.java | 21 ++++++++ .../java/ast/ASTSwitchLabeledExpression.java | 21 ++++++++ .../lang/java/ast/ASTSwitchLabeledRule.java | 11 ++++ .../ast/ASTSwitchLabeledThrowStatement.java | 21 ++++++++ .../java/ast/JavaParserDecoratedVisitor.java | 16 +++++- .../java/ast/JavaParserVisitorAdapter.java | 14 ++++- .../java/ast/JavaParserVisitorDecorator.java | 14 ++++- .../pmd/lang/java/rule/AbstractJavaRule.java | 14 ++++- .../typeresolution/ClassTypeResolver.java | 6 +-- .../pmd/lang/java/ast/Java12Test.java | 29 +++++------ .../lang/java/ast/SwitchExpressionTests.kt | 36 +++++-------- 13 files changed, 181 insertions(+), 115 deletions(-) delete mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledBlock.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledExpression.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java create mode 100644 pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledThrowStatement.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index db5f448aa2..53706c7156 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1,4 +1,7 @@ /** + * Add support for Java 12 switch expressions and switch rules. + * Andreas Dangel, Clément Fournier 03/2019 + *==================================================================== * Add support for Java 10 Local Variable Type Inference * See #743. In Java 10 mode, "var" as local variable type is handled special. * Andreas Dangel 04/2018 @@ -403,8 +406,6 @@ public class JavaParser { } } - private boolean inSwitchLabeledRuleGroup = true; - private void checkForBreakExpression() { if (jdkVersion < 12) { throwParseException("Expressions in break statements are only supported with Java 12"); @@ -2468,11 +2469,34 @@ void SwitchBlock() #void : {} { "{" - - (SwitchBlockGroup())* + ( + LOOKAHEAD(SwitchLabel() ":") (LOOKAHEAD(2) SwitchLabeledStatementGroup())* + | + (LOOKAHEAD(2) SwitchLabeledRule())* + ) "}" } +void SwitchLabeledRule() #void : +{checkForSwitchRules();} +{ + SwitchLabel() "->" + ( + ( Expression() ";" ) #SwitchLabeledExpression(2) + | + ( Block() ) #SwitchLabeledBlock(2) + | + ( ThrowStatement() ) #SwitchLabeledThrowStatement(2) + ) +} + +// For PMD 7, make this a real node to group the labels + statements +void SwitchLabeledStatementGroup() #void: +{} +{ + (LOOKAHEAD(2) SwitchLabel() ":")+ ( BlockStatement() )* +} + void SwitchLabel() : {} { @@ -2485,25 +2509,6 @@ void SwitchLabel() : { inSwitchLabel = false; } } -// only pushed if it's a new java12 switch label rule group, for compatibility -void SwitchBlockGroup() #SwitchBlockGroup(inSwitchLabeledRuleGroup): -{ - boolean prevInSwitchLabeledRuleGroup = inSwitchLabeledRuleGroup; - inSwitchLabeledRuleGroup = true; -} -{ - SwitchLabel() - ( "->" {checkForSwitchRules();} | ":" {inSwitchLabeledRuleGroup = false;}) - (LOOKAHEAD({!inSwitchLabeledRuleGroup}) - ( BlockStatement() )* - | ( Expression() ";" | Block () | ThrowStatement() ) - ) - { - jjtThis.setRule(inSwitchLabeledRuleGroup); - inSwitchLabeledRuleGroup = prevInSwitchLabeledRuleGroup; // restore - } -} - void IfStatement() : /* * The disambiguating algorithm of JavaCC automatically binds dangling diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java deleted file mode 100644 index 18c559771d..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchBlockGroup.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -/* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */ -/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ - -package net.sourceforge.pmd.lang.java.ast; - -public class ASTSwitchBlockGroup extends AbstractJavaNode { - private boolean rule; - - ASTSwitchBlockGroup(int id) { - super(id); - } - - ASTSwitchBlockGroup(JavaParser p, int id) { - super(p, id); - } - - @Override - public Object jjtAccept(JavaParserVisitor visitor, Object data) { - return visitor.visit(this, data); - } - - void setRule(boolean rule) { - this.rule = rule; - } - - /** - * Returns true if this group contains a switch label with a rule, such as - * a expression, a block, or a throw statement. - * - *

Since Java12. - * - * @return true if this is a java12 switch labeled rule group - */ - public boolean isRule() { - return rule; - } -} -/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledBlock.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledBlock.java new file mode 100644 index 0000000000..8ff927bef2 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledBlock.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +public class ASTSwitchLabeledBlock extends AbstractJavaNode implements ASTSwitchLabeledRule { + + ASTSwitchLabeledBlock(int id) { + super(id); + } + + ASTSwitchLabeledBlock(JavaParser p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledExpression.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledExpression.java new file mode 100644 index 0000000000..b2ba1b17a6 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledExpression.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +public class ASTSwitchLabeledExpression extends AbstractJavaNode implements ASTSwitchLabeledRule { + + ASTSwitchLabeledExpression(int id) { + super(id); + } + + ASTSwitchLabeledExpression(JavaParser p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java new file mode 100644 index 0000000000..60f827f78b --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledRule.java @@ -0,0 +1,11 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import net.sourceforge.pmd.lang.ast.Node; + +public interface ASTSwitchLabeledRule extends Node { + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledThrowStatement.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledThrowStatement.java new file mode 100644 index 0000000000..d0a863f967 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTSwitchLabeledThrowStatement.java @@ -0,0 +1,21 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +public class ASTSwitchLabeledThrowStatement extends AbstractJavaNode implements ASTSwitchLabeledRule { + + ASTSwitchLabeledThrowStatement(int id) { + super(id); + } + + ASTSwitchLabeledThrowStatement(JavaParser p, int id) { + super(p, id); + } + + @Override + public Object jjtAccept(JavaParserVisitor visitor, Object data) { + return visitor.visit(this, data); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java index 852f6dbdf9..e92a779c34 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserDecoratedVisitor.java @@ -870,13 +870,25 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor { } @Override - public Object visit(ASTSwitchBlockGroup node, Object data) { + public Object visit(ASTSwitchExpression node, Object data) { visitor.visit(node, data); return visit((JavaNode) node, data); } @Override - public Object visit(ASTSwitchExpression node, Object data) { + public Object visit(ASTSwitchLabeledBlock node, Object data) { + visitor.visit(node, data); + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledExpression node, Object data) { + visitor.visit(node, data); + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledThrowStatement node, Object data) { visitor.visit(node, data); return visit((JavaNode) node, data); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java index ef9b9675f6..6b4574d153 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorAdapter.java @@ -602,12 +602,22 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor { } @Override - public Object visit(ASTSwitchBlockGroup node, Object data) { + public Object visit(ASTSwitchExpression node, Object data) { return visit((JavaNode) node, data); } @Override - public Object visit(ASTSwitchExpression node, Object data) { + public Object visit(ASTSwitchLabeledBlock node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledExpression node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledThrowStatement node, Object data) { return visit((JavaNode) node, data); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java index abb2c5dd8d..71fccb55cd 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavaParserVisitorDecorator.java @@ -732,12 +732,22 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor } @Override - public Object visit(ASTSwitchBlockGroup node, Object data) { + public Object visit(ASTSwitchExpression node, Object data) { return visitor.visit(node, data); } @Override - public Object visit(ASTSwitchExpression node, Object data) { + public Object visit(ASTSwitchLabeledBlock node, Object data) { + return visitor.visit(node, data); + } + + @Override + public Object visit(ASTSwitchLabeledExpression node, Object data) { + return visitor.visit(node, data); + } + + @Override + public Object visit(ASTSwitchLabeledThrowStatement node, Object data) { return visitor.visit(node, data); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java index bd7bbcc5bc..72acf4dd27 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/AbstractJavaRule.java @@ -676,12 +676,22 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse } @Override - public Object visit(ASTSwitchBlockGroup node, Object data) { + public Object visit(ASTSwitchExpression node, Object data) { return visit((JavaNode) node, data); } @Override - public Object visit(ASTSwitchExpression node, Object data) { + public Object visit(ASTSwitchLabeledBlock node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledExpression node, Object data) { + return visit((JavaNode) node, data); + } + + @Override + public Object visit(ASTSwitchLabeledThrowStatement node, Object data) { return visit((JavaNode) node, data); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java index f4f5e1ae30..4883668d0a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/typeresolution/ClassTypeResolver.java @@ -75,8 +75,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTResource; import net.sourceforge.pmd.lang.java.ast.ASTShiftExpression; import net.sourceforge.pmd.lang.java.ast.ASTSingleMemberAnnotation; import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; -import net.sourceforge.pmd.lang.java.ast.ASTSwitchBlockGroup; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; +import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabeledRule; import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.ASTTypeArgument; import net.sourceforge.pmd.lang.java.ast.ASTTypeArguments; @@ -1185,8 +1185,8 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter { JavaTypeDefinition type = null; // first try to determine the type based on the first expression/break of a switch rule - List rules = node.findChildrenOfType(ASTSwitchBlockGroup.class); - for (ASTSwitchBlockGroup rule : rules) { + List rules = node.findChildrenOfType(ASTSwitchLabeledRule.class); + for (ASTSwitchLabeledRule rule : rules) { Node body = rule.jjtGetChild(1); // second child is either Expression, Block, ThrowStatement if (body instanceof ASTExpression) { type = ((ASTExpression) body).getTypeDefinition(); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java index 76f8d5aae2..fa6a76196e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java12Test.java @@ -53,22 +53,21 @@ public class Java12Test { Assert.assertNotNull(compilationUnit); ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression); - Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchBlockGroup); - ASTSwitchBlockGroup switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(1); - Assert.assertTrue(switchBlockGroup.isRule()); - Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); - Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTExpression); + Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabeledExpression); + ASTSwitchLabeledExpression switchLabeledExpression = (ASTSwitchLabeledExpression) switchStatement.jjtGetChild(1); + Assert.assertEquals(2, switchLabeledExpression.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledExpression.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledExpression.jjtGetChild(1) instanceof ASTExpression); - switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(4); - Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); - Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTBlock); + ASTSwitchLabeledBlock switchLabeledBlock = (ASTSwitchLabeledBlock) switchStatement.jjtGetChild(4); + Assert.assertEquals(2, switchLabeledBlock.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledBlock.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledBlock.jjtGetChild(1) instanceof ASTBlock); - switchBlockGroup = (ASTSwitchBlockGroup) switchStatement.jjtGetChild(5); - Assert.assertEquals(2, switchBlockGroup.jjtGetNumChildren()); - Assert.assertTrue(switchBlockGroup.jjtGetChild(0) instanceof ASTSwitchLabel); - Assert.assertTrue(switchBlockGroup.jjtGetChild(1) instanceof ASTThrowStatement); + ASTSwitchLabeledThrowStatement switchLabeledThrowStatement = (ASTSwitchLabeledThrowStatement) switchStatement.jjtGetChild(5); + Assert.assertEquals(2, switchLabeledThrowStatement.jjtGetNumChildren()); + Assert.assertTrue(switchLabeledThrowStatement.jjtGetChild(0) instanceof ASTSwitchLabel); + Assert.assertTrue(switchLabeledThrowStatement.jjtGetChild(1) instanceof ASTThrowStatement); } @Test(expected = ParseException.class) @@ -85,7 +84,7 @@ public class Java12Test { ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class); Assert.assertEquals(6, switchExpression.jjtGetNumChildren()); Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression); - Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchBlockGroup.class).size()); + Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size()); ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class).get(1); ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class); diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt index e4ace1b14c..4dd28b2bb2 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/SwitchExpressionTests.kt @@ -40,8 +40,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -78,8 +77,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -102,8 +100,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe true @@ -152,8 +149,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -174,8 +170,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -189,8 +184,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child { child(ignoreChildren = true) {} - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -200,8 +194,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe true @@ -213,8 +206,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe true @@ -270,10 +262,8 @@ class ASTSwitchExpressionTests : ParserTestSpec({ it.testedExpression shouldBe child(ignoreChildren = true) {} - child(ignoreChildren = true) { - it.isRule shouldBe true - } - child(ignoreChildren = true) {} + child(ignoreChildren = true) {} + child(ignoreChildren = true) {} } } @@ -310,8 +300,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ } } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false @@ -323,8 +312,7 @@ class ASTSwitchExpressionTests : ParserTestSpec({ child(ignoreChildren = true) {} } - child { - it.isRule shouldBe true + child { child { it.isDefault shouldBe false From ec68c2979c9263bfe556e2d9cf225deea26033de Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 10:33:02 +0200 Subject: [PATCH 92/99] [java] avoid most lookaheads for SwitchStatements --- pmd-java/etc/grammar/Java.jjt | 18 +++++++++++---- .../pmd/lang/java/ast/ParserCornersTest.java | 9 ++++++++ .../pmd/lang/java/ast/SwitchStatements.java | 23 +++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 53706c7156..364d997e99 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -2470,17 +2470,25 @@ void SwitchBlock() #void : { "{" ( - LOOKAHEAD(SwitchLabel() ":") (LOOKAHEAD(2) SwitchLabeledStatementGroup())* - | - (LOOKAHEAD(2) SwitchLabeledRule())* - ) + SwitchLabel() + ( + "->" SwitchLabeledRulePart() (SwitchLabeledRule())* + | + ":" (LOOKAHEAD(2) SwitchLabel() ":")* (BlockStatement())* (SwitchLabeledStatementGroup())* + ) + )? "}" } void SwitchLabeledRule() #void : {checkForSwitchRules();} { - SwitchLabel() "->" + SwitchLabel() "->" SwitchLabeledRulePart() +} + +void SwitchLabeledRulePart() #void: +{checkForSwitchRules();} +{ ( ( Expression() ";" ) #SwitchLabeledExpression(2) | 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 936babbb12..20b90e5fa0 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 @@ -282,6 +282,15 @@ public class ParserCornersTest { Assert.assertEquals(2, switchStatement.findChildrenOfType(ASTSwitchLabel.class).size()); } + @Test + public void testSwitchStatements() throws Exception { + ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("11", readAsString("SwitchStatements.java")); + Assert.assertNotNull(compilationUnit); + ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class); + Assert.assertEquals(2, switchStatement.findChildrenOfType(ASTSwitchLabel.class).size()); + } + + private String readAsString(String resource) { try (InputStream in = ParserCornersTest.class.getResourceAsStream(resource)) { return IOUtils.toString(in, StandardCharsets.UTF_8); diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.java new file mode 100644 index 0000000000..c198e03783 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/SwitchStatements.java @@ -0,0 +1,23 @@ +public class SwitchStatements { + + public void myMethod() { + int a = 1; + + // only fall through, no block statements. + switch (a) { + case 1: + default: + } + + // empty switch statement + switch (a) { } + + // last label without block statement + switch (a) { + case 1: + System.out.println("1"); + break; + default: + } + } +} \ No newline at end of file From dcb9bd007ddd92fe8b9add4e9513c5c0e37f5265 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 11:15:24 +0200 Subject: [PATCH 93/99] [apex] Update quickstart ruleset --- pmd-apex/src/main/resources/rulesets/apex/quickstart.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pmd-apex/src/main/resources/rulesets/apex/quickstart.xml b/pmd-apex/src/main/resources/rulesets/apex/quickstart.xml index 8ac07a5977..774f38ab50 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/quickstart.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/quickstart.xml @@ -236,6 +236,8 @@ + + From 3cd101a5a5f432d4f8a615c3a41d5fcf6d5d4f07 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 11:54:23 +0200 Subject: [PATCH 94/99] Fix do-release.sh --- do-release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/do-release.sh b/do-release.sh index 707c59ce8a..f7b5294fa0 100755 --- a/do-release.sh +++ b/do-release.sh @@ -76,14 +76,14 @@ echo "* Ensure all the new rules are listed in the proper file:" echo " ${RELEASE_RULESET}" echo echo "* Update **pmd-apex/src/main/resources/rulesets/apex/quickstart.xml** and" -echo " **pmd-java/src/main/resources/rulesets/java/quickstart.xml** with the new rules. +echo " **pmd-java/src/main/resources/rulesets/java/quickstart.xml** with the new rules." echo echo "* Update **docs/pages/next_major_development.md** with the API changes for" echo " the new release based on the release notes" echo echo "* Update **../pmd.github.io/_config.yml** to mention the new release" echo -echo "* Update property `pmd-designer.version` in **pom.xml** to reference the latest pmd-designer release" +echo "* Update property \`pmd-designer.version\` in **pom.xml** to reference the latest pmd-designer release" echo " See for the available releases." echo echo "Press enter to continue..." From 272e1ec2ffea6ba9cd770630aae14da487062ce9 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 11:58:55 +0200 Subject: [PATCH 95/99] Prepare pmd release 6.13.0 --- docs/_config.yml | 2 +- docs/pages/next_major_development.md | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 5323f4bfd2..d6f39e51f6 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -3,7 +3,7 @@ repository: pmd/pmd pmd: version: 6.13.0 previous_version: 6.12.0 - date: ??-March-2019 + date: 31-March-2019 release_type: minor output: web diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index 5d9de8db58..427b588b93 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -73,6 +73,26 @@ the breaking API changes will be performed in 7.0.0. an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0, we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %} +#### 6.13.0 + +##### Command Line Interface + +The start scripts `run.sh`, `pmd.bat` and `cpd.bat` support the new environment variable `PMD_JAVA_OPTS`. +This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. `PMD_JAVA_OPTS=-Xmx512m`) +or enable preview language features (e.g. `PMD_JAVA_OPTS=--enable-preview`). + +The previously available variables such as `OPTS` or `HEAPSIZE` are deprecated and will be removed with PMD 7.0.0. + +##### Deprecated API + +* {% jdoc core::renderers.CodeClimateRule %} is deprecated in 7.0.0 because it was unused for 2 years and + created an unwanted dependency. + Properties "cc_categories", "cc_remediation_points_multiplier", "cc_block_highlighting" will also be removed. + See [#1702](https://github.com/pmd/pmd/pull/1702) for more. + +* The Apex ruleset `rulesets/apex/ruleset.xml` has been deprecated and will be removed in 7.0.0. Please use the new + quickstart ruleset `rulesets/apex/quickstart.xml` instead. + #### 6.12.0 No changes. From 4ed549f0b2925ead2c52897cc6ee093d624acd0f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 12:06:56 +0200 Subject: [PATCH 96/99] [maven-release-plugin] prepare release pmd_releases/6.13.0 --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 4 ++-- 30 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index 0caba6de90..3f0c14ed5f 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index 83f1e28be6..fdf44fe66e 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index e1063e97b6..447d80370e 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 3a702dedb5..34b17f5f5b 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index c030ce403e..bbc21ca59f 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 43e1480ef6..9fe0876bd7 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 8e06ee278a..86d35fe807 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 2f1634783d..9147c0e596 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 0f8490f7a2..1298fd5a4b 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 9a89924726..880d542a77 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 9b58bdbbaf..871e12aebc 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index dace571d45..6ad57b954b 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 7556cc6026..6be4095ce7 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index cdcd67eeb0..98e2a0e013 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index 6f24db9f6f..31aac8e2da 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 6eb89bf533..86cf03768d 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index 1087f24065..b830ba6477 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index 463b374a34..37ab8b83bb 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index 0ad1060197..1a4241c0fa 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index f17c4425fb..875052e5b3 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index 1c6ac92e84..ecbe0ef46f 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index 5baae9480c..dad728721f 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index b86a14ac13..678799ec82 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index 233f422663..452a9828b3 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index 916d3ae93a..e1b56510f2 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index 81e1ec7bb3..c8b96fac69 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 80b019b7de..46cc24e3d0 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index 60c82c2351..ab22bf73c6 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index 65f00ac884..cb0bdb6800 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 diff --git a/pom.xml b/pom.xml index 7361f6e9cb..d9c6df35f3 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.13.0-SNAPSHOT + 6.13.0 pom PMD @@ -234,7 +234,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - HEAD + pmd_releases/6.13.0 From 5818abc0c7cab28ff711b05a66434e4a352e24ff Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 12:07:07 +0200 Subject: [PATCH 97/99] [maven-release-plugin] prepare for next development iteration --- pmd-apex-jorje/pom.xml | 2 +- pmd-apex/pom.xml | 2 +- pmd-core/pom.xml | 2 +- pmd-cpp/pom.xml | 2 +- pmd-cs/pom.xml | 2 +- pmd-dist/pom.xml | 2 +- pmd-doc/pom.xml | 2 +- pmd-fortran/pom.xml | 2 +- pmd-go/pom.xml | 2 +- pmd-groovy/pom.xml | 2 +- pmd-java/pom.xml | 2 +- pmd-java8/pom.xml | 2 +- pmd-javascript/pom.xml | 2 +- pmd-jsp/pom.xml | 2 +- pmd-kotlin/pom.xml | 2 +- pmd-lang-test/pom.xml | 2 +- pmd-matlab/pom.xml | 2 +- pmd-objectivec/pom.xml | 2 +- pmd-perl/pom.xml | 2 +- pmd-php/pom.xml | 2 +- pmd-plsql/pom.xml | 2 +- pmd-python/pom.xml | 2 +- pmd-ruby/pom.xml | 2 +- pmd-scala/pom.xml | 2 +- pmd-swift/pom.xml | 2 +- pmd-test/pom.xml | 2 +- pmd-visualforce/pom.xml | 2 +- pmd-vm/pom.xml | 2 +- pmd-xml/pom.xml | 2 +- pom.xml | 4 ++-- 30 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pmd-apex-jorje/pom.xml b/pmd-apex-jorje/pom.xml index 3f0c14ed5f..6896275014 100644 --- a/pmd-apex-jorje/pom.xml +++ b/pmd-apex-jorje/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-apex/pom.xml b/pmd-apex/pom.xml index fdf44fe66e..3000d29c92 100644 --- a/pmd-apex/pom.xml +++ b/pmd-apex/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-core/pom.xml b/pmd-core/pom.xml index 447d80370e..ce117d95e4 100644 --- a/pmd-core/pom.xml +++ b/pmd-core/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-cpp/pom.xml b/pmd-cpp/pom.xml index 34b17f5f5b..97b56a009a 100644 --- a/pmd-cpp/pom.xml +++ b/pmd-cpp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-cs/pom.xml b/pmd-cs/pom.xml index bbc21ca59f..0d76e4f9d2 100644 --- a/pmd-cs/pom.xml +++ b/pmd-cs/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 9fe0876bd7..18282ae0b5 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-doc/pom.xml b/pmd-doc/pom.xml index 86d35fe807..5d65bdb499 100644 --- a/pmd-doc/pom.xml +++ b/pmd-doc/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-fortran/pom.xml b/pmd-fortran/pom.xml index 9147c0e596..8e2b96472a 100644 --- a/pmd-fortran/pom.xml +++ b/pmd-fortran/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-go/pom.xml b/pmd-go/pom.xml index 1298fd5a4b..63af4c89dd 100644 --- a/pmd-go/pom.xml +++ b/pmd-go/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-groovy/pom.xml b/pmd-groovy/pom.xml index 880d542a77..a5c5d65b82 100644 --- a/pmd-groovy/pom.xml +++ b/pmd-groovy/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index 871e12aebc..50deef67af 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-java8/pom.xml b/pmd-java8/pom.xml index 6ad57b954b..beda38c0cb 100644 --- a/pmd-java8/pom.xml +++ b/pmd-java8/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-javascript/pom.xml b/pmd-javascript/pom.xml index 6be4095ce7..9636287af7 100644 --- a/pmd-javascript/pom.xml +++ b/pmd-javascript/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-jsp/pom.xml b/pmd-jsp/pom.xml index 98e2a0e013..28efac8fb0 100644 --- a/pmd-jsp/pom.xml +++ b/pmd-jsp/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-kotlin/pom.xml b/pmd-kotlin/pom.xml index 31aac8e2da..2febba19bc 100644 --- a/pmd-kotlin/pom.xml +++ b/pmd-kotlin/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 86cf03768d..005b1daf88 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -12,7 +12,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-matlab/pom.xml b/pmd-matlab/pom.xml index b830ba6477..cc2cc035b2 100644 --- a/pmd-matlab/pom.xml +++ b/pmd-matlab/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-objectivec/pom.xml b/pmd-objectivec/pom.xml index 37ab8b83bb..b0654d8f63 100644 --- a/pmd-objectivec/pom.xml +++ b/pmd-objectivec/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-perl/pom.xml b/pmd-perl/pom.xml index 1a4241c0fa..1969b945c3 100644 --- a/pmd-perl/pom.xml +++ b/pmd-perl/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-php/pom.xml b/pmd-php/pom.xml index 875052e5b3..03be9aa186 100644 --- a/pmd-php/pom.xml +++ b/pmd-php/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-plsql/pom.xml b/pmd-plsql/pom.xml index ecbe0ef46f..29cd4ebef2 100644 --- a/pmd-plsql/pom.xml +++ b/pmd-plsql/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-python/pom.xml b/pmd-python/pom.xml index dad728721f..ca235fcc24 100644 --- a/pmd-python/pom.xml +++ b/pmd-python/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-ruby/pom.xml b/pmd-ruby/pom.xml index 678799ec82..b0e0dba286 100644 --- a/pmd-ruby/pom.xml +++ b/pmd-ruby/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-scala/pom.xml b/pmd-scala/pom.xml index 452a9828b3..826c1eb2b0 100644 --- a/pmd-scala/pom.xml +++ b/pmd-scala/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-swift/pom.xml b/pmd-swift/pom.xml index e1b56510f2..5c242328ba 100644 --- a/pmd-swift/pom.xml +++ b/pmd-swift/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index c8b96fac69..66dbdb83a3 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -8,7 +8,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-visualforce/pom.xml b/pmd-visualforce/pom.xml index 46cc24e3d0..310a0bb058 100644 --- a/pmd-visualforce/pom.xml +++ b/pmd-visualforce/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-vm/pom.xml b/pmd-vm/pom.xml index ab22bf73c6..0155b800a5 100644 --- a/pmd-vm/pom.xml +++ b/pmd-vm/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pmd-xml/pom.xml b/pmd-xml/pom.xml index cb0bdb6800..04ca336fa7 100644 --- a/pmd-xml/pom.xml +++ b/pmd-xml/pom.xml @@ -7,7 +7,7 @@ net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index d9c6df35f3..f653cf75a4 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 net.sourceforge.pmd pmd - 6.13.0 + 6.14.0-SNAPSHOT pom PMD @@ -234,7 +234,7 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code scm:git:git://github.com/pmd/pmd.git scm:git:ssh://git@github.com/pmd/pmd.git https://github.com/pmd/pmd - pmd_releases/6.13.0 + HEAD From 238fcf73aaed0659c73a5b38fe71a851075423cf Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 12:13:11 +0200 Subject: [PATCH 98/99] Prepare next development version --- docs/_config.yml | 6 +- docs/pages/release_notes.md | 133 -------------------------- docs/pages/release_notes_old.md | 162 ++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 136 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index d6f39e51f6..df0d455412 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,9 @@ repository: pmd/pmd pmd: - version: 6.13.0 - previous_version: 6.12.0 - date: 31-March-2019 + version: 6.14.0 + previous_version: 6.13.0 + date: ??-April-2019 release_type: minor output: web diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index ec8d27e00e..b8f8783555 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -14,144 +14,11 @@ This is a {{ site.pmd.release_type }} release. ### New and noteworthy -#### Call For Logo - -We are still searching for a new logo for PMD for the next major release. - -Learn more about how to participate on [github issue 1663](https://github.com/pmd/pmd/issues/1663). - -#### Java 12 Support - -This release of PMD brings support for Java 12. PMD can parse the new [Switch Expressions](http://openjdk.java.net/jeps/325) -and resolve the type of such an expression. - -Note: The Switch Expressions are a preview language feature of OpenJDK 12 and are not enabled by default. In order to -analyze a project with PMD that uses these language features, you'll need to enable it via the new environment -variable `PMD_JAVA_OPTS`: - - export PMD_JAVA_OPTS=--enable-preview - ./run.sh pmd ... - -#### Quickstart Ruleset for Apex - -PMD provides now a quickstart ruleset for Salesforce.com Apex, which you can use as a base ruleset to -get your custom ruleset started. You can reference it with `rulesets/apex/quickstart.xml`. -You are strongly encouraged to [create your own ruleset](https://pmd.github.io/pmd-6.12.0/pmd_userdocs_making_rulesets.html) -though. - -The quickstart ruleset has the intention, to be useful out-of-the-box for many projects. Therefore it -references only rules, that are most likely to apply everywhere. - -Any feedback would be greatly appreciated. - -#### PMD Designer - -The rule designer's codebase has been moved out of the main repository and -will be developed at [pmd/pmd-designer](https://github.com/pmd/pmd-designer) -from now on. The maven coordinates will stay the same for the time being. -The designer will still be shipped with PMD's binaries. - -#### Improved Apex Support - -* Many AST nodes now expose more information which makes it easier to write XPath-based rules for Apex. Here are - some examples: - * `Annotation[@Resolved = false()]` finds unsupported annotations. - * `AnnotationParameter[@Name='RestResource'][@Value='/myurl']` gives access to - annotation parameters. - * `CatchBlockStatement[@ExceptionType='Exception'][@VariableName='e']` finds catch - block for specific exception types. - * `Field[@Type='String']` find all String fields, `Field[string-length(@Name) < 5]` - finds all fields with short names and `Field[@Value='a']` find alls fields, that are - initialized with a specific value. - * `LiteralExpression[@String = true()]` finds all String literals. There are attributes - for each type: `@Boolean`, `@Integer`, `@Double`, `@Long`, `@Decimal`, `@Null`. - * `Method[@Constructor = true()]` selects all constructors. `Method[@ReturnType = 'String']` - selects all methods that return a String. - * The `ModifierNode` node has a couple of attributes to check for the existence of specific - modifiers: `@Test`, `@TestOrTestSetup`, `@WithSharing`, `@WithoutSharing`, `@InheritedSharing`, - `@WebService`, `@Global`, `@Override`. - * Many nodes now expose their type. E.g. with `Parameter[@Type='Integer']` you can find all - method parameters of type Integer. The same attribute `Type` exists as well for: - `NewObjectExpression`, `Property`, `VariableDeclaration`. - * `VariableExpression[@Image='i']` finds all variable usages of the variable "i". - -#### New Rules - -* The new Java rule {% rule "java/design/AvoidUncheckedExceptionsInSignatures" %} (`java-design`) finds methods or constructors - that declare unchecked exceptions in their `throws` clause. This forces the caller to handle the exception, - even though it is a runtime exception. - -* The new Java rule {% rule "java/errorprone/DetachedTestCase" %} (`java-errorprone`) searches for public - methods in test classes, which are not annotated with `@Test`. These methods might be test cases where - the annotation has been forgotten. Because of that those test cases are never executed. - -* The new Java rule {% rule "java/bestpractices/WhileLoopWithLiteralBoolean" %} (`java-bestpractices`) finds - Do-While-Loops and While-Loops that can be simplified since they use simply `true` or `false` as their - loop condition. - -* The new Apex rule {% rule "apex/bestpractices/ApexAssertionsShouldIncludeMessage" %} (`apex-bestpractices`) - searches for assertions in unit tests and checks, whether they use a message argument. - -* The new Apex rule {% rule "apex/bestpractices/ApexUnitTestMethodShouldHaveIsTestAnnotation" %} (`apex-bestpractices`) - searches for methods in test classes, which are missing the `@IsTest` annotation. - -* The new PLSQL rule {% rule "plsql/codestyle/AvoidTabCharacter" %} (`plsql-codestyle`) checks, that there are - no tab characters ("\t") in the source file. - -* The new PLSQL rule {% rule "plsql/codestyle/LineLength" %} (`plsql-codestyle`) helps to enforce a maximum - line length. - ### Fixed Issues -* doc - * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example -* java - * [#1537](https://github.com/pmd/pmd/issues/1537): \[java] Java 12 support -* java-bestpractices - * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods -* java-codestyle - * [#1527](https://github.com/pmd/pmd/issues/1527): \[java] UseUnderscoresInNumericLiterals false positive on floating point numbers - * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong -* java-errorprone - * [#1570](https://github.com/pmd/pmd/issues/1570): \[java] AvoidDuplicateLiterals warning about deprecated separator property when not used -* plsql - * [#1510](https://github.com/pmd/pmd/issues/1510): \[plsql] Support XMLTABLE functions - * [#1716](https://github.com/pmd/pmd/issues/1716): \[plsql] Support access to whole plsql code - * [#1731](https://github.com/pmd/pmd/issues/1731): \[pslql] ParseException when parsing ELSIF - * [#1733](https://github.com/pmd/pmd/issues/1733): \[plsql] % not supported in "TestSearch%notfound" - * [#1734](https://github.com/pmd/pmd/issues/1734): \[plsql] TooManyMethods false-negative - * [#1735](https://github.com/pmd/pmd/issues/1735): \[plsql] False-negatives for TO_DATE_TO_CHAR, TO_DATEWithoutDateFormat, TO_TIMESTAMPWithoutDateFormat - ### API Changes -#### Command Line Interface - -The start scripts `run.sh`, `pmd.bat` and `cpd.bat` support the new environment variable `PMD_JAVA_OPTS`. -This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. `PMD_JAVA_OPTS=-Xmx512m`) -or enable preview language features (e.g. `PMD_JAVA_OPTS=--enable-preview`). - -The previously available variables such as `OPTS` or `HEAPSIZE` are deprecated and will be removed with PMD 7.0.0. - -#### Deprecated API - -* {% jdoc core::renderers.CodeClimateRule %} is deprecated in 7.0.0 because it was unused for 2 years and - created an unwanted dependency. - Properties "cc_categories", "cc_remediation_points_multiplier", "cc_block_highlighting" will also be removed. - See [#1702](https://github.com/pmd/pmd/pull/1702) for more. - -* The Apex ruleset `rulesets/apex/ruleset.xml` has been deprecated and will be removed in 7.0.0. Please use the new - quickstart ruleset `rulesets/apex/quickstart.xml` instead. - ### External Contributions -* [#1694](https://github.com/pmd/pmd/pull/1694): \[apex] New rules for test method and assert statements - [triandicAnt](https://github.com/triandicAnt) -* [#1697](https://github.com/pmd/pmd/pull/1697): \[doc] Update CPD documentation - [Matías Fraga](https://github.com/matifraga) -* [#1704](https://github.com/pmd/pmd/pull/1704): \[java] Added AvoidUncheckedExceptionsInSignatures Rule - [Bhanu Prakash Pamidi](https://github.com/pamidi99) -* [#1706](https://github.com/pmd/pmd/pull/1706): \[java] Add DetachedTestCase rule - [David Burström](https://github.com/davidburstromspotify) -* [#1709](https://github.com/pmd/pmd/pull/1709): \[java] Detect while loops with literal booleans conditions - [David Burström](https://github.com/davidburstromspotify) -* [#1717](https://github.com/pmd/pmd/pull/1717): \[java] Fix false positive in useTryWithResources when using a custom close method with multiple arguments - [Rishabh Jain](https://github.com/jainrish) -* [#1724](https://github.com/pmd/pmd/pull/1724): \[doc] Correct property override example - [Felix W. Dekker](https://github.com/FWDekker) -* [#1737](https://github.com/pmd/pmd/pull/1737): \[java] fix escaping of CommentDefaultAccessModifier documentation - [itaigilo](https://github.com/itaigilo) - {% endtocmaker %} diff --git a/docs/pages/release_notes_old.md b/docs/pages/release_notes_old.md index 7a08e324bd..92346db427 100644 --- a/docs/pages/release_notes_old.md +++ b/docs/pages/release_notes_old.md @@ -5,6 +5,168 @@ permalink: pmd_release_notes_old.html Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases +## 31-March-2019 - 6.13.0 + +The PMD team is pleased to announce PMD 6.13.0. + +This is a minor release. + +### Table Of Contents + +* [New and noteworthy](#new-and-noteworthy) + * [Call For Logo](#call-for-logo) + * [Java 12 Support](#java-12-support) + * [Quickstart Ruleset for Apex](#quickstart-ruleset-for-apex) + * [PMD Designer](#pmd-designer) + * [Improved Apex Support](#improved-apex-support) + * [New Rules](#new-rules) +* [Fixed Issues](#fixed-issues) +* [API Changes](#api-changes) + * [Command Line Interface](#command-line-interface) + * [Deprecated API](#deprecated-api) +* [External Contributions](#external-contributions) + +### New and noteworthy + +#### Call For Logo + +We are still searching for a new logo for PMD for the next major release. + +Learn more about how to participate on [github issue 1663](https://github.com/pmd/pmd/issues/1663). + +#### Java 12 Support + +This release of PMD brings support for Java 12. PMD can parse the new [Switch Expressions](http://openjdk.java.net/jeps/325) +and resolve the type of such an expression. + +Note: The Switch Expressions are a preview language feature of OpenJDK 12 and are not enabled by default. In order to +analyze a project with PMD that uses these language features, you'll need to enable it via the new environment +variable `PMD_JAVA_OPTS`: + + export PMD_JAVA_OPTS=--enable-preview + ./run.sh pmd ... + +#### Quickstart Ruleset for Apex + +PMD provides now a quickstart ruleset for Salesforce.com Apex, which you can use as a base ruleset to +get your custom ruleset started. You can reference it with `rulesets/apex/quickstart.xml`. +You are strongly encouraged to [create your own ruleset](https://pmd.github.io/pmd-6.12.0/pmd_userdocs_making_rulesets.html) +though. + +The quickstart ruleset has the intention, to be useful out-of-the-box for many projects. Therefore it +references only rules, that are most likely to apply everywhere. + +Any feedback would be greatly appreciated. + +#### PMD Designer + +The rule designer's codebase has been moved out of the main repository and +will be developed at [pmd/pmd-designer](https://github.com/pmd/pmd-designer) +from now on. The maven coordinates will stay the same for the time being. +The designer will still be shipped with PMD's binaries. + +#### Improved Apex Support + +* Many AST nodes now expose more information which makes it easier to write XPath-based rules for Apex. Here are + some examples: + * `Annotation[@Resolved = false()]` finds unsupported annotations. + * `AnnotationParameter[@Name='RestResource'][@Value='/myurl']` gives access to + annotation parameters. + * `CatchBlockStatement[@ExceptionType='Exception'][@VariableName='e']` finds catch + block for specific exception types. + * `Field[@Type='String']` find all String fields, `Field[string-length(@Name) < 5]` + finds all fields with short names and `Field[@Value='a']` find alls fields, that are + initialized with a specific value. + * `LiteralExpression[@String = true()]` finds all String literals. There are attributes + for each type: `@Boolean`, `@Integer`, `@Double`, `@Long`, `@Decimal`, `@Null`. + * `Method[@Constructor = true()]` selects all constructors. `Method[@ReturnType = 'String']` + selects all methods that return a String. + * The `ModifierNode` node has a couple of attributes to check for the existence of specific + modifiers: `@Test`, `@TestOrTestSetup`, `@WithSharing`, `@WithoutSharing`, `@InheritedSharing`, + `@WebService`, `@Global`, `@Override`. + * Many nodes now expose their type. E.g. with `Parameter[@Type='Integer']` you can find all + method parameters of type Integer. The same attribute `Type` exists as well for: + `NewObjectExpression`, `Property`, `VariableDeclaration`. + * `VariableExpression[@Image='i']` finds all variable usages of the variable "i". + +#### New Rules + +* The new Java rule [`AvoidUncheckedExceptionsInSignatures`](https://pmd.github.io/pmd-6.13.0/pmd_rules_java_design.html#avoiduncheckedexceptionsinsignatures) (`java-design`) finds methods or constructors + that declare unchecked exceptions in their `throws` clause. This forces the caller to handle the exception, + even though it is a runtime exception. + +* The new Java rule [`DetachedTestCase`](https://pmd.github.io/pmd-6.13.0/pmd_rules_java_errorprone.html#detachedtestcase) (`java-errorprone`) searches for public + methods in test classes, which are not annotated with `@Test`. These methods might be test cases where + the annotation has been forgotten. Because of that those test cases are never executed. + +* The new Java rule [`WhileLoopWithLiteralBoolean`](https://pmd.github.io/pmd-6.13.0/pmd_rules_java_bestpractices.html#whileloopwithliteralboolean) (`java-bestpractices`) finds + Do-While-Loops and While-Loops that can be simplified since they use simply `true` or `false` as their + loop condition. + +* The new Apex rule [`ApexAssertionsShouldIncludeMessage`](https://pmd.github.io/pmd-6.13.0/pmd_rules_apex_bestpractices.html#apexassertionsshouldincludemessage) (`apex-bestpractices`) + searches for assertions in unit tests and checks, whether they use a message argument. + +* The new Apex rule [`ApexUnitTestMethodShouldHaveIsTestAnnotation`](https://pmd.github.io/pmd-6.13.0/pmd_rules_apex_bestpractices.html#apexunittestmethodshouldhaveistestannotation) (`apex-bestpractices`) + searches for methods in test classes, which are missing the `@IsTest` annotation. + +* The new PLSQL rule [`AvoidTabCharacter`](https://pmd.github.io/pmd-6.13.0/pmd_rules_plsql_codestyle.html#avoidtabcharacter) (`plsql-codestyle`) checks, that there are + no tab characters ("\t") in the source file. + +* The new PLSQL rule [`LineLength`](https://pmd.github.io/pmd-6.13.0/pmd_rules_plsql_codestyle.html#linelength) (`plsql-codestyle`) helps to enforce a maximum + line length. + +### Fixed Issues + +* doc + * [#1721](https://github.com/pmd/pmd/issues/1721): \[doc] Documentation provides an invalid property configuration example +* java + * [#1537](https://github.com/pmd/pmd/issues/1537): \[java] Java 12 support +* java-bestpractices + * [#1701](https://github.com/pmd/pmd/issues/1701): \[java] UseTryWithResources does not handle multiple argument close methods +* java-codestyle + * [#1527](https://github.com/pmd/pmd/issues/1527): \[java] UseUnderscoresInNumericLiterals false positive on floating point numbers + * [#1674](https://github.com/pmd/pmd/issues/1674): \[java] documentation of CommentDefaultAccessModifier is wrong +* java-errorprone + * [#1570](https://github.com/pmd/pmd/issues/1570): \[java] AvoidDuplicateLiterals warning about deprecated separator property when not used +* plsql + * [#1510](https://github.com/pmd/pmd/issues/1510): \[plsql] Support XMLTABLE functions + * [#1716](https://github.com/pmd/pmd/issues/1716): \[plsql] Support access to whole plsql code + * [#1731](https://github.com/pmd/pmd/issues/1731): \[pslql] ParseException when parsing ELSIF + * [#1733](https://github.com/pmd/pmd/issues/1733): \[plsql] % not supported in "TestSearch%notfound" + * [#1734](https://github.com/pmd/pmd/issues/1734): \[plsql] TooManyMethods false-negative + * [#1735](https://github.com/pmd/pmd/issues/1735): \[plsql] False-negatives for TO_DATE_TO_CHAR, TO_DATEWithoutDateFormat, TO_TIMESTAMPWithoutDateFormat + +### API Changes + +#### Command Line Interface + +The start scripts `run.sh`, `pmd.bat` and `cpd.bat` support the new environment variable `PMD_JAVA_OPTS`. +This can be used to set arbitrary JVM options for running PMD, such as memory settings (e.g. `PMD_JAVA_OPTS=-Xmx512m`) +or enable preview language features (e.g. `PMD_JAVA_OPTS=--enable-preview`). + +The previously available variables such as `OPTS` or `HEAPSIZE` are deprecated and will be removed with PMD 7.0.0. + +#### Deprecated API + +* [`CodeClimateRule`](https://javadoc.io/page/net.sourceforge.pmd/pmd-core/6.13.0/net/sourceforge/pmd/renderers/CodeClimateRule.html#) is deprecated in 7.0.0 because it was unused for 2 years and + created an unwanted dependency. + Properties "cc_categories", "cc_remediation_points_multiplier", "cc_block_highlighting" will also be removed. + See [#1702](https://github.com/pmd/pmd/pull/1702) for more. + +* The Apex ruleset `rulesets/apex/ruleset.xml` has been deprecated and will be removed in 7.0.0. Please use the new + quickstart ruleset `rulesets/apex/quickstart.xml` instead. + +### External Contributions + +* [#1694](https://github.com/pmd/pmd/pull/1694): \[apex] New rules for test method and assert statements - [triandicAnt](https://github.com/triandicAnt) +* [#1697](https://github.com/pmd/pmd/pull/1697): \[doc] Update CPD documentation - [Matías Fraga](https://github.com/matifraga) +* [#1704](https://github.com/pmd/pmd/pull/1704): \[java] Added AvoidUncheckedExceptionsInSignatures Rule - [Bhanu Prakash Pamidi](https://github.com/pamidi99) +* [#1706](https://github.com/pmd/pmd/pull/1706): \[java] Add DetachedTestCase rule - [David Burström](https://github.com/davidburstromspotify) +* [#1709](https://github.com/pmd/pmd/pull/1709): \[java] Detect while loops with literal booleans conditions - [David Burström](https://github.com/davidburstromspotify) +* [#1717](https://github.com/pmd/pmd/pull/1717): \[java] Fix false positive in useTryWithResources when using a custom close method with multiple arguments - [Rishabh Jain](https://github.com/jainrish) +* [#1724](https://github.com/pmd/pmd/pull/1724): \[doc] Correct property override example - [Felix W. Dekker](https://github.com/FWDekker) +* [#1737](https://github.com/pmd/pmd/pull/1737): \[java] fix escaping of CommentDefaultAccessModifier documentation - [itaigilo](https://github.com/itaigilo) + ## 24-February-2019 - 6.12.0 The PMD team is pleased to announce PMD 6.12.0. From a8823c4afda8b4357bbc986806e1eb4a70522033 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Sun, 31 Mar 2019 13:41:33 +0200 Subject: [PATCH 99/99] Update pmd to 6.13.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f653cf75a4..2efb4559fe 100644 --- a/pom.xml +++ b/pom.xml @@ -542,12 +542,12 @@ Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code net.sourceforge.pmd pmd-core - 6.12.0 + 6.13.0 net.sourceforge.pmd pmd-java - 6.12.0 + 6.13.0