From 569338276d494d8b81b78b5b52cf9d210fc402d8 Mon Sep 17 00:00:00 2001 From: Philip Liddell Date: Mon, 2 Mar 2020 16:15:53 +0000 Subject: [PATCH] Fix #2689 Allow comments and newlines within package definition --- .../database/oracle/OracleParser.java | 14 +++++---- .../flywaydb/core/internal/parser/Parser.java | 31 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/flyway-core/src/main/java/org/flywaydb/core/internal/database/oracle/OracleParser.java b/flyway-core/src/main/java/org/flywaydb/core/internal/database/oracle/OracleParser.java index 25d35aa653..2426adead8 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/internal/database/oracle/OracleParser.java +++ b/flyway-core/src/main/java/org/flywaydb/core/internal/database/oracle/OracleParser.java @@ -56,6 +56,9 @@ public class OracleParser extends Parser { + private static final Pattern PLSQL_TYPE_BODY_REGEX = Pattern.compile( + "^CREATE(\\sOR\\sREPLACE)?(\\s(NON)?EDITIONABLE)?\\sTYPE\\sBODY\\s([^\\s]*\\s)?(IS|AS)"); + private static final Pattern PLSQL_PACKAGE_BODY_REGEX = Pattern.compile( "^CREATE(\\sOR\\sREPLACE)?(\\s(NON)?EDITIONABLE)?\\sPACKAGE\\sBODY\\s([^\\s]*\\s)?(IS|AS)"); private static final StatementType PLSQL_PACKAGE_BODY_STATEMENT = new StatementType(); @@ -430,12 +433,11 @@ protected void adjustBlockDepth(ParserContext context, List tokens, Token int parensDepth = keyword.getParensDepth(); if ("BEGIN".equals(keywordText) - || (CONTROL_FLOW_KEYWORDS.contains(keywordText) && !containsWithinLast(1, tokens, parensDepth, "END")) - || ("TRIGGER".equals(keywordText) && containsWithinLast(1, tokens, parensDepth, "COMPOUND")) - || (("AS".equals(keywordText) || "IS".equals(keywordText)) && ( - containsWithinLast(4, tokens, parensDepth, "PACKAGE") - || containsWithinLast(3, tokens, parensDepth, "PACKAGE", "BODY") - || containsWithinLast(3, tokens, parensDepth, "TYPE", "BODY"))) + || (CONTROL_FLOW_KEYWORDS.contains(keywordText) && !lastTokenIs(tokens, parensDepth, "END")) + || ("TRIGGER".equals(keywordText) && lastTokenIs(tokens, parensDepth, "COMPOUND")) + || doTokensMatchPattern(tokens, keyword, PLSQL_PACKAGE_BODY_REGEX) + || doTokensMatchPattern(tokens, keyword, PLSQL_PACKAGE_DEFINITION_REGEX) + || doTokensMatchPattern(tokens, keyword, PLSQL_TYPE_BODY_REGEX) ) { context.increaseBlockDepth(); } else if ("END".equals(keywordText)) { diff --git a/flyway-core/src/main/java/org/flywaydb/core/internal/parser/Parser.java b/flyway-core/src/main/java/org/flywaydb/core/internal/parser/Parser.java index 88b09615cd..5afa4be3b3 100644 --- a/flyway-core/src/main/java/org/flywaydb/core/internal/parser/Parser.java +++ b/flyway-core/src/main/java/org/flywaydb/core/internal/parser/Parser.java @@ -365,27 +365,24 @@ private static boolean containsLowerCase(String text) { } /** - * Checks if the specified token texts are found consecutively within the last tokens in the list + * Returns true if the previous token matches the tokenText */ - protected static boolean containsWithinLast(int count, List tokens, int parensDepth, String... consecutiveTokenTexts) { - int j = consecutiveTokenTexts.length - 1; - int remaining = count; - for (int i = tokens.size() - 1; i >= 0 && remaining > 0; i--) { + protected static boolean lastTokenIs(List tokens, int parensDepth, String tokenText) { + for (int i = tokens.size()-1; i >= 0; i--) { + Token previousToken = tokens.get(i); + // Only consider tokens at the same parenthesis depth - if (tokens.get(i).getParensDepth() != parensDepth) { + if (previousToken.getParensDepth() != parensDepth) { continue; } - if (consecutiveTokenTexts[j].equals(tokens.get(i).getText())) { - if (j == 0) { - return true; - } - j--; - } else if (j < consecutiveTokenTexts.length - 1) { - // Token texts weren't consecutive, so reset - j = consecutiveTokenTexts.length - 1; + // Skip over comments and blank lines + if (previousToken.getType() == TokenType.COMMENT || previousToken.getType() == TokenType.BLANK_LINES) { + continue; } - remaining--; + + return tokenText.equals(previousToken.getText()); } + return false; } @@ -402,7 +399,9 @@ protected static boolean doTokensMatchPattern(List previousTokens, Token break; } - tokenStrings.add(prevToken.getText()); + if (prevToken.getType() == TokenType.KEYWORD) { + tokenStrings.add(prevToken.getText()); + } } StringBuilder builder = new StringBuilder();