diff --git a/pmd-plsql/etc/grammar/PldocAST.jjt b/pmd-plsql/etc/grammar/PldocAST.jjt index 37cf0704f6..cfe52e8330 100644 --- a/pmd-plsql/etc/grammar/PldocAST.jjt +++ b/pmd-plsql/etc/grammar/PldocAST.jjt @@ -249,27 +249,7 @@ PARSER_END(PLSQLParser) TOKEN_MGR_DECLS : { - public static final class Exclusion { - - public int beginLine; - public int endLine; - public String source = null; - public String reason = null; - - public Exclusion(int b, int e, String s) { - this.beginLine = b; - this.endLine = e; - this.source = s; - int i1 = s.toUpperCase().indexOf("PMD-EXCLUDE-BEGIN"); - int i2 = s.toUpperCase().indexOf("\n"); - this.reason = s.substring(i1 + 17, i2).trim(); - if (this.reason.startsWith(":")) { - this.reason = this.reason.substring(2).trim(); - } - } - } - - public List exclusions = new ArrayList(); + public List exclusions = new ArrayList(); } @@ -313,11 +293,11 @@ ASTInput Input(String sourcecode) : )* { jjtThis.setSourcecode(sourcecode); - List exclusions = token_source.exclusions; + List exclusions = token_source.exclusions; if (exclusions != null) { - // System.err.println("Exclusions:"); + // System.err.println("ParsingExclusions:"); for (int i=0; i | | ) * | "@" ( <_CHARACTER> | | ) * | | "ACC" - | "ARCHIVE LOG LIST" + | LOOKAHEAD({isKeyword("ARCHIVE")}) KEYWORD("ARCHIVE") "LOG LIST" | | "BREAK" | "BTITLE" @@ -413,7 +393,7 @@ ASTSqlPlusCommand SqlPlusCommand() : // Attach Library | "." ) - { sb.append(token.getImage()) ; sb.append(" ") ; sb.append(Read2NextTokenOccurrence(EOL).getImage()) ; + { sb.append(token.getImage()) ; sb.append(" ") ; sb.append(Read2NextTokenOccurrence(EOL)) ; } ) { jjtThis.setImage(sb.toString()) ; return jjtThis ; } @@ -1206,11 +1186,11 @@ ASTRead2NextOccurrence Read2NextOccurrence(String target) : { jjtThis.setImage(sb.toString()) ; jjtThis.value = sb.toString(); return jjtThis ;} } +JAVACODE /* Read Tokens up to but not including the target token. */ -ASTRead2NextTokenOccurrence Read2NextTokenOccurrence(int target) : -{ +String Read2NextTokenOccurrence(int target) #void { StringBuilder sb = new StringBuilder(); Token nextToken = getToken(1); while (nextToken.kind!=target @@ -1223,9 +1203,7 @@ ASTRead2NextTokenOccurrence Read2NextTokenOccurrence(int target) : sb.append(' '); nextToken = getToken(1); } -} -{ - { jjtThis.setImage(sb.toString()) ; jjtThis.value = sb.toString(); return jjtThis ;} + return sb.toString(); } /* @@ -4711,7 +4689,7 @@ SPECIAL_TOKEN : { String excluded_source = matchedToken.getImage(); - exclusions.add(new Exclusion(matchedToken.getBeginLine(), matchedToken.getEndLine(), excluded_source)); + exclusions.add(new ParsingExclusion(matchedToken.getBeginLine(), matchedToken.getEndLine(), excluded_source)); } : DEFAULT } 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 865a91e4f3..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 @@ -165,11 +165,6 @@ public class PLSQLParserVisitorAdapter implements PLSQLParserVisitor { public Object visit(ASTRead2NextOccurrence node, Object data) { return visit((PLSQLNode) node, data); } - - @Override - public Object visit(ASTRead2NextTokenOccurrence node, Object data) { - return visit((PLSQLNode) node, data); - } @Override public Object visit(ASTReadPastNextOccurrence node, Object data) { diff --git a/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusion.java b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusion.java new file mode 100644 index 0000000000..82e91fc710 --- /dev/null +++ b/pmd-plsql/src/main/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusion.java @@ -0,0 +1,40 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.plsql.ast; + +import java.util.Locale; + +/** + * This represents an exclusion of a line range from parsing. + */ +public final class ParsingExclusion { + + public static final String BEGIN_MARKER = "PMD-EXCLUDE-BEGIN"; + public static final String END_MARKER = "PMD-EXCLUDE-END"; + public static final int LEN_BEGIN_MARKER = BEGIN_MARKER.length(); + + public int beginLine; + public int endLine; + public String source = null; + + + /** + * The reason is the comment text in the first line after the beginMarker. + */ + public String reason = null; + + public ParsingExclusion(int beginLine, int endLine, String source) { + this.beginLine = beginLine; + this.endLine = endLine; + this.source = source; + final String sourceUpper = source.toUpperCase(Locale.US); + int i1 = sourceUpper.indexOf(BEGIN_MARKER); + int i2 = sourceUpper.indexOf("\n"); + this.reason = source.substring(i1 + LEN_BEGIN_MARKER, i2).trim(); + if (this.reason.startsWith(":")) { + this.reason = this.reason.substring(2).trim(); + } + } +} 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 587c9bc0aa..8f091dae61 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 @@ -161,7 +161,6 @@ import net.sourceforge.pmd.lang.plsql.ast.ASTQueryBlock; import net.sourceforge.pmd.lang.plsql.ast.ASTQueryPartitionClause; import net.sourceforge.pmd.lang.plsql.ast.ASTRaiseStatement; import net.sourceforge.pmd.lang.plsql.ast.ASTRead2NextOccurrence; -import net.sourceforge.pmd.lang.plsql.ast.ASTRead2NextTokenOccurrence; import net.sourceforge.pmd.lang.plsql.ast.ASTReadPastNextOccurrence; import net.sourceforge.pmd.lang.plsql.ast.ASTReferencesClause; import net.sourceforge.pmd.lang.plsql.ast.ASTRegexpLikeCondition; @@ -482,11 +481,6 @@ public abstract class AbstractPLSQLRule extends AbstractRule implements PLSQLPar public Object visit(ASTRead2NextOccurrence node, Object data) { return visit((PLSQLNode) node, data); } - - @Override - public Object visit(ASTRead2NextTokenOccurrence node, Object data) { - return visit((PLSQLNode) node, data); - } @Override public Object visit(ASTReadPastNextOccurrence node, Object data) { diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParserExclusionTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusionTest.java similarity index 59% rename from pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParserExclusionTest.java rename to pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusionTest.java index 7a7fb2c668..38fda8ab18 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParserExclusionTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusionTest.java @@ -8,10 +8,10 @@ import org.junit.Test; import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; -public class ParserExclusionTest extends AbstractPLSQLParserTst { +public class ParsingExclusionTest extends AbstractPLSQLParserTst { @Test - public void parseParserExclusion() { - plsql.parseResource("ParserExclusion.sql"); + public void parseParsingExclusion() { + plsql.parseResource("ParsingExclusion.sql"); } } diff --git a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementTest.java b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementTest.java index 145f6f495b..357ed52145 100644 --- a/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementTest.java +++ b/pmd-plsql/src/test/java/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementTest.java @@ -19,12 +19,7 @@ public class SelectIntoStatementTest extends AbstractPLSQLParserTst { @Test public void testParsingExample1() { - try { - plsql.parseResource("SelectIntoStatementExample1.pls"); - throw new AssertionError("The last line of this example must cause a ParseException."); - } catch (ParseException e) { - // This is expected, because the last line of the example is valid only inside BEGIN END. - } + plsql.parseResource("SelectIntoStatementExample1.pls"); } @Test @@ -47,6 +42,11 @@ public class SelectIntoStatementTest extends AbstractPLSQLParserTst { plsql.parseResource("SelectIntoStatementExample5.pls"); } + @Test(expected = ParseException.class) + public void testParsingExample6Invalid() { + plsql.parseResource("SelectIntoStatementExample6Invalid.pls"); + } + @Test public void testParsingWithFunctionCall() { plsql.parseResource("SelectIntoStatementFunctionCall.pls"); diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ParserExclusion.sql b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusion.sql similarity index 100% rename from pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ParserExclusion.sql rename to pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/ParsingExclusion.sql diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample1.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample1.pls index 137703c569..9170365688 100644 --- a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample1.pls +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample1.pls @@ -10,5 +10,4 @@ BEGIN WHERE employee_id = 100; END; -DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus)); -/ \ No newline at end of file +exec DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus)) diff --git a/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample6Invalid.pls b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample6Invalid.pls new file mode 100644 index 0000000000..137703c569 --- /dev/null +++ b/pmd-plsql/src/test/resources/net/sourceforge/pmd/lang/plsql/ast/SelectIntoStatementExample6Invalid.pls @@ -0,0 +1,14 @@ +-- +-- Example 2-25 Assigning Value to Variable with SELECT INTO Statement +-- From: https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-language-fundamentals.html#GUID-664BFFEA-063A-48B6-A65B-95225EDDED59 +-- +DECLARE + bonus NUMBER(8,2); +BEGIN + SELECT salary * 0.10 INTO bonus + FROM employees + WHERE employee_id = 100; +END; + +DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus)); +/ \ No newline at end of file