Commit d22de18f authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Introduced SemanticInfo::nodeUnderCursor().

parent f8ed5c58
......@@ -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;
}
}
}
}
......
......@@ -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)
......
......@@ -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;
......
Markdown is supported
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