diff options
-rw-r--r-- | doc/ScintillaHistory.html | 4 | ||||
-rw-r--r-- | lexers/LexSQL.cxx | 162 |
2 files changed, 135 insertions, 31 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 42bd8c8b3..c724505e5 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -460,6 +460,10 @@ by stricter checking of ctags lines. </li> <li> + SQL folder folds 'create view' statements. + <a href="http://sourceforge.net/p/scintilla/feature-requests/1020/">Feature #1020.</a> + </li> + <li> For SCI_SETIDENTIFIERS allow \t, \r, and \n as well as space between identifiers. <a href="http://sourceforge.net/p/scintilla/bugs/1521/">Bug #1521</a>. </li> diff --git a/lexers/LexSQL.cxx b/lexers/LexSQL.cxx index dc4bf6697..4d895352f 100644 --- a/lexers/LexSQL.cxx +++ b/lexers/LexSQL.cxx @@ -62,6 +62,7 @@ static inline bool IsANumberChar(int ch) { ch == '.' || ch == '-' || ch == '+'); } +typedef unsigned int sql_state_t; class SQLStates { public : @@ -69,7 +70,7 @@ public : sqlStatement.Set(lineNumber, sqlStatesLine); } - unsigned short int IgnoreWhen (unsigned short int sqlStatesLine, bool enable) { + sql_state_t IgnoreWhen (sql_state_t sqlStatesLine, bool enable) { if (enable) sqlStatesLine |= MASK_IGNORE_WHEN; else @@ -78,7 +79,7 @@ public : return sqlStatesLine; } - unsigned short int IntoCondition (unsigned short int sqlStatesLine, bool enable) { + sql_state_t IntoCondition (sql_state_t sqlStatesLine, bool enable) { if (enable) sqlStatesLine |= MASK_INTO_CONDITION; else @@ -87,7 +88,7 @@ public : return sqlStatesLine; } - unsigned short int IntoExceptionBlock (unsigned short int sqlStatesLine, bool enable) { + sql_state_t IntoExceptionBlock (sql_state_t sqlStatesLine, bool enable) { if (enable) sqlStatesLine |= MASK_INTO_EXCEPTION; else @@ -96,7 +97,7 @@ public : return sqlStatesLine; } - unsigned short int IntoDeclareBlock (unsigned short int sqlStatesLine, bool enable) { + sql_state_t IntoDeclareBlock (sql_state_t sqlStatesLine, bool enable) { if (enable) sqlStatesLine |= MASK_INTO_DECLARE; else @@ -105,7 +106,7 @@ public : return sqlStatesLine; } - unsigned short int IntoMergeStatement (unsigned short int sqlStatesLine, bool enable) { + sql_state_t IntoMergeStatement (sql_state_t sqlStatesLine, bool enable) { if (enable) sqlStatesLine |= MASK_MERGE_STATEMENT; else @@ -114,7 +115,7 @@ public : return sqlStatesLine; } - unsigned short int CaseMergeWithoutWhenFound (unsigned short int sqlStatesLine, bool found) { + sql_state_t CaseMergeWithoutWhenFound (sql_state_t sqlStatesLine, bool found) { if (found) sqlStatesLine |= MASK_CASE_MERGE_WITHOUT_WHEN_FOUND; else @@ -122,7 +123,7 @@ public : return sqlStatesLine; } - unsigned short int IntoSelectStatementOrAssignment (unsigned short int sqlStatesLine, bool found) { + sql_state_t IntoSelectStatementOrAssignment (sql_state_t sqlStatesLine, bool found) { if (found) sqlStatesLine |= MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT; else @@ -130,67 +131,109 @@ public : return sqlStatesLine; } - unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) { + sql_state_t BeginCaseBlock (sql_state_t sqlStatesLine) { if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) { sqlStatesLine++; } return sqlStatesLine; } - unsigned short int EndCaseBlock (unsigned short int sqlStatesLine) { + sql_state_t EndCaseBlock (sql_state_t sqlStatesLine) { if ((sqlStatesLine & MASK_NESTED_CASES) > 0) { sqlStatesLine--; } return sqlStatesLine; } - bool IsIgnoreWhen (unsigned short int sqlStatesLine) { + sql_state_t IntoCreateStatement (sql_state_t sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_CREATE; + else + sqlStatesLine &= ~MASK_INTO_CREATE; + + return sqlStatesLine; + } + + sql_state_t IntoCreateViewStatement (sql_state_t sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_CREATE_VIEW; + else + sqlStatesLine &= ~MASK_INTO_CREATE_VIEW; + + return sqlStatesLine; + } + + sql_state_t IntoCreateViewAsStatement (sql_state_t sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_CREATE_VIEW_AS_STATEMENT; + else + sqlStatesLine &= ~MASK_INTO_CREATE_VIEW_AS_STATEMENT; + + return sqlStatesLine; + } + + bool IsIgnoreWhen (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_IGNORE_WHEN) != 0; } - bool IsIntoCondition (unsigned short int sqlStatesLine) { + bool IsIntoCondition (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_INTO_CONDITION) != 0; } - bool IsIntoCaseBlock (unsigned short int sqlStatesLine) { + bool IsIntoCaseBlock (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_NESTED_CASES) != 0; } - bool IsIntoExceptionBlock (unsigned short int sqlStatesLine) { + bool IsIntoExceptionBlock (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0; } - bool IsIntoSelectStatementOrAssignment (unsigned short int sqlStatesLine) { + bool IsIntoSelectStatementOrAssignment (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT) != 0; } - bool IsCaseMergeWithoutWhenFound (unsigned short int sqlStatesLine) { + bool IsCaseMergeWithoutWhenFound (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_CASE_MERGE_WITHOUT_WHEN_FOUND) != 0; } - bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) { + bool IsIntoDeclareBlock (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_INTO_DECLARE) != 0; } - bool IsIntoMergeStatement (unsigned short int sqlStatesLine) { + bool IsIntoMergeStatement (sql_state_t sqlStatesLine) { return (sqlStatesLine & MASK_MERGE_STATEMENT) != 0; } - unsigned short int ForLine(int lineNumber) { + bool IsIntoCreateStatement (sql_state_t sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_CREATE) != 0; + } + + bool IsIntoCreateViewStatement (sql_state_t sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_CREATE_VIEW) != 0; + } + + bool IsIntoCreateViewAsStatement (sql_state_t sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_CREATE_VIEW_AS_STATEMENT) != 0; + } + + sql_state_t ForLine(int lineNumber) { return sqlStatement.ValueAt(lineNumber); } SQLStates() {} private : - SparseState <unsigned short int> sqlStatement; + SparseState <sql_state_t> sqlStatement; enum { - MASK_NESTED_CASES = 0x01FF, - MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT = 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_NESTED_CASES = 0x0001FF, + MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT = 0x000200, + MASK_CASE_MERGE_WITHOUT_WHEN_FOUND = 0x000400, + MASK_MERGE_STATEMENT = 0x000800, + MASK_INTO_DECLARE = 0x001000, + MASK_INTO_EXCEPTION = 0x002000, + MASK_INTO_CONDITION = 0x004000, + MASK_IGNORE_WHEN = 0x008000, + MASK_INTO_CREATE = 0x010000, + MASK_INTO_CREATE_VIEW = 0x020000, + MASK_INTO_CREATE_VIEW_AS_STATEMENT = 0x040000 }; }; @@ -561,12 +604,46 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, if (lineCurrent > 0) { // Backtrack to previous line in case need to fix its fold status for folding block of single-line comments (i.e. '--'). - lineCurrent -= 1; - startPos = styler.LineStart(lineCurrent); - + int lastNLPos = -1; + // And keep going back until we find an operator ';' followed + // by white-space and/or comments. This will improve folding. + while (--startPos > 0) { + char ch = styler[startPos]; + if (ch == '\n' || (ch == '\r' && styler[startPos + 1] != '\n')) { + lastNLPos = startPos; + } else if (ch == ';' && + styler.StyleAt(startPos) == SCE_SQL_OPERATOR) { + bool isAllClear = true; + for (int tempPos = startPos + 1; + tempPos < lastNLPos; + ++tempPos) { + int tempStyle = styler.StyleAt(tempPos); + if (!IsCommentStyle(tempStyle) + && tempStyle != SCE_SQL_DEFAULT) { + isAllClear = false; + break; + } + } + if (isAllClear) { + startPos = lastNLPos + 1; + break; + } + } + } + lineCurrent = styler.GetLine(startPos); if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; } + // And because folding ends at ';', keep going until we find one + // Otherwise if create ... view ... as is split over multiple + // lines the folding won't always update immediately. + unsigned int docLength = styler.Length(); + for (; endPos < docLength; ++endPos) { + if (styler.SafeGetCharAt(endPos) == ';') { + break; + } + } + int levelNext = levelCurrent; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); @@ -576,7 +653,7 @@ void SCI_METHOD LexerSQL::Fold(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; + sql_state_t sqlStatesCurrentLine = 0; if (!options.foldOnlyBegin) { sqlStatesCurrentLine = sqlStates.ForLine(lineCurrent); } @@ -606,6 +683,16 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, } if (sqlStates.IsIntoSelectStatementOrAssignment(sqlStatesCurrentLine)) sqlStatesCurrentLine = sqlStates.IntoSelectStatementOrAssignment(sqlStatesCurrentLine, false); + if (sqlStates.IsIntoCreateStatement(sqlStatesCurrentLine)) { + if (sqlStates.IsIntoCreateViewStatement(sqlStatesCurrentLine)) { + if (sqlStates.IsIntoCreateViewAsStatement(sqlStatesCurrentLine)) { + levelNext--; + sqlStatesCurrentLine = sqlStates.IntoCreateViewAsStatement(sqlStatesCurrentLine, false); + } + sqlStatesCurrentLine = sqlStates.IntoCreateViewStatement(sqlStatesCurrentLine, false); + } + sqlStatesCurrentLine = sqlStates.IntoCreateStatement(sqlStatesCurrentLine, false); + } } if (ch == ':' && chNext == '=' && !IsCommentStyle(style)) sqlStatesCurrentLine = sqlStates.IntoSelectStatementOrAssignment(sqlStatesCurrentLine, true); @@ -805,6 +892,19 @@ void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true); levelNext++; statementFound = true; + } else if ((!options.foldOnlyBegin) && + strcmp(s, "create") == 0) { + sqlStatesCurrentLine = sqlStates.IntoCreateStatement(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && + strcmp(s, "view") == 0 && + sqlStates.IsIntoCreateStatement(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.IntoCreateViewStatement(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && + strcmp(s, "as") == 0 && + sqlStates.IsIntoCreateViewStatement(sqlStatesCurrentLine) && + ! sqlStates.IsIntoCreateViewAsStatement(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.IntoCreateViewAsStatement(sqlStatesCurrentLine, true); + levelNext++; } } if (atEOL) { |