diff --git a/src/libs/qmljs/qmljshighlighter.cpp b/src/libs/qmljs/qmljshighlighter.cpp index 81dbf34415c27f7a8da45081e0c7c237fa53d353..81c01d2b3308f9f9f4db98890d1f5c35aaabc7ec 100644 --- a/src/libs/qmljs/qmljshighlighter.cpp +++ b/src/libs/qmljs/qmljshighlighter.cpp @@ -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; } } diff --git a/src/libs/qmljs/qmljshighlighter.h b/src/libs/qmljs/qmljshighlighter.h index d289d91a5b6d9020d8c8c4fb64822bff29bd7790..e2e3e65ee1c6481c8441f16e97a15e3b45780be3 100644 --- a/src/libs/qmljs/qmljshighlighter.h +++ b/src/libs/qmljs/qmljshighlighter.h @@ -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 diff --git a/src/libs/qmljs/qmljsscanner.cpp b/src/libs/qmljs/qmljsscanner.cpp index 72ae34a0bba69e5be7a1537bcccd213e9c8dd9dc..c916f1aa234f236b954322af7b6fea0edb80842e 100644 --- a/src/libs/qmljs/qmljsscanner.cpp +++ b/src/libs/qmljs/qmljsscanner.cpp @@ -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; } diff --git a/src/libs/qmljs/qmljsscanner.h b/src/libs/qmljs/qmljsscanner.h index 9c98714fc69afa1dd860a033073152e4996fe36e..ae2485a52bcd8577cbcb1376c65e86f583048f29 100644 --- a/src/libs/qmljs/qmljsscanner.h +++ b/src/libs/qmljs/qmljsscanner.h @@ -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; }; diff --git a/src/plugins/qmljseditor/qmlhighlighter.cpp b/src/plugins/qmljseditor/qmlhighlighter.cpp index 797a3585ecaaf810e11225654969d8a956699748..2c431407a579432d0449efd40f580aff5e842d60 100644 --- a/src/plugins/qmljseditor/qmlhighlighter.cpp +++ b/src/plugins/qmljseditor/qmlhighlighter.cpp @@ -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()