aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lexers/LexMySQL.cxx196
1 files changed, 104 insertions, 92 deletions
diff --git a/lexers/LexMySQL.cxx b/lexers/LexMySQL.cxx
index 2e4fcef13..1b5ac0315 100644
--- a/lexers/LexMySQL.cxx
+++ b/lexers/LexMySQL.cxx
@@ -324,10 +324,10 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
-
- bool endFound = false;
- bool whenFound = false;
- bool elseFound = false;
+
+ bool endPending = false;
+ bool whenPending = false;
+ bool elseIfPending = false;
char nextChar = styler.SafeGetCharAt(startPos);
for (unsigned int i = startPos; length > 0; i++, length--)
@@ -335,11 +335,11 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL
int stylePrev = style;
style = styleNext;
styleNext = styler.StyleAt(i + 1);
-
+
char currentChar = nextChar;
nextChar = styler.SafeGetCharAt(i + 1);
bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n');
-
+
switch (style)
{
case SCE_MYSQL_COMMENT:
@@ -361,7 +361,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL
break;
case SCE_MYSQL_COMMENTLINE:
if (foldComment)
- {
+ {
// Not really a standard, but we add support for single line comments
// with special curly braces syntax as foldable comments too.
// MySQL needs -- comments to be followed by space or control char
@@ -378,18 +378,42 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL
}
break;
case SCE_MYSQL_HIDDENCOMMAND:
+ if (endPending)
+ {
+ // A conditional command is not a white space so it should end the current block
+ // before opening a new one.
+ endPending = false;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
if (style != stylePrev)
levelNext++;
else
if (style != styleNext)
+ {
levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
break;
case SCE_MYSQL_OPERATOR:
+ if (endPending)
+ {
+ endPending = false;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
if (currentChar == '(')
levelNext++;
else
if (currentChar == ')')
+ {
levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
break;
case SCE_MYSQL_MAJORKEYWORD:
case SCE_MYSQL_KEYWORD:
@@ -398,110 +422,98 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL
// Reserved and other keywords.
if (style != stylePrev)
{
- bool beginFound = MatchIgnoreCase(styler, i, "begin");
- bool ifFound = MatchIgnoreCase(styler, i, "if");
- bool thenFound = MatchIgnoreCase(styler, i, "then");
- bool whileFound = MatchIgnoreCase(styler, i, "while");
- bool loopFound = MatchIgnoreCase(styler, i, "loop");
- bool repeatFound = MatchIgnoreCase(styler, i, "repeat");
-
- if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound))
+ // END decreases the folding level, regardless which keyword follows.
+ bool endFound = MatchIgnoreCase(styler, i, "end");
+ if (endPending)
{
- endFound = false;
levelNext--;
if (levelNext < SC_FOLDLEVELBASE)
levelNext = SC_FOLDLEVELBASE;
-
- // Note that "else" is special here. It may or may not be followed by an "if .. then",
- // but in any case the level stays the same. When followed by an "if .. then" the level
- // will be increased later, if not, then at eol.
}
else
- if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else"))
+ if (!endFound)
{
- levelNext--;
- elseFound = true;
- }
- else
- if (!foldOnlyBegin && thenFound)
- {
- if (whenFound)
- whenFound = false;
- else
- levelNext++;
- }
+ if (MatchIgnoreCase(styler, i, "begin"))
+ levelNext++;
else
- if (ifFound)
- elseFound = false;
- else
- if (MatchIgnoreCase(styler, i, "when"))
- whenFound = true;
+ {
+ if (!foldOnlyBegin)
+ {
+ bool whileFound = MatchIgnoreCase(styler, i, "while");
+ bool loopFound = MatchIgnoreCase(styler, i, "loop");
+ bool repeatFound = MatchIgnoreCase(styler, i, "repeat");
+ bool caseFound = MatchIgnoreCase(styler, i, "case");
+
+ if (whileFound || loopFound || repeatFound || caseFound)
+ levelNext++;
else
{
- if (beginFound)
- levelNext++;
- else
- if (!foldOnlyBegin && (loopFound || repeatFound || whileFound))
+ // IF alone does not increase the fold level as it is also used in non-block'ed
+ // code like DROP PROCEDURE blah IF EXISTS.
+ // Instead THEN opens the new level (if not part of an ELSEIF or WHEN (case) branch).
+ if (MatchIgnoreCase(styler, i, "then"))
+ {
+ if (!elseIfPending && !whenPending)
+ levelNext++;
+ else
{
- if (endFound)
- endFound = false;
- else
- levelNext++;
+ elseIfPending = false;
+ whenPending = false;
}
- else
- if (MatchIgnoreCase(styler, i, "end"))
- {
- // Multiple "end" in a row are counted multiple times!
- if (endFound)
- {
- levelNext--;
- if (levelNext < SC_FOLDLEVELBASE)
- levelNext = SC_FOLDLEVELBASE;
- }
- endFound = true;
- whenFound = false;
- }
+ }
+ else
+ {
+ // Neither of if/then/while/loop/repeat/case, so check for
+ // sub parts of IF and CASE.
+ if (MatchIgnoreCase(styler, i, "elseif"))
+ elseIfPending = true;
+ if (MatchIgnoreCase(styler, i, "when"))
+ whenPending = true;
+ }
}
+ }
+ }
+ }
+
+ // Keep the current end state for the next round.
+ endPending = endFound;
+ }
+ break;
+
+ default:
+ if (!isspace(currentChar) && endPending)
+ {
+ // END followed by a non-whitespace character (not covered by other cases like identifiers)
+ // also should end a folding block. Typical case: END followed by self defined delimiter.
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
}
break;
}
-
- // Handle the case of a trailing end without an if / while etc, as in the case of a begin.
- if (endFound)
- {
- endFound = false;
- levelNext--;
- if (levelNext < SC_FOLDLEVELBASE)
- levelNext = SC_FOLDLEVELBASE;
- }
-
- if (atEOL)
+
+ if (atEOL)
{
- if (elseFound)
- {
- levelNext++;
- elseFound = false;
- }
-
- int levelUse = levelCurrent;
- int lev = levelUse | levelNext << 16;
- if (visibleChars == 0 && foldCompact)
- lev |= SC_FOLDLEVELWHITEFLAG;
- if (levelUse < levelNext)
- lev |= SC_FOLDLEVELHEADERFLAG;
- if (lev != styler.LevelAt(lineCurrent))
- styler.SetLevel(lineCurrent, lev);
-
- lineCurrent++;
- levelCurrent = levelNext;
- visibleChars = 0;
- endFound = false;
- whenFound = false;
- }
+ // Apply the new folding level to this line.
+ // Leave pending states as they are otherwise a line break will de-sync
+ // code folding and valid syntax.
+ int levelUse = levelCurrent;
+ int lev = levelUse | levelNext << 16;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ if (levelUse < levelNext)
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ if (lev != styler.LevelAt(lineCurrent))
+ styler.SetLevel(lineCurrent, lev);
+
+ lineCurrent++;
+ levelCurrent = levelNext;
+ visibleChars = 0;
+ }
if (!isspacechar(currentChar))
- visibleChars++;
- }
+ visibleChars++;
+ }
}
//--------------------------------------------------------------------------------------------------