From d22de18fae2ee42ba314879f56b6c86c46de6f4b Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Tue, 2 Feb 2010 13:18:56 +0100 Subject: [PATCH] Introduced SemanticInfo::nodeUnderCursor(). --- src/plugins/qmljseditor/qmlhoverhandler.cpp | 53 ++++++------- src/plugins/qmljseditor/qmljseditor.cpp | 83 +++++++++++++-------- src/plugins/qmljseditor/qmljseditor.h | 3 + 3 files changed, 76 insertions(+), 63 deletions(-) diff --git a/src/plugins/qmljseditor/qmlhoverhandler.cpp b/src/plugins/qmljseditor/qmlhoverhandler.cpp index 44b5e8184d4..f247aa9a800 100644 --- a/src/plugins/qmljseditor/qmlhoverhandler.cpp +++ b/src/plugins/qmljseditor/qmlhoverhandler.cpp @@ -39,6 +39,7 @@ #include <qmljs/qmljsbind.h> #include <qmljs/qmljscheck.h> #include <qmljs/qmljsinterpreter.h> +#include <qmljs/parser/qmljsast_p.h> #include <texteditor/itexteditor.h> #include <texteditor/basetexteditor.h> @@ -151,9 +152,6 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in m_helpEngineNeedsSetup = false; } - QTextCursor tc(edit->document()); - tc.setPosition(pos); - // We only want to show F1 if the tooltip matches the help id bool showF1 = true; @@ -166,36 +164,27 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in QString symbolName = QLatin1String("<unknown>"); if (m_helpId.isEmpty()) { - // Move to the end of a qualified name - bool stop = false; - while (!stop) { - const QChar ch = editor->characterAt(tc.position()); - if (ch.isLetterOrNumber() || ch == QLatin1Char('_')) { - tc.setPosition(tc.position() + 1); - } else { - stop = true; - } - } + AST::Node *node = semanticInfo.nodeUnderCursor(pos); + if (node && !(AST::cast<AST::StringLiteral *>(node) != 0 || AST::cast<AST::NumericLiteral *>(node) != 0)) { + AST::UiObjectMember *declaringMember = semanticInfo.declaringMember(pos); + + Interpreter::Engine interp; + Interpreter::ObjectValue *scope = Bind::scopeChainAt(qmlDocument, snapshot, &interp, declaringMember); + + Check check(&interp); + const Interpreter::Value *value = check(node->expressionCast(), scope); + + QStringList baseClasses; + m_toolTip = prettyPrint(value, &interp, &baseClasses); + + foreach (const QString &baseClass, baseClasses) { + QString helpId = QLatin1String("QML."); + helpId += baseClass; - // Fetch the expression's code - QmlExpressionUnderCursor expressionUnderCursor; - QmlJS::AST::ExpressionNode *expression = expressionUnderCursor(tc); - - AST::UiObjectMember *declaringMember = semanticInfo.declaringMember(pos); - - Interpreter::Engine interp; - Interpreter::ObjectValue *scope = Bind::scopeChainAt(qmlDocument, snapshot, &interp, declaringMember); - Check check(&interp); - const Interpreter::Value *value = check(expression, scope); - QStringList baseClasses; - m_toolTip = prettyPrint(value, &interp, &baseClasses); - foreach (const QString &baseClass, baseClasses) { - QString helpId = QLatin1String("QML."); - helpId += baseClass; - - if (! m_helpEngine->linksForIdentifier(helpId).isEmpty()) { - m_helpId = helpId; - break; + if (! m_helpEngine->linksForIdentifier(helpId).isEmpty()) { + m_helpId = helpId; + break; + } } } } diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 34398fcc81b..0b25fccbbad 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -481,6 +481,38 @@ AST::UiObjectMember *SemanticInfo::declaringMember(int cursorPosition) const return declaringMember; } +AST::Node *SemanticInfo::nodeUnderCursor(int pos) const +{ + if (! document) + return 0; + + const unsigned cursorPosition = pos; + + CollectASTNodes nodes; + nodes.accept(document->ast()); + + foreach (AST::UiQualifiedId *q, nodes.qualifiedIds) { + if (cursorPosition >= q->identifierToken.begin()) { + for (AST::UiQualifiedId *tail = q; tail; tail = tail->next) { + if (! tail->next && cursorPosition <= tail->identifierToken.end()) + return q; + } + } + } + + foreach (AST::IdentifierExpression *id, nodes.identifiers) { + if (cursorPosition >= id->identifierToken.begin() && cursorPosition <= id->identifierToken.end()) + return id; + } + + foreach (AST::FieldMemberExpression *mem, nodes.fieldMembers) { + if (mem->name && cursorPosition >= mem->identifierToken.begin() && cursorPosition <= mem->identifierToken.end()) + return mem; + } + + return 0; +} + int SemanticInfo::revision() const { if (document) @@ -834,46 +866,35 @@ void QmlJSTextEditor::createToolBar(QmlJSEditorEditable *editable) TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &cursor, bool /*resolveTarget*/) { - Link link; const SemanticInfo semanticInfo = m_semanticInfo; + const unsigned cursorPosition = cursor.position(); - if (semanticInfo.document && semanticInfo.revision() == document()->revision()) { - CollectASTNodes nodes; - nodes.accept(semanticInfo.document->ast()); - - const unsigned cursorPosition = cursor.position(); - - foreach (AST::UiQualifiedId *q, nodes.qualifiedIds) { - if (cursorPosition >= q->identifierToken.begin()) { - for (AST::UiQualifiedId *tail = q; tail; tail = tail->next) { - if (! tail->next && cursorPosition <= tail->identifierToken.end()) { - link.begin = tail->identifierToken.begin(); - link.end = tail->identifierToken.end(); - return link; - } - } - } - } - - foreach (AST::IdentifierExpression *id, nodes.identifiers) { - if (cursorPosition >= id->identifierToken.begin() && cursorPosition <= id->identifierToken.end()) { - link.begin = id->firstSourceLocation().begin(); - link.end = id->lastSourceLocation().end(); - return link; - } - } + AST::Node *node = semanticInfo.nodeUnderCursor(cursorPosition); - foreach (AST::FieldMemberExpression *mem, nodes.fieldMembers) { - if (mem->name && cursorPosition >= mem->identifierToken.begin() && cursorPosition <= mem->identifierToken.end()) { - link.begin = mem->lastSourceLocation().begin(); - link.end = mem->lastSourceLocation().end(); + if (AST::UiQualifiedId *q = AST::cast<AST::UiQualifiedId *>(node)) { + for (AST::UiQualifiedId *tail = q; tail; tail = tail->next) { + if (! tail->next && cursorPosition <= tail->identifierToken.end()) { + Link link; + link.begin = tail->identifierToken.begin(); + link.end = tail->identifierToken.end(); return link; } } + } else if (AST::IdentifierExpression *id = AST::cast<AST::IdentifierExpression *>(node)) { + Link link; + link.begin = id->firstSourceLocation().begin(); + link.end = id->lastSourceLocation().end(); + return link; + + } else if (AST::FieldMemberExpression *mem = AST::cast<AST::FieldMemberExpression *>(node)) { + Link link; + link.begin = mem->lastSourceLocation().begin(); + link.end = mem->lastSourceLocation().end(); + return link; } - return link; + return Link(); } void QmlJSTextEditor::contextMenuEvent(QContextMenuEvent *e) diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 139644e75bc..3991eefa19a 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -108,6 +108,9 @@ public: // Returns the declaring member QmlJS::AST::UiObjectMember *declaringMember(int cursorPosition) const; + // Returns the AST node under cursor + QmlJS::AST::Node *nodeUnderCursor(int cursorPosition) const; + public: // attributes QmlJS::Document::Ptr document; QmlJS::Snapshot snapshot; -- GitLab