diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index adad5e462f..ec48d15af6 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -171,6 +171,10 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati * pmd-apex * {% jdoc apex::lang.apex.metrics.ApexMetrics %}, {% jdoc apex::lang.apex.metrics.ApexMetricsComputer %} +#### PLSQL AST + +The production and node `ASTCursorBody` was unnecessary, not used and has been removed. Cursors have been already +parsed as `ASTCursorSpecification`. ### External Contributions @@ -186,6 +190,7 @@ methods on {% jdoc apex::lang.apex.ast.ApexParserVisitor %} and its implementati * [#2321](https://github.com/pmd/pmd/pull/2321): \[apex] Support switch statements correctly in Cognitive Complexity - [Gwilym Kuiper](https://github.com/gwilymatgearset) * [#2326](https://github.com/pmd/pmd/pull/2326): \[plsql] Added XML functions to parser: extract(xml), xml_root and fixed xml_forest - [Piotr Szymanski](https://github.com/szyman23) * [#2327](https://github.com/pmd/pmd/pull/2327): \[plsql] Parsing of WHERE CURRENT OF added - [Piotr Szymanski](https://github.com/szyman23) +* [#2331](https://github.com/pmd/pmd/pull/2331): \[plsql] Fix in Comment statement - [Piotr Szymanski](https://github.com/szyman23) {% endtocmaker %} diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 65b527e53c..dc448c027d 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -268,9 +268,9 @@ ASTInput Input(String sourcecode) : {} | LOOKAHEAD(6) Global() | (LOOKAHEAD(6) DDLCommand())+ | LOOKAHEAD(2) SqlPlusCommand() - | UpdateStatement() - | DeleteStatement() - | InsertStatement() + | UpdateStatement() [";"] + | DeleteStatement() [";"] + | InsertStatement() [";"] | SelectStatement() [";"] |(|||||) ReadPastNextOccurrence(";") //Ignore SQL statements in scripts ) @@ -477,9 +477,7 @@ ASTDeclarativeUnit DeclarativeUnit() : ProgramUnit() | LOOKAHEAD(4) VariableOrConstantDeclaration() | - LOOKAHEAD(2) CursorSpecification() | - CursorBody() | CollectionDeclaration() | //ProgramUnit() //|TypeMethod() @@ -1059,54 +1057,48 @@ void SkipPastNextOccurrence(String target) : { return; } } -/* - Read Tokens up to but not including the target Token.kind. -*/ +/** + * Read Tokens up to but not including the target Token.kind. + */ void Skip2NextTokenOccurrence(int target) : { - Token nextToken = getToken(1); - Token specToken = null ; - while (nextToken.kind!=target - && (null == nextToken.specialToken || nextToken.specialToken.kind!=target ) //In case the target is a Special Token - && nextToken.kind!=EOF //SRT 20110521 - Prevent endless loop when target does not exist in the input stream - ) - { - /* - Check if the target appears as a SpecialToken - - - nextToken.specialToken points to the _LAST_ of any SpecialTokens before the current normal Token. - - It is the head of a doubly-linked list: - - The ${specialToken}.specialToken field POINTS BACKWARDS TOWARDS the FIRST occurring SpecialToken - The ${specialToken}.next field POINTS FORWARDS to to the LAST occurring SpecialToken - - This means that if the program is interested in a specific SpecialToken, it must examine the linked list for every Token which has nexToken.specialToken != null. - - */ - specToken = nextToken.specialToken; - if (null!= specToken) + Token nextToken = getToken(1); + Token specToken = null ; + while (nextToken.kind!=target + && (null == nextToken.specialToken || nextToken.specialToken.kind!=target ) //In case the target is a Special Token + && nextToken.kind!=EOF) //SRT 20110521 - Prevent endless loop when target does not exist in the input stream { - //Walk backwards through the list looking for this Token as a Special Token - while (specToken != null && specToken.kind != target) - { - specToken = specToken.specialToken; - } - - //We have found the target as a SpecialToken - break out of normal Token search - if (null != specToken && specToken.kind == target) - { - break; + /* + * Check if the target appears as a SpecialToken + * + * nextToken.specialToken points to the _LAST_ of any SpecialTokens before the current normal Token. + * + * It is the head of a doubly-linked list: + * + * The ${specialToken}.specialToken field POINTS BACKWARDS TOWARDS the FIRST occurring SpecialToken + * The ${specialToken}.next field POINTS FORWARDS to to the LAST occurring SpecialToken + * + * This means that if the program is interested in a specific SpecialToken, it must examine the linked list for every Token which has nexToken.specialToken != null. + */ + specToken = nextToken.specialToken; + if (null!= specToken) { + //Walk backwards through the list looking for this Token as a Special Token + while (specToken != null && specToken.kind != target) { + specToken = specToken.specialToken; + } } - } - nextToken = getNextToken(); - nextToken = getToken(1); - } + //We have found the target as a SpecialToken - break out of normal Token search + if (null != specToken && specToken.kind == target) { + break; + } + + nextToken = getNextToken(); + nextToken = getToken(1); + } } { - { return; } + { return; } } /* @@ -2890,37 +2882,16 @@ ASTCursorUnit CursorUnit() : { jjtThis.setImage(simpleNode.getImage()) ; return jjtThis ; } } -ASTCursorSpecification CursorSpecification() : {} +/** + * This is in plsql actually called CursorDeclaration + * or CursorDefinition. + */ +ASTCursorSpecification CursorSpecification() : {} { - CursorUnit() - { return jjtThis ; } + CursorUnit() + { return jjtThis ; } } -ASTCursorBody CursorBody() : {} -{ - CursorUnit() -// /**/ - { return jjtThis ; } -} - - - -// ============================================================================ -// E X P R E S S I O N S -// ============================================================================ - -/* -String expression() : -{} -{ - "test" - { return ""; } -} -*/ - - - - ASTExpression Expression() : { PLSQLNode simpleNode = null; @@ -3925,12 +3896,10 @@ ASTComment Comment() : ( [LOOKAHEAD(ID()"."ID()"."ID()) ID()"."] ID() "." ID()) ) StringLiteral() - ";" + (";" | "/") { return jjtThis ; } } - - ASTTypeMethod TypeMethod() : { } @@ -4466,9 +4435,7 @@ ASTCompoundTriggerBlock CompoundTriggerBlock() : SubTypeDefinition() | LOOKAHEAD(4) VariableOrConstantDeclaration() | - LOOKAHEAD(2) CursorSpecification() | - CursorBody() | CollectionDeclaration() | ProgramUnit() )* 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 c9631b54b0..81e247e122 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 @@ -341,16 +341,6 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { return visit((PLSQLNode) node, data); } - @Override - public Object visit(ASTCursorSpecification node, Object data) { - return visit((PLSQLNode) node, data); - } - - @Override - public Object visit(ASTCursorBody node, Object data) { - return visit((PLSQLNode) node, data); - } - @Override public Object visit(ASTExpression node, Object data) { return visit((PLSQLNode) node, data); @@ -1121,4 +1111,9 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { public Object visit(ASTWithClause node, Object data) { return visit((PLSQLNode) node, data); } + + @Override + public Object visit(ASTCursorSpecification 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 f5af7d86e5..f1c776c8dc 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 @@ -51,7 +51,6 @@ import net.sourceforge.pmd.lang.plsql.ast.ASTConditionalInsertClause; import net.sourceforge.pmd.lang.plsql.ast.ASTConditionalOrExpression; import net.sourceforge.pmd.lang.plsql.ast.ASTContinueStatement; import net.sourceforge.pmd.lang.plsql.ast.ASTCrossOuterApplyClause; -import net.sourceforge.pmd.lang.plsql.ast.ASTCursorBody; import net.sourceforge.pmd.lang.plsql.ast.ASTCursorForLoopStatement; import net.sourceforge.pmd.lang.plsql.ast.ASTCursorSpecification; import net.sourceforge.pmd.lang.plsql.ast.ASTCursorUnit; @@ -657,16 +656,6 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar return visit((PLSQLNode) node, data); } - @Override - public Object visit(ASTCursorSpecification node, Object data) { - return visit((PLSQLNode) node, data); - } - - @Override - public Object visit(ASTCursorBody node, Object data) { - return visit((PLSQLNode) node, data); - } - @Override public Object visit(ASTExpression node, Object data) { return visit((PLSQLNode) node, data); @@ -1441,6 +1430,11 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar return visit((PLSQLNode) node, data); } + @Override + public Object visit(ASTCursorSpecification 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/MultipleDDLStatementsTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/MultipleDDLStatementsTest.java index d318911662..5b21d5711a 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/MultipleDDLStatementsTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/MultipleDDLStatementsTest.java @@ -17,9 +17,9 @@ public class MultipleDDLStatementsTest extends AbstractPLSQLParserTst { public void parseDDLCommands() throws Exception { ASTInput input = plsql.parseResource("DDLCommands.sql"); List ddlcommands = input.findDescendantsOfType(ASTDDLCommand.class); - Assert.assertEquals(4, ddlcommands.size()); + Assert.assertEquals(6, ddlcommands.size()); List comments = input.findDescendantsOfType(ASTComment.class); - Assert.assertEquals(3, comments.size()); + Assert.assertEquals(5, comments.size()); Assert.assertEquals("'abbreviated job title'", comments.get(0).getFirstChildOfType(ASTStringLiteral.class).getImage()); } } diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/DDLCommands.sql b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/DDLCommands.sql index 5833689339..d6b4e6714b 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/DDLCommands.sql +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/DDLCommands.sql @@ -5,3 +5,7 @@ COMMENT ON COLUMN employees.job_id IS 'abbreviated job title'; DROP TABLE employees; COMMENT ON COLUMN employees.job_id IS 'abbreviated job title'; + +comment on COLUMN employees.job_id is 'abbreviated job title' +/ +comment on COLUMN employees.job_id is 'abbreviated job title'; \ No newline at end of file