diff options
| author | 2015-11-25 16:48:49 -0500 | |
|---|---|---|
| committer | 2015-11-25 16:48:49 -0500 | |
| commit | 7412693e086a7eafaa7ea861164caf523943e5fa (patch) | |
| tree | 0aee322e40572df306b9813546c7a12b3093bcea /Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp | |
| parent | 640196993d31cf5d6fdf36386990ec05f473a048 (diff) | |
| parent | 8e640722c62692818ab840d50b3758f89a41a54e (diff) | |
Merge tag 'upstream/3.0.7'
Upstream version 3.0.7
# gpg: Signature made Wed 25 Nov 2015 04:48:48 PM EST using RSA key ID EBE9BD91
# gpg: Good signature from "Unit 193 <unit193@gmail.com>"
# gpg: aka "Unit 193 <unit193@ninthfloor.org>"
# gpg: aka "Unit 193 <unit193@ubuntu.com>"
# gpg: aka "Unit 193 <unit193@ninthfloor.com>"
Diffstat (limited to 'Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp')
| -rw-r--r-- | Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp | 206 |
1 files changed, 204 insertions, 2 deletions
diff --git a/Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp b/Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp index 8f75960..a08f95c 100644 --- a/Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp +++ b/Plugins/SqlEnterpriseFormatter/sqlenterpriseformatter.cpp @@ -3,6 +3,7 @@ #include "common/unused.h" #include "common/global.h" #include <QDebug> +#include <parser/lexer.h> #include <parser/parser.h> SqlEnterpriseFormatter::SqlEnterpriseFormatter() @@ -11,6 +12,8 @@ SqlEnterpriseFormatter::SqlEnterpriseFormatter() QString SqlEnterpriseFormatter::format(SqliteQueryPtr query) { + QList<Comment*> comments = collectComments(query->tokens); + int wrapperIdx = cfg.SqlEnterpriseFormatter.Wrappers.get().indexOf(cfg.SqlEnterpriseFormatter.PrefferedWrapper.get()); NameWrapper wrapper = getAllNameWrappers()[wrapperIdx]; @@ -24,7 +27,11 @@ QString SqlEnterpriseFormatter::format(SqliteQueryPtr query) QString formatted = formatStmt->format(); delete formatStmt; - return formatted; + QString formattedWithComments = applyComments(formatted, comments, query->dialect); + for (Comment* c : comments) + delete c; + + return formattedWithComments; } bool SqlEnterpriseFormatter::init() @@ -34,7 +41,9 @@ bool SqlEnterpriseFormatter::init() static_qstring(query1, "SELECT (2 + 4) AND (3 + 5), 4 NOT IN (SELECT t1.'some[_]name' + t2.[some'name2] FROM xyz t1 JOIN zxc t2 ON (t1.aaa = t2.aaa)) " "FROM a, (SELECT id FROM table2);"); static_qstring(query2, "INSERT INTO table1 (id, value1, value2) VALUES (1, (2 + 5), (SELECT id FROM table2));"); - static_qstring(query3, "CREATE TABLE tab (id INTEGER PRIMARY KEY, value1 VARCHAR(6), value2 NUMBER(8,2) NOT NULL DEFAULT 1.0);"); + static_qstring(query3, "CREATE TABLE tab (id INTEGER PRIMARY KEY, /*a primary key column*/ value1 VARCHAR(6), " + "value2 /*column with constraints*/ NUMBER(8,2) NOT NULL DEFAULT 1.0" + ");"); static_qstring(query4, "CREATE UNIQUE INDEX IF NOT EXISTS dbName.idx1 ON [messages column] (id COLLATE x ASC, lang DESC, description);"); Parser parser(Dialect::Sqlite3); @@ -110,3 +119,196 @@ void SqlEnterpriseFormatter::configDialogClosed() { disconnect(&cfg.SqlEnterpriseFormatter, SIGNAL(changed(CfgEntry*)), this, SLOT(configModified(CfgEntry*))); } + +QList<SqlEnterpriseFormatter::Comment *> SqlEnterpriseFormatter::collectComments(const TokenList &tokens) +{ + QList<Comment*> results; + + QList<TokenList> tokensInLines = tokensByLines(tokens); + Comment* prevCommentInThisLine = nullptr; + Comment* cmt = nullptr; + bool tokensBefore = false; + int pos = 0; + int line = 0; + for (const TokenList& tokensInLine : tokensInLines) + { + tokensBefore = true; + prevCommentInThisLine = nullptr; + for (const TokenPtr& token : tokensInLine) + { + if (token->type == Token::Type::SPACE) + continue; + + if (prevCommentInThisLine) + prevCommentInThisLine->tokensAfter = true; + + if (token->type == Token::Type::COMMENT) + { + cmt = new Comment; + cmt->tokensBefore = tokensBefore; + cmt->position = pos; + cmt->multiline = token->value.startsWith("/*"); + if (cmt->multiline) + cmt->contents = token->value.mid(2, token->value.length() - 4).trimmed(); + else + cmt->contents = token->value.mid(2).trimmed(); + + results << cmt; + prevCommentInThisLine = cmt; + continue; + } + + tokensBefore = true; + pos++; + } + line++; + } + + return results; +} + +QList<TokenList> SqlEnterpriseFormatter::tokensByLines(const TokenList &tokens, bool includeSpaces) +{ + QList<TokenList> tokensInLines; + TokenList tokensInLine; + for (const TokenPtr& token : tokens) + { + if (includeSpaces || token->type != Token::Type::SPACE) + tokensInLine << token; + + if (token->type == Token::Type::SPACE && token->value.contains('\n')) + { + tokensInLines << tokensInLine; + tokensInLine.clear(); + } + } + if (tokensInLine.size() > 0) + tokensInLines << tokensInLine; + + return tokensInLines; +} + +TokenList SqlEnterpriseFormatter::adjustCommentsToEnd(const TokenList &inputTokens) +{ + QList<TokenList> tokensInLines = tokensByLines(inputTokens, true); + TokenList newTokens; + TokenList commentTokensForLine; + TokenPtr newLineToken; + for (const TokenList& tokensInLine : tokensInLines) + { + commentTokensForLine.clear(); + newLineToken.clear(); + for (const TokenPtr& token : tokensInLine) + { + if (token->type == Token::Type::COMMENT) + { + wrapComment(token, true); + //token->value = " " + endLineCommentTpl.arg(token->value); + commentTokensForLine << token; + } + else if (token->type == Token::Type::SPACE && token->value.contains("\n")) + newLineToken = token; + else + newTokens << token; + } + + newTokens += commentTokensForLine; + if (newLineToken) + newTokens << newLineToken; + } + return newTokens; +} + +TokenList SqlEnterpriseFormatter::wrapOnlyComments(const TokenList &inputTokens) +{ + QList<TokenList> tokensInLines = tokensByLines(inputTokens, true); + TokenList newTokens; + bool lineEnd = true; + for (const TokenList& tokensInLine : reverse(tokensInLines)) + { + lineEnd = true; + for (const TokenPtr& token : reverse(tokensInLine)) + { + if (!token->isWhitespace()) + lineEnd = false; + + if (token->type == Token::Type::COMMENT) + wrapComment(token, lineEnd); + + newTokens << token; + } + } + return reverse(newTokens); +} + +TokenList SqlEnterpriseFormatter::optimizeInnerComments(const TokenList &inputTokens) +{ + // TODO + return inputTokens; +} + +TokenList SqlEnterpriseFormatter::optimizeEndLineComments(const TokenList &inputTokens) +{ + // TODO + return inputTokens; +} + +void SqlEnterpriseFormatter::indentMultiLineComments(const TokenList &inputTokens) +{ + // TODO +} + +void SqlEnterpriseFormatter::wrapComment(const TokenPtr &token, bool isAtLineEnd) +{ + static_qstring(multiCommentTpl, "/* %1 */"); + static_qstring(endLineCommentTpl, "-- %1"); + + bool isMultiLine = token->value.contains("\n"); + if (isAtLineEnd && !isMultiLine && cfg.SqlEnterpriseFormatter.PreferredCommentMarker.get() == "--") + token->value = endLineCommentTpl.arg(token->value); + else + token->value = multiCommentTpl.arg(token->value); +} + +QString SqlEnterpriseFormatter::applyComments(const QString& formatted, QList<SqlEnterpriseFormatter::Comment*> comments, Dialect dialect) +{ + if (comments.size() == 0) + return formatted; + + int currentCommentPosition = comments.first()->position; + + TokenList allTokens = Lexer::tokenize(formatted, dialect); + TokenList newTokens; + int currentTokenPosition = 0; + for (const TokenPtr& token : allTokens) + { + if (currentTokenPosition == currentCommentPosition) + { + newTokens << TokenPtr::create(Token::Type::COMMENT, comments.first()->contents); + comments.removeFirst(); + if (comments.size() > 0) + currentCommentPosition = comments.first()->position; + else + currentCommentPosition = -1; + } + + newTokens << token; + if (token->type != Token::Type::SPACE) + currentTokenPosition++; + } + + // Any remaining comments + for (Comment* cmt : comments) + newTokens << TokenPtr::create(Token::Type::COMMENT, cmt->contents); + + if (cfg.SqlEnterpriseFormatter.MoveAllCommentsToLineEnd.get()) + newTokens = adjustCommentsToEnd(newTokens); + else + newTokens = wrapOnlyComments(newTokens); + + newTokens = optimizeInnerComments(newTokens); + newTokens = optimizeEndLineComments(newTokens); + indentMultiLineComments(newTokens); + + return newTokens.detokenize(); +} |
