From e0d465a81bf93c0c67d20e71854ee74fc6169913 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 7 Jun 2024 22:59:44 +0200 Subject: [PATCH] [plsql] Fix tests, restore exception handler, implicit cursor attribute --- pmd-plsql/etc/grammar/PLSQL.jjt | 30 ++- .../pmd/lang/plsql/ast/PlsqlTreeDumpTest.java | 5 + ...dTriggerWithAdditionalDeclarations4270.txt | 6 + .../lang/plsql/ast/ErrorLoggingClause2779.txt | 1 - .../ast/ExceptionHandlerTomKytesDespair.pls | 44 ++++ .../ast/ExceptionHandlerTomKytesDespair.txt | 193 ++++++++++++++++++ .../bestpractices/xml/TomKytesDespair.xml | 4 +- .../rule/design/xml/ExcessiveMethodLength.xml | 20 -- .../rule/design/xml/ExcessiveObjectLength.xml | 14 -- .../ExcessivePackageSpecificationLength.xml | 16 -- .../design/xml/ExcessiveParameterList.xml | 9 - .../rule/design/xml/ExcessiveTypeLength.xml | 14 -- .../plsql/rule/design/xml/NcssMethodCount.xml | 22 -- .../plsql/rule/design/xml/NcssObjectCount.xml | 22 -- 14 files changed, 277 insertions(+), 123 deletions(-) create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.pls create mode 100644 pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.txt diff --git a/pmd-plsql/etc/grammar/PLSQL.jjt b/pmd-plsql/etc/grammar/PLSQL.jjt index 9c66c4895f..3dd03c9905 100644 --- a/pmd-plsql/etc/grammar/PLSQL.jjt +++ b/pmd-plsql/etc/grammar/PLSQL.jjt @@ -569,7 +569,7 @@ ASTDeclarativeSection DeclarativeSection() : {} { DeclarativeUnit() - ( LOOKAHEAD(||||||ID() (||Datatype()), {getToken(1).kind != BEGIN}) DeclarativeUnit() )* + ( LOOKAHEAD(3) DeclarativeUnit() )* { return jjtThis; } } @@ -1080,7 +1080,6 @@ ASTExceptionHandler ExceptionHandler() : { ( - | QualifiedName() ( QualifiedName())* ) (Statement())+ @@ -3148,6 +3147,28 @@ ASTExpression Expression() : } } +/** + * https://docs.oracle.com/en/database/oracle/oracle-database/23/lnpls/implicit-cursor-attribute.html + */ +ASTImplicitCursorAttribute ImplicitCursorAttribute() : +{} +{ + "%" + ( + LOOKAHEAD({isKeyword("isopen")}) KEYWORD("ISOPEN") + | LOOKAHEAD({isKeyword("found")}) KEYWORD("FOUND") + | LOOKAHEAD({isKeyword("notfound")}) KEYWORD("NOTFOUND") + | LOOKAHEAD({isKeyword("rowcount")}) KEYWORD("ROWCOUNT") + | LOOKAHEAD({isKeyword("bulk_rowcount")}) KEYWORD("BULK_ROWCOUNT") "(" PrimaryExpression() ")" + | LOOKAHEAD({isKeyword("bulk_exceptions")}) KEYWORD("BULK_EXCEPTIONS") + ( "." "COUNT" + | "(" PrimaryExpression() ")" "." (LOOKAHEAD({isKeyword("error_index")}) KEYWORD("ERROR_INDEX") | LOOKAHEAD({isKeyword("error_code")}) KEYWORD("ERROR_CODE")) + ) + ) + + { return jjtThis; } +} + ASTCompilationExpression CompilationExpression() : { PLSQLNode simpleNode = null; @@ -3509,7 +3530,10 @@ ASTUnaryExpressionNotPlusMinus UnaryExpressionNotPlusMinus() #UnaryExpressionNot LOOKAHEAD(2) simpleNode = ExtractExpression() | LOOKAHEAD(2) simpleNode = IsNullCondition() - ) {sb.append(simpleNode.getImage()); } + | + simpleNode = ImplicitCursorAttribute() + ) + {sb.append(simpleNode.getImage()); } { jjtThis.setImage(sb.toString()); return jjtThis; } diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java index 2dae2f8ce8..cd3c2a2f07 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/PlsqlTreeDumpTest.java @@ -56,4 +56,9 @@ class PlsqlTreeDumpTest extends BaseTreeDumpTest { void compoundTriggerWithAdditionalDeclarations() { doTest("CompoundTriggerWithAdditionalDeclarations4270"); } + + @Test + void exceptionHandlerTomKytesDespair() { + doTest("ExceptionHandlerTomKytesDespair"); + } } diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CompoundTriggerWithAdditionalDeclarations4270.txt b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CompoundTriggerWithAdditionalDeclarations4270.txt index 51d49b7c2e..4be12a3962 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CompoundTriggerWithAdditionalDeclarations4270.txt +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/CompoundTriggerWithAdditionalDeclarations4270.txt @@ -149,6 +149,9 @@ | | +- Column[@CanonicalImage = "L_TOT_NUMBERS", @Image = "l_tot_numbers"] | | +- ID[@CanonicalImage = "L_TOT_NUMBERS", @Image = "l_tot_numbers"] | +- ExceptionHandler[@CanonicalImage = null] + | +- QualifiedName[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | +- UnqualifiedID[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | +- KEYWORD_UNRESERVED[@CanonicalImage = "OTHERS", @Image = "OTHERS"] | +- Statement[@CanonicalImage = null] | +- UnlabelledStatement[@CanonicalImage = null] | +- Expression[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] @@ -201,6 +204,9 @@ | | +- Literal[@CanonicalImage = "\'THIS IS JUST AN EXAMPLE!\'", @Image = "\'This is just an example!\'"] | | +- StringLiteral[@CanonicalImage = "\'THIS IS JUST AN EXAMPLE!\'", @Image = "\'This is just an example!\'", @String = "This is just an example!"] | +- ExceptionHandler[@CanonicalImage = null] + | +- QualifiedName[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | +- UnqualifiedID[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | +- KEYWORD_UNRESERVED[@CanonicalImage = "OTHERS", @Image = "OTHERS"] | +- Statement[@CanonicalImage = null] | +- UnlabelledStatement[@CanonicalImage = null] | +- Expression[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ErrorLoggingClause2779.txt b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ErrorLoggingClause2779.txt index ce2cf4c5e2..59df3c8ab5 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ErrorLoggingClause2779.txt +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ErrorLoggingClause2779.txt @@ -4,7 +4,6 @@ +- MethodDeclarator[@CanonicalImage = "TEST", @Image = "test", @ParameterCount = 1] | +- ObjectNameDeclaration[@CanonicalImage = "TEST", @Image = "test"] | +- ID[@CanonicalImage = "TEST", @Image = "test"] - +- DeclarativeSection[@CanonicalImage = null] +- Statement[@CanonicalImage = null] | +- UnlabelledStatement[@CanonicalImage = null] | +- InsertStatement[@CanonicalImage = null] diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.pls new file mode 100644 index 0000000000..49835b655e --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.pls @@ -0,0 +1,44 @@ +-- +-- BSD-style license; for more info see http://pmd.sourceforge.net/license.html +-- + +CREATE OR REPLACE PACKAGE BODY update_planned_hrs +IS + +PROCEDURE set_new_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER, p_hours IN NUMBER) +IS +BEGIN + UPDATE employee_on_activity ea + SET ea.ea_planned_hours = p_hours + WHERE + ea.ea_emp_id = p_emp_id + AND ea.ea_proj_id = p_project_id; + +EXCEPTION + WHEN NO_DATA_FOUND THEN + RAISE_APPLICATION_ERROR (-20100, 'No such employee or project'); + +END set_new_planned; + +FUNCTION existing_planned (p_emp_id IN NUMBER, p_project_id IN NUMBER) RETURN NUMBER + +IS + +existing_hours NUMBER(4); + +BEGIN + SELECT ea.ea_planned_hours INTO existing_hours + FROM employee_on_activity ea + WHERE + ea.ea_emp_id = p_emp_id + AND ea.ea_proj_id = p_project_id; + + RETURN (existing_hours); + + EXCEPTION + WHEN OTHERS THEN NULL; -- rule violation + + END existing_planned; + +END update_planned_hrs; +/ diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.txt b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.txt new file mode 100644 index 0000000000..dd4ad1a27d --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ExceptionHandlerTomKytesDespair.txt @@ -0,0 +1,193 @@ ++- Input[@CanonicalImage = null, @ExcludedLinesCount = 0, @ExcludedRangesCount = 0] + +- PackageBody[@CanonicalImage = "UPDATE_PLANNED_HRS", @Image = "update_planned_hrs", @ObjectName = "update_planned_hrs"] + +- ObjectNameDeclaration[@CanonicalImage = "UPDATE_PLANNED_HRS", @Image = "update_planned_hrs"] + | +- ID[@CanonicalImage = "UPDATE_PLANNED_HRS", @Image = "update_planned_hrs"] + +- DeclarativeSection[@CanonicalImage = null] + | +- DeclarativeUnit[@CanonicalImage = null] + | | +- ProgramUnit[@CanonicalImage = null, @MethodName = "set_new_planned", @Name = "set_new_planned", @ObjectName = null] + | | +- MethodDeclarator[@CanonicalImage = "SET_NEW_PLANNED", @Image = "set_new_planned", @ParameterCount = 1] + | | | +- ObjectNameDeclaration[@CanonicalImage = "SET_NEW_PLANNED", @Image = "set_new_planned"] + | | | | +- ID[@CanonicalImage = "SET_NEW_PLANNED", @Image = "set_new_planned"] + | | | +- FormalParameters[@CanonicalImage = "(P_EMP_ID,P_PROJECT_ID,P_HOURS)", @Image = "(p_emp_id,p_project_id,p_hours)"] + | | | +- FormalParameter[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id", @In = true, @NoCopy = false, @Out = false] + | | | | +- ID[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | | | +- FormalParameter[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id", @In = true, @NoCopy = false, @Out = false] + | | | | +- ID[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | | | +- FormalParameter[@CanonicalImage = "P_HOURS", @Image = "p_hours", @In = true, @NoCopy = false, @Out = false] + | | | +- ID[@CanonicalImage = "P_HOURS", @Image = "p_hours"] + | | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | | +- Statement[@CanonicalImage = null] + | | | +- UnlabelledStatement[@CanonicalImage = null] + | | | +- UpdateStatement[@CanonicalImage = null] + | | | +- DMLTableExpressionClause[@CanonicalImage = null] + | | | | +- TableName[@CanonicalImage = "EMPLOYEE_ON_ACTIVITY", @Image = "employee_on_activity"] + | | | | +- ID[@CanonicalImage = "EMPLOYEE_ON_ACTIVITY", @Image = "employee_on_activity"] + | | | +- TableAlias[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | +- UpdateSetClause[@CanonicalImage = null] + | | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- Column[@CanonicalImage = "EA_PLANNED_HOURS", @Image = "ea_planned_hours"] + | | | | | +- ID[@CanonicalImage = "EA_PLANNED_HOURS", @Image = "ea_planned_hours"] + | | | | +- Expression[@CanonicalImage = "P_HOURS", @Image = "p_hours"] + | | | | +- PrimaryPrefix[@CanonicalImage = "P_HOURS", @Image = "p_hours", @SelfModifier = false] + | | | | +- SimpleExpression[@CanonicalImage = "P_HOURS", @Image = "p_hours"] + | | | | +- Column[@CanonicalImage = "P_HOURS", @Image = "p_hours"] + | | | | +- ID[@CanonicalImage = "P_HOURS", @Image = "p_hours"] + | | | +- WhereClause[@CanonicalImage = null] + | | | +- Condition[@CanonicalImage = null] + | | | +- CompoundCondition[@CanonicalImage = null, @Type = "AND"] + | | | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="] + | | | | +- SqlExpression[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id"] + | | | | | +- PrimaryPrefix[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id", @SelfModifier = false] + | | | | | +- SimpleExpression[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id"] + | | | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | | | +- Column[@CanonicalImage = "EA_EMP_ID", @Image = "ea_emp_id"] + | | | | | +- ID[@CanonicalImage = "EA_EMP_ID", @Image = "ea_emp_id"] + | | | | +- SqlExpression[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | | +- PrimaryPrefix[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id", @SelfModifier = false] + | | | | +- SimpleExpression[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | | +- Column[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | | +- ID[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | +- Condition[@CanonicalImage = null] + | | | +- CompoundCondition[@CanonicalImage = null, @Type = null] + | | | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="] + | | | +- SqlExpression[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id"] + | | | | +- PrimaryPrefix[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id", @SelfModifier = false] + | | | | +- SimpleExpression[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id"] + | | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- Column[@CanonicalImage = "EA_PROJ_ID", @Image = "ea_proj_id"] + | | | | +- ID[@CanonicalImage = "EA_PROJ_ID", @Image = "ea_proj_id"] + | | | +- SqlExpression[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | | +- PrimaryPrefix[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id", @SelfModifier = false] + | | | +- SimpleExpression[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | | +- Column[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | | +- ID[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | +- ExceptionHandler[@CanonicalImage = null] + | | | +- QualifiedName[@CanonicalImage = "NO_DATA_FOUND", @Image = "NO_DATA_FOUND"] + | | | | +- UnqualifiedID[@CanonicalImage = "NO_DATA_FOUND", @Image = "NO_DATA_FOUND"] + | | | +- Statement[@CanonicalImage = null] + | | | +- UnlabelledStatement[@CanonicalImage = null] + | | | +- Expression[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] + | | | +- PrimaryPrefix[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR", @SelfModifier = false] + | | | +- FunctionCall[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] + | | | +- FunctionName[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] + | | | | +- ID[@CanonicalImage = "RAISE_APPLICATION_ERROR", @Image = "RAISE_APPLICATION_ERROR"] + | | | +- Arguments[@ArgumentCount = 2, @CanonicalImage = null] + | | | +- ArgumentList[@CanonicalImage = null] + | | | +- Argument[@CanonicalImage = null] + | | | | +- Expression[@CanonicalImage = "-20100", @Image = " -20100"] + | | | | +- PrimaryPrefix[@CanonicalImage = "20100", @Image = "20100", @SelfModifier = false] + | | | | +- Literal[@CanonicalImage = "20100", @Image = "20100"] + | | | | +- NumericLiteral[@CanonicalImage = "20100", @Image = "20100"] + | | | +- Argument[@CanonicalImage = null] + | | | +- Expression[@CanonicalImage = "\'NO SUCH EMPLOYEE OR PROJECT\'", @Image = "\'No such employee or project\'"] + | | | +- PrimaryPrefix[@CanonicalImage = "\'NO SUCH EMPLOYEE OR PROJECT\'", @Image = "\'No such employee or project\'", @SelfModifier = false] + | | | +- Literal[@CanonicalImage = "\'NO SUCH EMPLOYEE OR PROJECT\'", @Image = "\'No such employee or project\'"] + | | | +- StringLiteral[@CanonicalImage = "\'NO SUCH EMPLOYEE OR PROJECT\'", @Image = "\'No such employee or project\'", @String = "No such employee or project"] + | | +- ID[@CanonicalImage = "SET_NEW_PLANNED", @Image = "set_new_planned"] + | +- DeclarativeUnit[@CanonicalImage = null] + | +- ProgramUnit[@CanonicalImage = null, @MethodName = "existing_planned", @Name = "existing_planned", @ObjectName = null] + | +- MethodDeclarator[@CanonicalImage = "EXISTING_PLANNED", @Image = "existing_planned", @ParameterCount = 1] + | | +- ObjectNameDeclaration[@CanonicalImage = "EXISTING_PLANNED", @Image = "existing_planned"] + | | | +- ID[@CanonicalImage = "EXISTING_PLANNED", @Image = "existing_planned"] + | | +- FormalParameters[@CanonicalImage = "(P_EMP_ID,P_PROJECT_ID)", @Image = "(p_emp_id,p_project_id)"] + | | | +- FormalParameter[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id", @In = true, @NoCopy = false, @Out = false] + | | | | +- ID[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | | | +- FormalParameter[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id", @In = true, @NoCopy = false, @Out = false] + | | | +- ID[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | | +- Datatype[@CanonicalImage = "NUMBER", @Image = "NUMBER", @TypeImage = "NUMBER"] + | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER", @Image = "NUMBER"] + | +- DeclarativeSection[@CanonicalImage = null] + | | +- DeclarativeUnit[@CanonicalImage = null] + | | +- VariableOrConstantDeclaration[@CanonicalImage = null] + | | +- VariableOrConstantDeclarator[@CanonicalImage = "EXISTING_HOURS NUMBER(4)", @Image = "existing_hours NUMBER(4)"] + | | +- VariableOrConstantDeclaratorId[@Array = false, @ArrayDepth = 0, @CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | | +- ID[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | +- Datatype[@CanonicalImage = "NUMBER(4)", @Image = "NUMBER(4)", @TypeImage = "NUMBER(4)"] + | | +- ScalarDataTypeName[@CanonicalImage = "NUMBER(4)", @Image = "NUMBER(4)"] + | | +- NumericLiteral[@CanonicalImage = "4", @Image = "4"] + | +- Statement[@CanonicalImage = null] + | | +- UnlabelledStatement[@CanonicalImage = null] + | | +- SelectIntoStatement[@All = false, @CanonicalImage = null, @Distinct = false, @Unique = false] + | | +- SelectList[@CanonicalImage = null] + | | | +- SqlExpression[@CanonicalImage = "EA.EA_PLANNED_HOURS", @Image = "ea.ea_planned_hours"] + | | | +- PrimaryPrefix[@CanonicalImage = "EA.EA_PLANNED_HOURS", @Image = "ea.ea_planned_hours", @SelfModifier = false] + | | | +- SimpleExpression[@CanonicalImage = "EA.EA_PLANNED_HOURS", @Image = "ea.ea_planned_hours"] + | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | +- Column[@CanonicalImage = "EA_PLANNED_HOURS", @Image = "ea_planned_hours"] + | | | +- ID[@CanonicalImage = "EA_PLANNED_HOURS", @Image = "ea_planned_hours"] + | | +- IntoClause[@CanonicalImage = null] + | | | +- VariableName[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | | +- ID[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | +- FromClause[@CanonicalImage = null] + | | | +- TableReference[@CanonicalImage = null] + | | | +- TableName[@CanonicalImage = "EMPLOYEE_ON_ACTIVITY", @Image = "employee_on_activity"] + | | | | +- ID[@CanonicalImage = "EMPLOYEE_ON_ACTIVITY", @Image = "employee_on_activity"] + | | | +- TableAlias[@CanonicalImage = "EA", @Image = "ea"] + | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | +- WhereClause[@CanonicalImage = null] + | | +- Condition[@CanonicalImage = null] + | | +- CompoundCondition[@CanonicalImage = null, @Type = "AND"] + | | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="] + | | | +- SqlExpression[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id"] + | | | | +- PrimaryPrefix[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id", @SelfModifier = false] + | | | | +- SimpleExpression[@CanonicalImage = "EA.EA_EMP_ID", @Image = "ea.ea_emp_id"] + | | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- Column[@CanonicalImage = "EA_EMP_ID", @Image = "ea_emp_id"] + | | | | +- ID[@CanonicalImage = "EA_EMP_ID", @Image = "ea_emp_id"] + | | | +- SqlExpression[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | +- PrimaryPrefix[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id", @SelfModifier = false] + | | | +- SimpleExpression[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | +- Column[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | | +- ID[@CanonicalImage = "P_EMP_ID", @Image = "p_emp_id"] + | | +- Condition[@CanonicalImage = null] + | | +- CompoundCondition[@CanonicalImage = null, @Type = null] + | | +- ComparisonCondition[@CanonicalImage = null, @Operator = "="] + | | +- SqlExpression[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id"] + | | | +- PrimaryPrefix[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id", @SelfModifier = false] + | | | +- SimpleExpression[@CanonicalImage = "EA.EA_PROJ_ID", @Image = "ea.ea_proj_id"] + | | | +- TableName[@CanonicalImage = "EA", @Image = "ea"] + | | | | +- ID[@CanonicalImage = "EA", @Image = "ea"] + | | | +- Column[@CanonicalImage = "EA_PROJ_ID", @Image = "ea_proj_id"] + | | | +- ID[@CanonicalImage = "EA_PROJ_ID", @Image = "ea_proj_id"] + | | +- SqlExpression[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | +- PrimaryPrefix[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id", @SelfModifier = false] + | | +- SimpleExpression[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | +- Column[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | | +- ID[@CanonicalImage = "P_PROJECT_ID", @Image = "p_project_id"] + | +- Statement[@CanonicalImage = null] + | | +- UnlabelledStatement[@CanonicalImage = null] + | | +- ReturnStatement[@CanonicalImage = null] + | | +- Expression[@CanonicalImage = "(EXISTING_HOURS)", @Image = "(existing_hours)"] + | | +- PrimaryPrefix[@CanonicalImage = "(EXISTING_HOURS)", @Image = "(existing_hours)", @SelfModifier = false] + | | +- Expression[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | +- PrimaryPrefix[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours", @SelfModifier = false] + | | +- SimpleExpression[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | +- Column[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | | +- ID[@CanonicalImage = "EXISTING_HOURS", @Image = "existing_hours"] + | +- ExceptionHandler[@CanonicalImage = null] + | | +- QualifiedName[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | | +- UnqualifiedID[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | | +- KEYWORD_UNRESERVED[@CanonicalImage = "OTHERS", @Image = "OTHERS"] + | | +- Statement[@CanonicalImage = null] + | | +- UnlabelledStatement[@CanonicalImage = null] + | | +- Expression[@CanonicalImage = "NULL", @Image = "NULL"] + | | +- PrimaryPrefix[@CanonicalImage = "NULL", @Image = "NULL", @SelfModifier = false] + | | +- Literal[@CanonicalImage = "NULL", @Image = "NULL"] + | | +- NullLiteral[@CanonicalImage = "NULL", @Image = "NULL"] + | +- ID[@CanonicalImage = "EXISTING_PLANNED", @Image = "existing_planned"] + +- ID[@CanonicalImage = "UPDATE_PLANNED_HRS", @Image = "update_planned_hrs"] 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 index b13dc7ada0..d8cb27c197 100644 --- 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 @@ -7,7 +7,7 @@ Example code 1 - 34 + 35