Allow excluding lines from the parser using comments -- PMD-EXCLUDE-BEGIN and -- PMD-EXCLUDE-END. This is to workaround bugs in the PL/SQL parser - some valid statements cannot be parsed. by wrapping them inside PMD-EXCLUDE-BEGIN/END the parser just ignores them and continues parsing with the next line.

This commit is contained in:
hvbargen
2021-02-26 19:11:27 +01:00
parent 475f750216
commit 46e368a3e0
2 changed files with 57 additions and 4 deletions

View File

@ -3416,7 +3416,7 @@ ASTPrimaryPrefix PrimaryPrefix() :
| LOOKAHEAD(Literal()) ( simpleNode = Literal() ) { sb.append(simpleNode.getImage()) ; }
| LOOKAHEAD(SimpleExpression()) ( simpleNode = SimpleExpression() ) { sb.append(simpleNode.getImage()); }
| ( simpleNode =Name() ) { sb.append(simpleNode.getImage()) ; }
| SelectStatement()
// | SelectStatement()
| LOOKAHEAD("(" <SELECT>) "(" SelectStatement() ")"
| LOOKAHEAD(<WITH>) (<WITH>) {sb.append("WITH ..."); } Skip2NextTerminator(null,";")
| LOOKAHEAD(("(")+ <WITH>) ("(") {sb.append("(WITH ..."); } Skip2NextTerminator("(",")") ")"
@ -4593,6 +4593,51 @@ SKIP :
" " | "\t" | "\f"
}
/*
This Grammar (or JavaCC) has several bugs.
Currently (2021-02-26) it fails for things like
- dbms_lob.trim(...),
- scalar subqueries in the WHERE-clause,
- TREAT(object AS type),
just to name a few.
Running PMD over a code base of approx. 1100 DDL scripts
from a commercial product, the parser failed for 182 files.
About 10% of these parsing errors actually showed flaws in the code,
e.g. "\u2013" instead of "-", or utf-8 encoding instead of windows-1252
(which is the standard for the product's scripts).
Still, ~ 15% of perfectly valid DDL scripts could not be parsed by PMD.
Nevertheless it should be best practice to call PMD for _every_ DDL script.
Thus, we introduce the following workaround to cope with the situation.
We introduce two special comments PMD-EXCLUDE-BEGIN and PMD-EXCLUDE-END
which cause PMD to treat the source inbetween these comments more or less
like a multi-line comment, or in other words, just not try to parse them.
It is good practice to include a reason for excluding inside the
-- PMD-EXCUDE-BEGIN comment.
The PMD-EXCLUDE-BEGIN and PMD-EXLUDE-END comment lines must not contain
other statements, e.g. do_xy(); -- PMD-EXCLUDE-BEGIN is invalid.
Example:
begin
do_something();
-- PMD-EXCLUDE-BEGIN: PMD does not like dbms_lob.trim (clash with TrimExpression)
dbms_lob.trim(the_blob, 1000);
-- PMD-EXCLUDE-END
do_something_else();
end;
A future version of PMD might pass the existence of the exclusion to the AST
as an "ASTParsingExclusion" statement, perhaps including the comment and the
excluded source, to allow for detecting this workaround with a rule.
But for now, it is just skipped.
*/
/* COMMENTS */
MORE :
@ -4600,6 +4645,14 @@ MORE :
<"/**" ~["/"]> : IN_FORMAL_COMMENT
|
"/*" : IN_MULTI_LINE_COMMENT
|
<"--" (" ")* "PMD-EXCLUDE-BEGIN" (" ")* (":")? (" ")* (~["\n", "\r"])*> : IN_PARSING_EXCLUSION
}
<IN_PARSING_EXCLUSION>
SPECIAL_TOKEN :
{
<PARSING_EXCLUSION: "--" (" ")* "PMD-EXCLUDE-END" (~["\n", "\r"])* > : DEFAULT
}
SPECIAL_TOKEN :
@ -4635,7 +4688,7 @@ SKIP :
*/
<IN_FORMAL_COMMENT, IN_MULTI_LINE_COMMENT,
IN_SQL_STATEMENT_ENDED_SEMICOLON>
IN_SQL_STATEMENT_ENDED_SEMICOLON, IN_PARSING_EXCLUSION>
MORE :
{
< ~[] >

View File

@ -17,7 +17,7 @@ IF ioFPOobj IS NOT OF TYPE (ONLY FPOGE_OBJ) THEN
loFPOGE_OBJ:=treat(ioFPOobj AS FPOGE_OBJ);
end if;
loFPOGE_OBJ:=SELECT A FROM persons p WHERE VALUE(p) IS OF TYPE (employee_t);
loFPOGE_OBJ:=SELECT A FROM persons p WHERE VALUE(p) IS NOT OF TYPE (ONLY employee_t, other_t);
SELECT A into lo_FPOGE_OBJ FROM persons p WHERE VALUE(p) IS OF TYPE (employee_t);
SELECT A into lo_FPOGE_OBJ FROM persons p WHERE VALUE(p) IS NOT OF TYPE (ONLY employee_t, other_t);
end;