Commit 18798383 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Use the QML/JS incremental scanner in the indenter.

parent f3b738bb
......@@ -66,6 +66,7 @@
*/
#include "qscriptindenter.h"
#include "qscriptincrementalscanner.h"
#include <QtDebug>
using namespace SharedTools;
......@@ -82,12 +83,9 @@ const int QScriptIndenter::SmallRoof = 40;
const int QScriptIndenter::BigRoof = 400;
QScriptIndenter::QScriptIndenter()
: literal(QRegExp(QLatin1String("([\"'])(?:\\\\.|[^\\\\])*\\1"))),
label(QRegExp(QLatin1String("^\\s*((?:case\\b([^:])+|[a-zA-Z_0-9.]+)(?:\\s+)?:)(?!:)"))),
inlineCComment(QRegExp(QLatin1String("/\\*.*\\*/"))),
: label(QRegExp(QLatin1String("^\\s*((?:case\\b([^:])+|[a-zA-Z_0-9.]+)(?:\\s+)?:)(?!:)"))),
braceX(QRegExp(QLatin1String("^\\s*\\}\\s*(?:else|catch)\\b"))),
iflikeKeyword(QRegExp(QLatin1String("\\b(?:catch|do|for|if|while|with)\\b"))),
propertylikeKeyword(QRegExp(QLatin1String("^\\s*\\b(?:property|signal|import|readonly|return)\\b")))
iflikeKeyword(QRegExp(QLatin1String("\\b(?:catch|do|for|if|while|with)\\b")))
{
/*
......@@ -120,9 +118,6 @@ QScriptIndenter::QScriptIndenter()
yyLine = 0;
yyBraceDepth = 0;
yyLeftBraceFollows = 0;
literal.setMinimal(true);
inlineCComment.setMinimal(true);
}
QScriptIndenter::~QScriptIndenter()
......@@ -209,98 +204,84 @@ void QScriptIndenter::eraseChar(QString &t, int k, QChar ch) const
Removes some nefast constructs from a code line and returns the
resulting line.
*/
QString QScriptIndenter::trimmedCodeLine(const QString &t) const
QString QScriptIndenter::trimmedCodeLine(const QString &t)
{
QString trimmed = t;
int k;
QScriptIncrementalScanner scanner;
/*
Replace character and string literals by X's, since they may
contain confusing characters (such as '{' and ';'). "Hello!" is
replaced by XXXXXXXX. The literals are rigourously of the same
length before and after; otherwise, we would break alignment of
continuation lines.
*/
k = 0;
while ((k = literal.indexIn(trimmed, k)) != -1) {
for (int i = 0; i < literal.matchedLength(); i++)
eraseChar(trimmed, k + i, QLatin1Char('X'));
k += literal.matchedLength();
}
int state = yyLinizerState.iter.userState();
if (state == -1)
state = 0;
state = state & 0xff;
/*
Replace inline C-style comments by spaces. Other comments are
handled elsewhere.
*/
k = 0;
while ((k = inlineCComment.indexIn(trimmed, k)) != -1) {
for (int i = 0; i < inlineCComment.matchedLength(); i++)
eraseChar(trimmed, k + i, QLatin1Char(' '));
k += inlineCComment.matchedLength();
}
yyLinizerState.tokens = scanner(t, state);
QString trimmed;
int previousTokenEnd = 0;
foreach (const QScriptIncrementalScanner::Token &token, yyLinizerState.tokens) {
trimmed.append(t.midRef(previousTokenEnd, token.begin() - previousTokenEnd));
/*
Replace goto and switch labels by whitespace, but be careful
with this case:
if (token.is(QScriptIncrementalScanner::Token::String)) {
for (int i = 0; i < token.length; ++i)
trimmed.append(QLatin1Char('X'));
foo1: bar1;
bar2;
*/
} else if (token.is(QScriptIncrementalScanner::Token::Comment)) {
for (int i = 0; i < token.length; ++i)
trimmed.append(QLatin1Char(' '));
bool insertSemicolon = false;
while (trimmed.lastIndexOf(QLatin1Char(':')) != -1 && label.indexIn(trimmed) != -1) {
insertSemicolon = true;
} else {
trimmed.append(t.midRef(token.offset, token.length));
}
const QString cap1 = label.cap(1);
int pos1 = label.pos(1);
int stop = cap1.length();
previousTokenEnd = token.end();
}
if (pos1 + stop < trimmed.length() && ppIndentSize < stop)
stop = ppIndentSize;
int index = yyLinizerState.tokens.size() - 1;
for (; index != -1; --index) {
const QScriptIncrementalScanner::Token &token = yyLinizerState.tokens.at(index);
if (token.isNot(QScriptIncrementalScanner::Token::Comment))
break;
}
int i = 0;
while (i < stop) {
eraseChar(trimmed, pos1 + i, QLatin1Char(';'));
i++;
}
while (i < cap1.length()) {
eraseChar(trimmed, pos1 + i, QLatin1Char(';'));
i++;
bool isBinding = false;
foreach (const QScriptIncrementalScanner::Token &token, yyLinizerState.tokens) {
if (token.is(QScriptIncrementalScanner::Token::Colon)) {
isBinding = true;
break;
}
}
/*
Remove C++-style comments.
*/
k = trimmed.indexOf(QRegExp(QLatin1String("\\s*//")));
if (k != -1)
trimmed.truncate(k);
if (! insertSemicolon && ! trimmed.isEmpty()) {
const QChar ch = trimmed.at(trimmed.length() - 1);
switch (ch.unicode()) {
case ',':
case ']':
case '"':
case '\'':
case '_':
insertSemicolon = true;
if (index != -1) {
const QScriptIncrementalScanner::Token &last = yyLinizerState.tokens.at(index);
switch (last.kind) {
case QScriptIncrementalScanner::Token::LeftParenthesis:
case QScriptIncrementalScanner::Token::LeftBrace:
case QScriptIncrementalScanner::Token::Semicolon:
case QScriptIncrementalScanner::Token::Operator:
break;
default:
if (ch.isLetterOrNumber()) {
if (! trimmed.endsWith(QLatin1String("else")))
insertSemicolon = true;
} else if (trimmed.indexOf(propertylikeKeyword) != -1)
insertSemicolon = true;
case QScriptIncrementalScanner::Token::RightParenthesis:
case QScriptIncrementalScanner::Token::RightBrace:
if (isBinding)
trimmed.append(QLatin1Char(';'));
break;
case QScriptIncrementalScanner::Token::Colon:
case QScriptIncrementalScanner::Token::LeftBracket:
case QScriptIncrementalScanner::Token::RightBracket:
trimmed.append(QLatin1Char(';'));
break;
case QScriptIncrementalScanner::Token::Identifier:
case QScriptIncrementalScanner::Token::Keyword:
if (t.midRef(last.offset, last.length) != QLatin1String("else"))
trimmed.append(QLatin1Char(';'));
break;
}
}
if (insertSemicolon)
trimmed.append(QLatin1Char(';'));
default:
trimmed.append(QLatin1Char(';'));
break;
} // end of switch
}
return trimmed;
}
......
......@@ -30,6 +30,7 @@
#ifndef QTSCRIPTINDENTER_H
#define QTSCRIPTINDENTER_H
#include <qscripthighlighter/qscriptincrementalscanner.h>
#include <QtCore/QRegExp>
#include <QtCore/QStringList>
#include <QtGui/QTextBlock>
......@@ -57,7 +58,7 @@ private:
bool isOnlyWhiteSpace(const QString &t) const;
int columnForIndex(const QString &t, int index) const;
int indentOfLine(const QString &t) const;
QString trimmedCodeLine(const QString &t) const;
QString trimmedCodeLine(const QString &t);
void eraseChar(QString &t, int k, QChar ch) const;
QChar lastParen(const QString &t) const;
......@@ -102,6 +103,7 @@ private:
bool inComment;
bool pendingRightBrace;
QString line;
QList<QScriptIncrementalScanner::Token> tokens;
QTextBlock iter;
};
......@@ -127,12 +129,9 @@ private:
const int *yyBraceDepth;
const bool *yyLeftBraceFollows;
QRegExp literal;
QRegExp label;
QRegExp inlineCComment;
QRegExp braceX;
QRegExp iflikeKeyword;
QRegExp propertylikeKeyword;
};
} // namespace SharedTools
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment