OSDN Git Service

QmlJS highlighting: Use semantics for types and binding names.
authorChristian Kamm <christian.d.kamm@nokia.com>
Mon, 12 Sep 2011 12:00:05 +0000 (14:00 +0200)
committerChristian Kamm <christian.d.kamm@nokia.com>
Wed, 14 Sep 2011 09:51:35 +0000 (11:51 +0200)
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
src/plugins/qmljseditor/qmljssemantichighlighter.cpp
src/plugins/qmljseditor/qmljssemantichighlighter.h
src/plugins/texteditor/texteditorconstants.h
src/plugins/texteditor/texteditorsettings.cpp

index a093c63..beebaf3 100644 (file)
@@ -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:
index cc81c57..c0ba426 100644 (file)
@@ -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
index 18ee030..52549e5 100644 (file)
@@ -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;
index fb06787..9e1ed79 100644 (file)
@@ -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";
index 3c8ca76..0d04562 100644 (file)
@@ -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));