From 1a0fb751cde975f43564c9a8b1475c263acecc9a Mon Sep 17 00:00:00 2001 From: Christian Kamm <christian.d.kamm@nokia.com> Date: Mon, 12 Sep 2011 14:00:05 +0200 Subject: [PATCH] QmlJS highlighting: Use semantics for types and binding names. This fixes some problems with highlighting like anchors {}, allows us to only highlight correct types and to make the binding name formatting customizable. Change-Id: I7ab0c0ed384108b74a2998796d868d5ced4a5310 Reviewed-on: http://codereview.qt-project.org/4669 Reviewed-by: Thomas Hartmann <Thomas.Hartmann@nokia.com> --- src/plugins/qmljseditor/qmljshighlighter.cpp | 48 ------------------- .../qmljseditor/qmljssemantichighlighter.cpp | 34 +++++++++++++ .../qmljseditor/qmljssemantichighlighter.h | 4 +- src/plugins/texteditor/texteditorconstants.h | 1 + src/plugins/texteditor/texteditorsettings.cpp | 2 + 5 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/plugins/qmljseditor/qmljshighlighter.cpp b/src/plugins/qmljseditor/qmljshighlighter.cpp index a093c639381..beebaf33ef7 100644 --- a/src/plugins/qmljseditor/qmljshighlighter.cpp +++ b/src/plugins/qmljseditor/qmljshighlighter.cpp @@ -166,54 +166,6 @@ void Highlighter::highlightBlock(const QString &text) break; } } - - if (!spell.isEmpty() && spell.at(0).isUpper()) - setFormat(token.offset, token.length, m_formats[TypeFormat]); - - if (index + 1 < tokens.size()) { - bool maybeBinding = (index == 0 || checkStartOfBinding(tokens.at(index - 1))); - bool maybeOnBinding = false; - if (index > 0) { - const Token &previousToken = tokens.at(index - 1); - if (text.midRef(previousToken.offset, previousToken.length) == QLatin1String("on")) { - maybeOnBinding = true; - maybeBinding = false; - } - } - - if (maybeBinding || maybeOnBinding) { - Token::Kind expectedTerminator = Token::Colon; - if (maybeOnBinding) - expectedTerminator = Token::LeftBrace; - - const int start = index; - - // put index on last identifier not followed by .identifier - while (index + 2 < tokens.size() && - tokens.at(index + 1).is(Token::Dot) && - tokens.at(index + 2).is(Token::Identifier)) { - index += 2; - } - - if (index + 1 < tokens.size() && tokens.at(index + 1).is(expectedTerminator)) { - // it's a binding. - for (int i = start; i <= index; ++i) { - const Token &tok = tokens.at(i); - if (tok.kind == Token::Dot) - continue; - const QStringRef tokSpell = text.midRef(tok.offset, tok.length); - if (!tokSpell.isEmpty() && tokSpell.at(0).isUpper()) { - setFormat(tok.offset, tok.length, m_formats[TypeFormat]); - } else { - setFormat(tok.offset, tok.length, m_formats[FieldFormat]); - } - } - break; - } else { - index = start; - } - } - } } break; case Token::Delimiter: diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp index cc81c57cc7b..c0ba42675b4 100644 --- a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp +++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp @@ -40,6 +40,7 @@ #include <qmljs/qmljsevaluate.h> #include <qmljs/qmljscontext.h> #include <qmljs/qmljsbind.h> +#include <qmljs/qmljscheck.h> #include <qmljs/parser/qmljsast_p.h> #include <qmljs/parser/qmljsastvisitor_p.h> #include <texteditor/syntaxhighlighter.h> @@ -249,26 +250,57 @@ protected: addUse(location, type); } + void processTypeId(UiQualifiedId *typeId) + { + if (!typeId) + return; + if (m_scopeChain.context()->lookupType(m_scopeChain.document().data(), typeId)) + addUse(fullLocationForQualifiedId(typeId), SemanticHighlighter::QmlTypeType); + } + + void processBindingName(UiQualifiedId *localId) + { + if (!localId) + return; + addUse(fullLocationForQualifiedId(localId), SemanticHighlighter::BindingNameType); + } + bool visit(UiObjectDefinition *ast) { + if (m_scopeChain.document()->bind()->isGroupedPropertyBinding(ast)) { + processBindingName(ast->qualifiedTypeNameId); + } else { + processTypeId(ast->qualifiedTypeNameId); + } scopedAccept(ast, ast->initializer); return false; } bool visit(UiObjectBinding *ast) { + processTypeId(ast->qualifiedTypeNameId); + processBindingName(ast->qualifiedId); scopedAccept(ast, ast->initializer); return false; } bool visit(UiScriptBinding *ast) { + processBindingName(ast->qualifiedId); scopedAccept(ast, ast->statement); return false; } + bool visit(UiArrayBinding *ast) + { + processBindingName(ast->qualifiedId); + return true; + } + bool visit(UiPublicMember *ast) { + if (ast->identifierToken.isValid()) + addUse(ast->identifierToken, SemanticHighlighter::BindingNameType); scopedAccept(ast, ast->statement); return false; } @@ -436,6 +468,8 @@ void SemanticHighlighter::updateFontSettings(const TextEditor::FontSettings &fon m_formats[JsImportType] = fontSettings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_JS_IMPORT_VAR)); m_formats[JsGlobalType] = fontSettings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_JS_GLOBAL_VAR)); m_formats[LocalStateNameType] = fontSettings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_QML_STATE_NAME)); + m_formats[BindingNameType] = fontSettings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_BINDING)); + m_formats[FieldType] = fontSettings.toTextCharFormat(QLatin1String(TextEditor::Constants::C_FIELD)); } int SemanticHighlighter::startRevision() const diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.h b/src/plugins/qmljseditor/qmljssemantichighlighter.h index 18ee0306575..52549e55f58 100644 --- a/src/plugins/qmljseditor/qmljssemantichighlighter.h +++ b/src/plugins/qmljseditor/qmljssemantichighlighter.h @@ -69,7 +69,9 @@ public: JsScopeType, // var or function in local js scope JsImportType, // name of js import JsGlobalType, // in global scope - LocalStateNameType // name of a state in the current file + LocalStateNameType, // name of a state in the current file + BindingNameType, // name on the left hand side of a binding + FieldType // member of an object }; typedef TextEditor::SemanticHighlighter::Result Use; diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index fb06787a1bc..9e1ed7911e0 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -138,6 +138,7 @@ const char * const C_JS_SCOPE_VAR = "JsScopeVar"; const char * const C_JS_IMPORT_VAR = "JsImportVar"; const char * const C_JS_GLOBAL_VAR = "JsGlobalVar"; const char * const C_QML_STATE_NAME = "QmlStateName"; +const char * const C_BINDING = "Binding"; const char * const C_DISABLED_CODE = "DisabledCode"; diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp index 3c8ca761637..0d04562bc38 100644 --- a/src/plugins/texteditor/texteditorsettings.cpp +++ b/src/plugins/texteditor/texteditorsettings.cpp @@ -146,6 +146,8 @@ TextEditorSettings::TextEditorSettings(QObject *parent) virtualMethodFormatDescriptor.format().setItalic(true); formatDescriptions.append(virtualMethodFormatDescriptor); + formatDescriptions.append(FormatDescription(QLatin1String(C_BINDING), tr("QML Binding"), Qt::darkRed)); + Format qmlLocalNameFormat; qmlLocalNameFormat.setItalic(true); formatDescriptions.append(FormatDescription(QLatin1String(C_QML_LOCAL_ID), tr("QML Local Id"), qmlLocalNameFormat)); -- GitLab