diff options
Diffstat (limited to 'lexers/LexMySQL.cxx')
| -rw-r--r-- | lexers/LexMySQL.cxx | 196 | 
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++; +  }  }  //-------------------------------------------------------------------------------------------------- | 
