Skip to content

Commit

Permalink
Fix #3025: check that attached keywords are on the same line
Browse files Browse the repository at this point in the history
  • Loading branch information
DoodleBobBuffPants committed Dec 10, 2020
1 parent 47485ce commit 82102c8
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ protected void adjustBlockDepth(ParserContext context, List<Token> tokens, Token
int parensDepth = keyword.getParensDepth();

if ("BEGIN".equals(keywordText)
|| (CONTROL_FLOW_KEYWORDS.contains(keywordText) && !precedingEndAttachesToThisKeyword(tokens, parensDepth, context, keywordText))
|| (CONTROL_FLOW_KEYWORDS.contains(keywordText) && !precedingEndAttachesToThisKeyword(tokens, parensDepth, context, keyword))
|| ("TRIGGER".equals(keywordText) && lastTokenIs(tokens, parensDepth, "COMPOUND"))
|| doTokensMatchPattern(tokens, keyword, PLSQL_PACKAGE_BODY_REGEX)
|| doTokensMatchPattern(tokens, keyword, PLSQL_PACKAGE_DEFINITION_REGEX)
Expand All @@ -479,19 +479,20 @@ protected void adjustBlockDepth(ParserContext context, List<Token> tokens, Token
TokenType tokenType = keyword.getType();
if (context.getStatementType() == PLSQL_PACKAGE_BODY_STATEMENT && (TokenType.EOF == tokenType || TokenType.DELIMITER == tokenType) && context.getBlockDepth() == 1) {
context.decreaseBlockDepth();
return;
}
}

private boolean precedingEndAttachesToThisKeyword(List<Token> tokens, int parensDepth, ParserContext context, String keywordText) {
private boolean precedingEndAttachesToThisKeyword(List<Token> tokens, int parensDepth, ParserContext context, Token keyword) {
// Normally IF, LOOP and CASE all pair up with END IF, END LOOP, END CASE
// However, CASE ... END is valid in expressions, so in code such as
// FOR i IN 1 .. CASE WHEN foo THEN 5 ELSE 6 END
// LOOP
// ...
// END LOOP
// the first END does *not* attach to the subsequent LOOP. The same is possible with $IF ... $END constructions
return lastTokenIs(tokens, parensDepth, "END") && keywordText.equals(context.getLastClosedBlockInitiator());
return lastTokenIs(tokens, parensDepth, "END") &&
lastTokenIsOnLine(tokens, parensDepth, keyword.getLine()) &&
keyword.getText().equals(context.getLastClosedBlockInitiator());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,18 @@ protected static boolean lastTokenIs(List<Token> tokens, int parensDepth, String
return tokenText.equals(previousToken.getText());
}

/**
* Returns true if the previous token is on the given line
*/
protected static boolean lastTokenIsOnLine(List<Token> tokens, int parensDepth, int line) {
Token previousToken = getPreviousToken(tokens, parensDepth);
if (previousToken == null) {
return false;
}

return previousToken.getLine() == line;
}

/**
* Check if the previous tokens in the statement at the same depth as the current token match the provided regex
*/
Expand Down

0 comments on commit 82102c8

Please sign in to comment.