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:
@ -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 :
|
||||
{
|
||||
< ~[] >
|
||||
|
@ -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;
|
Reference in New Issue
Block a user