Commit 14207aa8 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Fixed highlihing of QML context keywords.

parent 272014a5
......@@ -50,12 +50,17 @@ QScriptHighlighter::QScriptHighlighter(bool duiEnabled, QTextDocument *parent):
rc[PreProcessorFormat].setForeground(Qt::darkBlue);
rc[VisualWhitespace].setForeground(Qt::lightGray); // for debug: rc[VisualWhitespace].setBackground(Qt::red);
setFormats(rc);
m_scanner.setKeywords(keywords());
}
bool QScriptHighlighter::isDuiEnabled() const
{ return m_duiEnabled; }
{
return m_duiEnabled;
}
QTextCharFormat QScriptHighlighter::labelTextCharFormat() const
{
return m_formats[LabelFormat];
}
static bool checkStartOfBinding(const Token &token)
{
......@@ -85,18 +90,6 @@ void QScriptHighlighter::highlightBlock(const QString &text)
setFormat(token.offset, token.length, m_formats[KeywordFormat]);
break;
case Token::String:
highlightWhitespace(token, text, StringFormat);
break;
case Token::Comment:
highlightWhitespace(token, text, CommentFormat);
break;
case Token::Number:
highlightWhitespace(token, text, NumberFormat);
break;
case Token::LeftParenthesis:
onOpeningParenthesis('(', token.offset);
break;
......@@ -122,6 +115,16 @@ void QScriptHighlighter::highlightBlock(const QString &text)
break;
case Token::Identifier: {
if (maybeQmlKeyword(text.midRef(token.offset, token.length))) {
// check the previous token
if (index == 0 || tokens.at(index - 1).isNot(Token::Dot)) {
if (index + 1 == tokens.size() || tokens.at(index + 1).isNot(Token::Colon)) {
setFormat(token.offset, token.length, m_formats[KeywordFormat]);
break;
}
}
}
if (index + 1 < tokens.size()) {
if (tokens.at(index + 1).is(Token::LeftBrace) && text.at(token.offset).isUpper()) {
setFormat(token.offset, token.length, m_formats[TypeFormat]);
......@@ -195,8 +198,8 @@ void QScriptHighlighter::highlightBlock(const QString &text)
if (! tokens.isEmpty())
firstNonSpace = tokens.first().offset;
setCurrentBlockState(m_scanner.endState());
onBlockEnd(m_scanner.endState(), firstNonSpace);
setCurrentBlockState(m_scanner.state());
onBlockEnd(m_scanner.state(), firstNonSpace);
}
void QScriptHighlighter::setFormats(const QVector<QTextCharFormat> &s)
......@@ -205,76 +208,6 @@ void QScriptHighlighter::setFormats(const QVector<QTextCharFormat> &s)
qCopy(s.constBegin(), s.constEnd(), m_formats);
}
QSet<QString> QScriptHighlighter::keywords()
{
QSet<QString> keywords;
keywords << QLatin1String("Infinity");
keywords << QLatin1String("NaN");
keywords << QLatin1String("abstract");
keywords << QLatin1String("boolean");
keywords << QLatin1String("break");
keywords << QLatin1String("byte");
keywords << QLatin1String("case");
keywords << QLatin1String("catch");
keywords << QLatin1String("char");
keywords << QLatin1String("class");
keywords << QLatin1String("const");
keywords << QLatin1String("constructor");
keywords << QLatin1String("continue");
keywords << QLatin1String("debugger");
keywords << QLatin1String("default");
keywords << QLatin1String("delete");
keywords << QLatin1String("do");
keywords << QLatin1String("double");
keywords << QLatin1String("else");
keywords << QLatin1String("enum");
keywords << QLatin1String("export");
keywords << QLatin1String("extends");
keywords << QLatin1String("false");
keywords << QLatin1String("final");
keywords << QLatin1String("finally");
keywords << QLatin1String("float");
keywords << QLatin1String("for");
keywords << QLatin1String("function");
keywords << QLatin1String("goto");
keywords << QLatin1String("if");
keywords << QLatin1String("implements");
keywords << QLatin1String("import");
keywords << QLatin1String("in");
keywords << QLatin1String("instanceof");
keywords << QLatin1String("int");
keywords << QLatin1String("interface");
keywords << QLatin1String("long");
keywords << QLatin1String("native");
keywords << QLatin1String("new");
keywords << QLatin1String("package");
keywords << QLatin1String("private");
keywords << QLatin1String("protected");
keywords << QLatin1String("public");
keywords << QLatin1String("return");
keywords << QLatin1String("short");
keywords << QLatin1String("static");
keywords << QLatin1String("super");
keywords << QLatin1String("switch");
keywords << QLatin1String("synchronized");
keywords << QLatin1String("this");
keywords << QLatin1String("throw");
keywords << QLatin1String("throws");
keywords << QLatin1String("transient");
keywords << QLatin1String("true");
keywords << QLatin1String("try");
keywords << QLatin1String("typeof");
keywords << QLatin1String("undefined");
keywords << QLatin1String("var");
keywords << QLatin1String("void");
keywords << QLatin1String("volatile");
keywords << QLatin1String("while");
keywords << QLatin1String("with");
return keywords;
}
int QScriptHighlighter::onBlockStart()
{
return currentBlockState();
......@@ -292,22 +225,23 @@ void QScriptHighlighter::onClosingParenthesis(QChar, int)
{
}
void QScriptHighlighter::highlightWhitespace(const Token &token, const QString &text, int nonWhitespaceFormat)
bool QScriptHighlighter::maybeQmlKeyword(const QStringRef &text) const
{
const QTextCharFormat normalFormat = m_formats[nonWhitespaceFormat];
const QTextCharFormat visualSpaceFormat = m_formats[VisualWhitespace];
const int end = token.end();
int index = token.offset;
while (index != end) {
const bool isSpace = text.at(index).isSpace();
const int start = index;
do { ++index; }
while (index != end && text.at(index).isSpace() == isSpace);
if (text.isEmpty())
return false;
const int tokenLength = index - start;
setFormat(start, tokenLength, isSpace ? visualSpaceFormat : normalFormat);
const QChar ch = text.at(0);
if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
return true;
} else if (ch == QLatin1Char('a') && text == QLatin1String("alias")) {
return true;
} else if (ch == QLatin1Char('s') && text == QLatin1String("signal")) {
return true;
} else if (ch == QLatin1Char('p') && text == QLatin1String("property")) {
return true;
} else if (ch == QLatin1Char('r') && text == QLatin1String("readonly")) {
return true;
} else {
return false;
}
}
......@@ -55,10 +55,7 @@ public:
// MS VC 6 compatible, still.
void setFormats(const QVector<QTextCharFormat> &s);
QTextCharFormat labelTextCharFormat() const
{ return m_formats[LabelFormat]; }
QSet<QString> keywords();
QTextCharFormat labelTextCharFormat() const;
protected:
virtual int onBlockStart();
......@@ -69,14 +66,14 @@ protected:
virtual void onOpeningParenthesis(QChar parenthesis, int pos);
virtual void onClosingParenthesis(QChar parenthesis, int pos);
virtual void highlightWhitespace(const Token &token, const QString &text, int nonWhitespaceFormat);
bool maybeQmlKeyword(const QStringRef &text) const;
protected:
QmlJSScanner m_scanner;
private:
bool m_duiEnabled;
QTextCharFormat m_formats[NumFormats];
bool m_duiEnabled;
};
} // namespace QmlJS
......
......@@ -33,6 +33,49 @@
using namespace QmlJS;
namespace {
QString js_keywords[] = {
QLatin1String("break"),
QString::fromLatin1("case"),
QString::fromLatin1("catch"),
QString::fromLatin1("continue"),
QString::fromLatin1("debugger"),
QString::fromLatin1("default"),
QString::fromLatin1("delete"),
QString::fromLatin1("do"),
QString::fromLatin1("else"),
QString::fromLatin1("finally"),
QString::fromLatin1("for"),
QString::fromLatin1("function"),
QString::fromLatin1("if"),
QString::fromLatin1("in"),
QString::fromLatin1("instanceof"),
QString::fromLatin1("new"),
QString::fromLatin1("return"),
QString::fromLatin1("switch"),
QString::fromLatin1("this"),
QString::fromLatin1("throw"),
QString::fromLatin1("try"),
QString::fromLatin1("typeof"),
QString::fromLatin1("var"),
QString::fromLatin1("void"),
QString::fromLatin1("while"),
QString::fromLatin1("with")
};
} // end of anonymous namespace
template <typename _Tp, int N>
const _Tp *begin(const _Tp (&a)[N])
{
return a;
}
template <typename _Tp, int N>
const _Tp *end(const _Tp (&a)[N])
{
return a + N;
}
QmlJSScanner::QmlJSScanner()
: m_state(0)
{
......@@ -240,7 +283,15 @@ QList<Token> QmlJSScanner::operator()(const QString &text, int startState)
return tokens;
}
int QmlJSScanner::state() const
{
return m_state;
}
bool QmlJSScanner::isKeyword(const QString &text) const
{
return m_keywords.contains(text);
if (qBinaryFind(begin(js_keywords), end(js_keywords), text) != end(js_keywords))
return true;
return false;
}
......@@ -80,19 +80,12 @@ public:
QmlJSScanner();
virtual ~QmlJSScanner();
void setKeywords(const QSet<QString> keywords)
{ m_keywords = keywords; }
QList<Token> operator()(const QString &text, int startState = 0);
int state() const;
int endState() const
{ return m_state; }
private:
bool isKeyword(const QString &text) const;
private:
QSet<QString> m_keywords;
int m_state;
};
......
......@@ -39,13 +39,6 @@ QmlHighlighter::QmlHighlighter(QTextDocument *parent) :
{
m_currentBlockParentheses.reserve(20);
m_braceDepth = 0;
QSet<QString> qmlKeywords(keywords());
qmlKeywords << QLatin1String("alias");
qmlKeywords << QLatin1String("property");
qmlKeywords << QLatin1String("signal");
qmlKeywords << QLatin1String("readonly");
m_scanner.setKeywords(qmlKeywords);
}
int QmlHighlighter::onBlockStart()
......
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