summaryrefslogtreecommitdiffstats
path: root/scintilla/lexers/LexSQL.cxx
diff options
context:
space:
mode:
authorXhmikosR <xhmikosr@users.sourceforge.net>2011-01-12 13:13:08 +0000
committerXhmikosR <xhmikosr@users.sourceforge.net>2011-01-12 13:13:08 +0000
commitdf90ee82751705f0000ee624c83e0726bd367d79 (patch)
tree691f087c024e4166031e583beb343ff48ac9c4d2 /scintilla/lexers/LexSQL.cxx
parent6e29cd82d8b3547aa56e822a213eb3a82d6d0b54 (diff)
downloadnotepad2-mod-df90ee82751705f0000ee624c83e0726bd367d79.zip
notepad2-mod-df90ee82751705f0000ee624c83e0726bd367d79.tar.gz
notepad2-mod-df90ee82751705f0000ee624c83e0726bd367d79.tar.bz2
update scintilla
git-svn-id: https://notepad2-mod.googlecode.com/svn/trunk@375 28bd50df-7adb-d945-0439-6e466c6a13cc
Diffstat (limited to 'scintilla/lexers/LexSQL.cxx')
-rw-r--r--scintilla/lexers/LexSQL.cxx488
1 files changed, 402 insertions, 86 deletions
diff --git a/scintilla/lexers/LexSQL.cxx b/scintilla/lexers/LexSQL.cxx
index aa074b8..6fc3dc3 100644
--- a/scintilla/lexers/LexSQL.cxx
+++ b/scintilla/lexers/LexSQL.cxx
@@ -2,7 +2,7 @@
/** @file LexSQL.cxx
** Lexer for SQL, including PL/SQL and SQL*Plus.
**/
-// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
@@ -12,6 +12,15 @@
#include <assert.h>
#include <ctype.h>
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@@ -23,6 +32,7 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
+#include "OptionSet.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -47,36 +57,288 @@ static inline bool IsANumberChar(int ch) {
// Not exactly following number definition (several dots are seen as OK, etc.)
// but probably enough in most cases.
return (ch < 0x80) &&
- (isdigit(ch) || toupper(ch) == 'E' ||
- ch == '.' || ch == '-' || ch == '+');
+ (isdigit(ch) || toupper(ch) == 'E' ||
+ ch == '.' || ch == '-' || ch == '+');
}
-static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
- Accessor &styler) {
- WordList &keywords1 = *keywordlists[0];
- WordList &keywords2 = *keywordlists[1];
- WordList &kw_pldoc = *keywordlists[2];
- WordList &kw_sqlplus = *keywordlists[3];
- WordList &kw_user1 = *keywordlists[4];
- WordList &kw_user2 = *keywordlists[5];
- WordList &kw_user3 = *keywordlists[6];
- WordList &kw_user4 = *keywordlists[7];
+class SQLStates {
+public :
+ void Set(int lineNumber, unsigned short int sqlStatesLine) {
+ if (!sqlStatement.size() == 0 || !sqlStatesLine == 0) {
+ sqlStatement.resize(lineNumber + 1, 0);
+ sqlStatement[lineNumber] = sqlStatesLine;
+ }
+ }
+
+ unsigned short int IgnoreWhen (unsigned short int sqlStatesLine, bool enable) {
+ if (enable)
+ sqlStatesLine |= MASK_IGNORE_WHEN;
+ else
+ sqlStatesLine &= ~MASK_IGNORE_WHEN;
+
+ return sqlStatesLine;
+ }
- StyleContext sc(startPos, length, initStyle, styler);
+ unsigned short int IntoCondition (unsigned short int sqlStatesLine, bool enable) {
+ if (enable)
+ sqlStatesLine |= MASK_INTO_CONDITION;
+ else
+ sqlStatesLine &= ~MASK_INTO_CONDITION;
+
+ return sqlStatesLine;
+ }
+
+ unsigned short int IntoExceptionBlock (unsigned short int sqlStatesLine, bool enable) {
+ if (enable)
+ sqlStatesLine |= MASK_INTO_EXCEPTION;
+ else
+ sqlStatesLine &= ~MASK_INTO_EXCEPTION;
+
+ return sqlStatesLine;
+ }
+
+ unsigned short int IntoDeclareBlock (unsigned short int sqlStatesLine, bool enable) {
+ if (enable)
+ sqlStatesLine |= MASK_INTO_DECLARE;
+ else
+ sqlStatesLine &= ~MASK_INTO_DECLARE;
+
+ return sqlStatesLine;
+ }
+
+ unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) {
+ if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) {
+ sqlStatesLine++;
+ }
+ return sqlStatesLine;
+ }
+
+ unsigned short int EndCaseBlock (unsigned short int sqlStatesLine) {
+ if ((sqlStatesLine & MASK_NESTED_CASES) > 0) {
+ sqlStatesLine--;
+ }
+ return sqlStatesLine;
+ }
+
+ bool IsIgnoreWhen (unsigned short int sqlStatesLine) {
+ return (sqlStatesLine & MASK_IGNORE_WHEN) != 0;
+ }
+
+ bool IsIntoCondition (unsigned short int sqlStatesLine) {
+ return (sqlStatesLine & MASK_INTO_CONDITION) != 0;
+ }
+
+ bool IsIntoCaseBlock (unsigned short int sqlStatesLine) {
+ return (sqlStatesLine & MASK_NESTED_CASES) != 0;
+ }
+
+ bool IsIntoExceptionBlock (unsigned short int sqlStatesLine) {
+ return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0;
+ }
+
+ bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) {
+ return (sqlStatesLine & MASK_INTO_DECLARE) != 0;
+ }
+
+ unsigned short int ForLine(int lineNumber) {
+ if ((lineNumber > 0) && (sqlStatement.size() > static_cast<size_t>(lineNumber))) {
+ return sqlStatement[lineNumber];
+ } else {
+ return 0;
+ }
+ }
+
+ SQLStates() {}
- // property sql.backslash.escapes
- // Enables backslash as an escape character in SQL.
- bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
+private :
+ std::vector <unsigned short int> sqlStatement;
+ enum {
+ MASK_INTO_DECLARE = 0x1000,
+ MASK_INTO_EXCEPTION = 0x2000,
+ MASK_INTO_CONDITION = 0x4000,
+ MASK_IGNORE_WHEN = 0x8000,
+ MASK_NESTED_CASES = 0x0FFF
+ };
+};
+
+// Options used for LexerSQL
+struct OptionsSQL {
+ bool fold;
+ bool foldAtElse;
+ bool foldComment;
+ bool foldCompact;
+ bool foldOnlyBegin;
+ bool foldSqlExists;
+ bool sqlBackticksIdentifier;
+ bool sqlNumbersignComment;
+ bool sqlBackslashEscapes;
+ OptionsSQL() {
+ fold = false;
+ foldAtElse = false;
+ foldComment = false;
+ foldCompact = false;
+ foldOnlyBegin = false;
+ foldSqlExists = false;
+ sqlBackticksIdentifier = false;
+ sqlNumbersignComment = false;
+ sqlBackslashEscapes = false;
+ }
+};
+
+static const char * const sqlWordListDesc[] = {
+ "Keywords",
+ "Database Objects",
+ "PLDoc",
+ "SQL*Plus",
+ "User Keywords 1",
+ "User Keywords 2",
+ "User Keywords 3",
+ "User Keywords 4",
+ 0
+};
+
+struct OptionSetSQL : public OptionSet<OptionsSQL> {
+ OptionSetSQL() {
+ DefineProperty("fold", &OptionsSQL::fold);
+
+ DefineProperty("lexer.sql.fold.at.else", &OptionsSQL::foldAtElse,
+ "This option enables SQL folding on a \"ELSE\" and \"ELSIF\"line of an IF statement.");
+
+ DefineProperty("fold.comment", &OptionsSQL::foldComment);
- bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0;
+ DefineProperty("fold.compact", &OptionsSQL::foldCompact);
- // property lexer.sql.numbersign.comment
- // If "lexer.sql.numbersign.comment" property is set to 0 a line beginning with '#' will not be a comment.
- bool sqlNumbersignComment = styler.GetPropertyInt("lexer.sql.numbersign.comment", 1) != 0;
+ DefineProperty("fold.sql.only.begin", &OptionsSQL::foldOnlyBegin);
+
+ DefineProperty("fold.sql.exists", &OptionsSQL::foldSqlExists,
+ "Enables \"EXISTS\" to end a fold as is started by \"IF\" in \"DROP TABLE IF EXISTS\".");
+
+ DefineProperty("lexer.sql.backticks.identifier", &OptionsSQL::sqlBackticksIdentifier);
+
+ DefineProperty("lexer.sql.numbersign.comment", &OptionsSQL::sqlNumbersignComment,
+ "If \"lexer.sql.numbersign.comment\" property is set to 0 a line beginning with '#' will not be a comment.");
+
+ DefineProperty("sql.backslash.escapes", &OptionsSQL::sqlBackslashEscapes,
+ "Enables backslash as an escape character in SQL.");
+
+ DefineWordListSets(sqlWordListDesc);
+ }
+};
+
+class LexerSQL : public ILexer {
+public :
+ LexerSQL() {}
+
+ int SCI_METHOD Version () const {
+ return lvOriginal;
+ }
+
+ void SCI_METHOD Release() {
+ delete this;
+ }
+
+ const char * SCI_METHOD PropertyNames() {
+ return osSQL.PropertyNames();
+ }
+
+ int SCI_METHOD PropertyType(const char *name) {
+ return osSQL.PropertyType(name);
+ }
+
+ const char * SCI_METHOD DescribeProperty(const char *name) {
+ return osSQL.DescribeProperty(name);
+ }
+ int SCI_METHOD PropertySet(const char *key, const char *val) {
+ if (osSQL.PropertySet(&options, key, val)) {
+ return 0;
+ }
+ return -1;
+ }
+
+ const char * SCI_METHOD DescribeWordListSets() {
+ return osSQL.DescribeWordListSets();
+ }
+
+ int SCI_METHOD WordListSet(int n, const char *wl);
+ void SCI_METHOD Lex (unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
+ void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
+
+ void * SCI_METHOD PrivateCall(int, void *) {
+ return 0;
+ }
+
+ static ILexer *LexerFactorySQL() {
+ return new LexerSQL();
+ }
+private:
+ bool IsStreamCommentStyle(int style) {
+ return style == SCE_SQL_COMMENT ||
+ style == SCE_SQL_COMMENTDOC ||
+ style == SCE_SQL_COMMENTDOCKEYWORD ||
+ style == SCE_SQL_COMMENTDOCKEYWORDERROR;
+ }
+
+ OptionsSQL options;
+ OptionSetSQL osSQL;
+ SQLStates sqlStates;
+
+ WordList keywords1;
+ WordList keywords2;
+ WordList kw_pldoc;
+ WordList kw_sqlplus;
+ WordList kw_user1;
+ WordList kw_user2;
+ WordList kw_user3;
+ WordList kw_user4;
+};
+
+int SCI_METHOD LexerSQL::WordListSet(int n, const char *wl) {
+ WordList *wordListN = 0;
+ switch (n) {
+ case 0:
+ wordListN = &keywords1;
+ break;
+ case 1:
+ wordListN = &keywords2;
+ break;
+ case 2:
+ wordListN = &kw_pldoc;
+ break;
+ case 3:
+ wordListN = &kw_sqlplus;
+ break;
+ case 4:
+ wordListN = &kw_user1;
+ break;
+ case 5:
+ wordListN = &kw_user2;
+ break;
+ case 6:
+ wordListN = &kw_user3;
+ break;
+ case 7:
+ wordListN = &kw_user4;
+ }
+ int firstModification = -1;
+ if (wordListN) {
+ WordList wlNew;
+ wlNew.Set(wl);
+ if (*wordListN != wlNew) {
+ wordListN->Set(wl);
+ firstModification = 0;
+ }
+ }
+ return firstModification;
+}
+
+void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
+ LexAccessor styler(pAccess);
+ StyleContext sc(startPos, length, initStyle, styler);
int styleBeforeDCKeyword = SCE_SQL_DEFAULT;
- for (; sc.More(); sc.Forward()) {
+ int offset = 0;
+ for (; sc.More(); sc.Forward(), offset++) {
// Determine if the current state should terminate.
switch (sc.state) {
case SCE_SQL_OPERATOR:
@@ -166,7 +428,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
}
break;
case SCE_SQL_CHARACTER:
- if (sqlBackslashEscapes && sc.ch == '\\') {
+ if (options.sqlBackslashEscapes && sc.ch == '\\') {
sc.Forward();
} else if (sc.ch == '\'') {
if (sc.chNext == '\"') {
@@ -196,7 +458,7 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
sc.SetState(SCE_SQL_NUMBER);
} else if (IsAWordStart(sc.ch)) {
sc.SetState(SCE_SQL_IDENTIFIER);
- } else if (sc.ch == 0x60 && sqlBackticksIdentifier) {
+ } else if (sc.ch == 0x60 && options.sqlBackticksIdentifier) {
sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
} else if (sc.Match('/', '*')) {
if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style
@@ -209,9 +471,9 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
// MySQL requires a space or control char after --
// http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
// Perhaps we should enforce that with proper property:
-//~ } else if (sc.Match("-- ")) {
+ //~ } else if (sc.Match("-- ")) {
sc.SetState(SCE_SQL_COMMENTLINE);
- } else if (sc.ch == '#' && sqlNumbersignComment) {
+ } else if (sc.ch == '#' && options.sqlNumbersignComment) {
sc.SetState(SCE_SQL_COMMENTLINEDOC);
} else if (sc.ch == '\'') {
sc.SetState(SCE_SQL_CHARACTER);
@@ -225,26 +487,10 @@ static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, Wo
sc.Complete();
}
-static bool IsStreamCommentStyle(int style) {
- return style == SCE_SQL_COMMENT ||
- style == SCE_SQL_COMMENTDOC ||
- style == SCE_SQL_COMMENTDOCKEYWORD ||
- style == SCE_SQL_COMMENTDOCKEYWORDERROR;
-}
-
-// Store both the current line's fold level and the next lines in the
-// level store to make it easy to pick up with each increment.
-static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
- WordList *[], Accessor &styler) {
- bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
- bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
- bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0;
- bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
-
- // property fold.sql.exists
- // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS".
- bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 1) != 0;
-
+void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
+ if (!options.fold)
+ return;
+ LexAccessor styler(pAccess);
unsigned int endPos = startPos + length;
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
@@ -261,6 +507,10 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
// this statementFound flag avoids to fold when the statement is on only one line by ignoring ELSE or ELSIF
// eg. "IF condition1 THEN ... ELSIF condition2 THEN ... ELSE ... END IF;"
bool statementFound = false;
+ unsigned short int sqlStatesCurrentLine = 0;
+ if (!options.foldOnlyBegin) {
+ sqlStatesCurrentLine = sqlStates.ForLine(lineCurrent);
+ }
for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
@@ -269,12 +519,15 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (atEOL || (ch == ';')) {
+ if (endFound) {
+ //Maybe this is the end of "EXCEPTION" BLOCK (eg. "BEGIN ... EXCEPTION ... END;")
+ sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, false);
+ }
// set endFound and isUnfoldingIgnored to false if EOL is reached or ';' is found
endFound = false;
isUnfoldingIgnored = false;
}
-
- if (foldComment && IsStreamCommentStyle(style)) {
+ if (options.foldComment && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
@@ -282,9 +535,7 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
levelNext--;
}
}
- /* notepad2-mod custom code start */
- /* Disable explicit folding; it can often cause problems with non-aware code
- if (foldComment && (style == SCE_SQL_COMMENTLINE)) {
+ if (options.foldComment && (style == SCE_SQL_COMMENTLINE)) {
// MySQL needs -- comments to be followed by space or control char
if ((ch == '-') && (chNext == '-')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
@@ -296,17 +547,18 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
}
}
}
- */ /* notepad2-mod custom code end */
if (style == SCE_SQL_OPERATOR) {
if (ch == '(') {
levelNext++;
} else if (ch == ')') {
levelNext--;
+ } else if ((!options.foldOnlyBegin) && ch == ';') {
+ sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, false);
}
}
// If new keyword (cannot trigger on elseif or nullif, does less tests)
if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) {
- const int MAX_KW_LEN = 6; // Maximum length of folding keywords
+ const int MAX_KW_LEN = 9; // Maximum length of folding keywords
char s[MAX_KW_LEN + 2];
unsigned int j = 0;
for (; j < MAX_KW_LEN + 1; j++) {
@@ -321,57 +573,131 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
} else {
s[j] = '\0';
}
- if (strcmp(s, "if") == 0 ||
- strcmp(s, "loop") == 0 ||
- strcmp(s, "case") == 0) {
+
+ if (strcmp(s, "if") == 0) {
if (endFound) {
endFound = false;
- if (foldOnlyBegin && !isUnfoldingIgnored) {
+ if (options.foldOnlyBegin && !isUnfoldingIgnored) {
// this end isn't for begin block, but for if block ("end if;")
- // or loop block ("end loop;") or case block ("end case;")
// so ignore previous "end" by increment levelNext.
levelNext++;
}
- } else if (!foldOnlyBegin) {
+ } else {
+ if (!options.foldOnlyBegin)
+ sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);
+ if (levelCurrent > levelNext) {
+ // doesn't include this line into the folding block
+ // because doesn't hide IF (eg "END; IF")
+ levelCurrent = levelNext;
+ }
+ }
+ } else if (!options.foldOnlyBegin &&
+ strcmp(s, "then") == 0 &&
+ sqlStates.IsIntoCondition(sqlStatesCurrentLine)) {
+ sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, false);
+ if (!options.foldOnlyBegin) {
+ if (levelCurrent > levelNext) {
+ levelCurrent = levelNext;
+ }
+ if (!statementFound)
+ levelNext++;
+
statementFound = true;
+ } else if (levelCurrent > levelNext) {
+ // doesn't include this line into the folding block
+ // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE")
+ levelCurrent = levelNext;
+ }
+ } else if (strcmp(s, "loop") == 0 ||
+ strcmp(s, "case") == 0) {
+ if (endFound) {
+ endFound = false;
+ if (options.foldOnlyBegin && !isUnfoldingIgnored) {
+ // this end isn't for begin block, but for loop block ("end loop;") or case block ("end case;")
+ // so ignore previous "end" by increment levelNext.
+ levelNext++;
+ }
+ if ((!options.foldOnlyBegin) && strcmp(s, "case") == 0) {
+ sqlStatesCurrentLine = sqlStates.EndCaseBlock(sqlStatesCurrentLine);
+ levelNext--; //again for the "end case;" and block when
+ }
+ } else if (!options.foldOnlyBegin) {
+ if (strcmp(s, "case") == 0) {
+ sqlStatesCurrentLine = sqlStates.BeginCaseBlock(sqlStatesCurrentLine);
+
+ //for case block increment 2 times
+ if (!statementFound)
+ levelNext++;
+ }
+
if (levelCurrent > levelNext) {
levelCurrent = levelNext;
}
- levelNext++;
+ if (!statementFound)
+ levelNext++;
+
+ statementFound = true;
} else if (levelCurrent > levelNext) {
// doesn't include this line into the folding block
- // because doesn't hide IF, LOOP or CASE (eg "END; IF" or "END; LOOP" or "END; CASE")
+ // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE")
levelCurrent = levelNext;
}
- } else if ((!foldOnlyBegin) && (
- // folding for ELSE and ELSIF block only if foldAtElse is set
- // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound)
- foldAtElse && !statementFound && (strcmp(s, "elsif") == 0 || strcmp(s, "else") == 0))) {
- // prevent also ELSIF and ELSE are on the same line (eg. "ELSIF condition2 THEN ... ELSE ... END IF;")
+ } else if ((!options.foldOnlyBegin) && (
+ // folding for ELSE and ELSIF block only if foldAtElse is set
+ // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound)
+ options.foldAtElse && !statementFound) && strcmp(s, "elsif") == 0) {
+ sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);
+ levelCurrent--;
+ levelNext--;
+ } else if ((!options.foldOnlyBegin) && (
+ // folding for ELSE and ELSIF block only if foldAtElse is set
+ // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound)
+ 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--;
+
} else if (strcmp(s, "begin") == 0) {
levelNext++;
+ sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false);
} else if ((strcmp(s, "end") == 0) ||
-// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
- (foldSqlExists && (strcmp(s, "exists") == 0)) ||
-// // SQL Anywhere permits IF ... ELSE ... ENDIF
-// // will only be active if "endif" appears in the
-// // keyword list.
- (strcmp(s, "endif") == 0)) {
+ // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
+ (options.foldSqlExists && (strcmp(s, "exists") == 0)) ||
+ // SQL Anywhere permits IF ... ELSE ... ENDIF
+ // will only be active if "endif" appears in the
+ // keyword list.
+ (strcmp(s, "endif") == 0)) {
endFound = true;
levelNext--;
if (levelNext < SC_FOLDLEVELBASE) {
levelNext = SC_FOLDLEVELBASE;
isUnfoldingIgnored = true;
}
+ } else if ((!options.foldOnlyBegin) &&
+ strcmp(s, "when") == 0 &&
+ !sqlStates.IsIgnoreWhen(sqlStatesCurrentLine) &&
+ !sqlStates.IsIntoExceptionBlock(sqlStatesCurrentLine) &&
+ sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine)) {
+ sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);
+
+ // 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")
+ if (!statementFound) {
+ levelCurrent--;
+ levelNext--;
+ }
+ } else if ((!options.foldOnlyBegin) && strcmp(s, "exit") == 0) {
+ sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, true);
+ } else if ((!options.foldOnlyBegin) && !sqlStates.IsIntoDeclareBlock(sqlStatesCurrentLine) && strcmp(s, "exception") == 0) {
+ sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, true);
+ } else if ((!options.foldOnlyBegin) && strcmp (s, "declare") == 0) {
+ sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, true);
}
}
if (atEOL) {
int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16;
- if (visibleChars == 0 && foldCompact)
+ if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
@@ -382,6 +708,8 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
levelCurrent = levelNext;
visibleChars = 0;
statementFound = false;
+ if (!options.foldOnlyBegin)
+ sqlStates.Set(lineCurrent, sqlStatesCurrentLine);
}
if (!isspacechar(ch)) {
visibleChars++;
@@ -389,16 +717,4 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
}
}
-static const char * const sqlWordListDesc[] = {
- "Keywords",
- "Database Objects",
- "PLDoc",
- "SQL*Plus",
- "User Keywords 1",
- "User Keywords 2",
- "User Keywords 3",
- "User Keywords 4",
- 0
-};
-
-LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc);
+LexerModule lmSQL(SCLEX_SQL, LexerSQL::LexerFactorySQL, "sql", sqlWordListDesc);