diff options
-rw-r--r-- | lexers/LexSQL.cxx | 96 |
1 files changed, 72 insertions, 24 deletions
diff --git a/lexers/LexSQL.cxx b/lexers/LexSQL.cxx index 2e3bc2bb8..dc4e164b4 100644 --- a/lexers/LexSQL.cxx +++ b/lexers/LexSQL.cxx @@ -1,8 +1,10 @@ +//-*- coding: utf-8 -*- // Scintilla source code edit control /** @file LexSQL.cxx ** Lexer for SQL, including PL/SQL and SQL*Plus. + ** Improved by Jérôme LAFORGE <jerome.laforge_AT_gmail_DOT_com> from 2010 to 2012. **/ -// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2012 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> @@ -114,6 +116,24 @@ public : return sqlStatesLine; } + unsigned short int CaseMergeWithoutWhenFound (unsigned short int sqlStatesLine, bool found) { + if (found) + sqlStatesLine |= MASK_CASE_MERGE_WITHOUT_WHEN_FOUND; + else + sqlStatesLine &= ~MASK_CASE_MERGE_WITHOUT_WHEN_FOUND; + + return sqlStatesLine; + } + + unsigned short int IntoSelectStatement (unsigned short int sqlStatesLine, bool found) { + if (found) + sqlStatesLine |= MASK_INTO_SELECT_STATEMENT; + else + sqlStatesLine &= ~MASK_INTO_SELECT_STATEMENT; + + return sqlStatesLine; + } + unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) { if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) { sqlStatesLine++; @@ -144,6 +164,14 @@ public : return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0; } + bool IsIntoSelectStatement (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_SELECT_STATEMENT) != 0; + } + + bool IsCaseMergeWithoutWhenFound (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_CASE_MERGE_WITHOUT_WHEN_FOUND) != 0; + } + bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) { return (sqlStatesLine & MASK_INTO_DECLARE) != 0; } @@ -165,12 +193,14 @@ public : private : std::vector <unsigned short int> sqlStatement; enum { + MASK_NESTED_CASES = 0x01FF, + MASK_INTO_SELECT_STATEMENT = 0x0200, + MASK_CASE_MERGE_WITHOUT_WHEN_FOUND = 0x0400, + MASK_MERGE_STATEMENT = 0x0800, MASK_INTO_DECLARE = 0x1000, MASK_INTO_EXCEPTION = 0x2000, MASK_INTO_CONDITION = 0x4000, - MASK_IGNORE_WHEN = 0x8000, - MASK_MERGE_STATEMENT = 0x0800, - MASK_NESTED_CASES = 0x07FF + MASK_IGNORE_WHEN = 0x8000 }; }; @@ -574,10 +604,17 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, endFound = false; isUnfoldingIgnored = false; } - if ((!IsCommentStyle(style) && ch == ';') && sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine)) { - // This is the end of "MERGE" statement. - sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, false); - levelNext-=2; + if ((!IsCommentStyle(style) && ch == ';')) { + if (sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine)) { + // This is the end of "MERGE" statement. + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; + sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, false); + //sqlStatesCurrentLine = sqlStates.WhenThenFound(sqlStatesCurrentLine, false); + levelNext--; + } + if (sqlStates.IsIntoSelectStatement(sqlStatesCurrentLine)) + sqlStatesCurrentLine = sqlStates.IntoSelectStatement(sqlStatesCurrentLine, false); } if (options.foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { @@ -635,7 +672,10 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, s[j] = '\0'; } - if (strcmp(s, "if") == 0) { + if (!options.foldOnlyBegin && + strcmp(s, "select") == 0) { + sqlStatesCurrentLine = sqlStates.IntoSelectStatement(sqlStatesCurrentLine, true); + } else if (strcmp(s, "if") == 0) { if (endFound) { endFound = false; if (options.foldOnlyBegin && !isUnfoldingIgnored) { @@ -680,23 +720,21 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, } if ((!options.foldOnlyBegin) && strcmp(s, "case") == 0) { sqlStatesCurrentLine = sqlStates.EndCaseBlock(sqlStatesCurrentLine); - levelNext--; //again for the "end case;" and block when + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; //again for the "end case;" and block when + //sqlStatesCurrentLine = sqlStates.WhenThenFound(sqlStatesCurrentLine, false); } } else if (!options.foldOnlyBegin) { - if (strcmp(s, "case") == 0) { + if (strcmp(s, "case") == 0) sqlStatesCurrentLine = sqlStates.BeginCaseBlock(sqlStatesCurrentLine); - //for case block increment 2 times - if (!statementFound) - levelNext++; - } - - if (levelCurrent > levelNext) { + if (levelCurrent > levelNext) levelCurrent = levelNext; - } + if (!statementFound) levelNext++; + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true); statementFound = true; } else if (levelCurrent > levelNext) { // doesn't include this line into the folding block @@ -716,9 +754,13 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, options.foldAtElse && !statementFound) && strcmp(s, "else") == 0) { // prevent also ELSE is on the same line (eg. "ELSE ... END IF;") statementFound = true; - // we are in same case "} ELSE {" in C language - levelCurrent--; - + if (sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine) && sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false); + levelNext++; + } else { + // we are in same case "} ELSE {" in C language + levelCurrent--; + } } else if (strcmp(s, "begin") == 0) { levelNext++; sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false); @@ -729,6 +771,8 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, (strcmp(s, "endif") == 0)) { endFound = true; levelNext--; + if (sqlStates.IsIntoSelectStatement(sqlStatesCurrentLine) && !sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; if (levelNext < SC_FOLDLEVELBASE) { levelNext = SC_FOLDLEVELBASE; isUnfoldingIgnored = true; @@ -746,8 +790,11 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, // Don't foldind when CASE and WHEN are on the same line (with flag statementFound) (eg. "CASE selector WHEN expression1 THEN sequence_of_statements1;\n") // and same way for MERGE statement. if (!statementFound) { - levelCurrent--; - levelNext--; + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) { + levelCurrent--; + levelNext--; + } + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false); } } else if ((!options.foldOnlyBegin) && strcmp(s, "exit") == 0) { sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, true); @@ -762,7 +809,8 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, } else if ((!options.foldOnlyBegin) && strcmp(s, "merge") == 0) { sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, true); - levelNext += 2; + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true); + levelNext++; statementFound = true; } } |