Commit 6db71d18 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Try to get the item under cursor.

parent 24f5a9c0
......@@ -28,14 +28,17 @@
**************************************************************************/
#include "qmljsinterpreter.h"
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
#include <QtCore/QDebug>
#ifndef NO_DECLARATIVE_BACKEND
# include <QtDeclarative/QmlType>
# include <QtDeclarative/QmlMetaType>
# include <QtDeclarative/private/qmlgraphicsanchors_p.h> // ### remove me
# include <QtCore/QMetaObject>
# include <QtCore/QMetaProperty>
# include <QtDeclarative/private/qmlgraphicsrectangle_p.h> // ### remove me
# include <QtDeclarative/private/qmlvaluetype_p.h> // ### remove me
#endif
using namespace QmlJS::Interpreter;
......@@ -1405,6 +1408,10 @@ ObjectValue *Engine::newQmlObject(const QString &name)
QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsAnchors::staticMetaObject, this);
_objects.append(object);
return object;
} else if (name == QLatin1String("QmlGraphicsPen")) {
QmlObjectValue *object = new QmlObjectValue(&QmlGraphicsPen::staticMetaObject, this);
_objects.append(object);
return object;
}
// ### TODO: add support for QML packages
......
......@@ -99,11 +99,11 @@ class FindMembers: protected AST::Visitor
QList<AST::UiObjectMember *> _members;
public:
QList<AST::UiObjectMember *> operator()(AST::Node *node)
QList<AST::UiObjectMember *> operator()(Document::Ptr doc)
{
_members.clear();
if (node)
node->accept(this);
if (doc && doc->qmlProgram())
doc->qmlProgram()->accept(this);
return _members;
}
......@@ -657,6 +657,23 @@ bool QmlCodeCompletion::triggersCompletion(TextEditor::ITextEditable *editor)
return false;
}
static QString qualifiedNameId(AST::UiQualifiedId *it)
{
QString text;
for (; it; it = it->next) {
if (! it->name)
continue;
text += it->name->asString();
if (it->next)
text += QLatin1Char('.');
}
return text;
}
int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
{
m_editor = editor;
......@@ -717,19 +734,86 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
// Set up the current scope chain.
Interpreter::ObjectValue *scope = interp.newObject(/* prototype = */ 0);
// ### FIXME: get the declaring item
Interpreter::ObjectValue *declaringItem = interp.newQmlObject(QLatin1String("Item"));
AST::UiObjectMember *declaringMember = 0;
AST::UiObjectMember *parentMember = 0;
scope->setScope(declaringItem);
declaringItem->setScope(interp.globalObject());
const int cursorLine = edit->textCursor().blockNumber() + 1;
const int cursorColumn = edit->textCursor().columnNumber() + 1;
if (qmlDocument && qmlDocument->qmlProgram()) {
const Interpreter::ObjectValue *parentItem = 0;
const QString declaringItem = QLatin1String("Item"); // ### FIXME: resolve the parent of the declaring item
parentItem = interp.newQmlObject(declaringItem);
scope->setProperty(QLatin1String("parent"), parentItem);
FindMembers findMembers;
const QList<AST::UiObjectMember *> members = findMembers(qmlDocument);
for (int index = 0; index < members.size(); ++index) {
AST::UiObjectMember *member = members.at(index);
AST::SourceLocation pos = member->firstSourceLocation();
const int startLine = pos.startLine;
const int startColumn = pos.startColumn;
if (startLine < cursorLine || (startLine == cursorLine && cursorColumn >= startColumn)) {
AST::SourceLocation endPos = member->lastSourceLocation();
const int endLine = endPos.startLine;
const int endColumn = endPos.startColumn + endPos.length;
if (cursorLine < endLine || (cursorLine == endLine && cursorColumn <= endColumn)) {
parentMember = declaringMember;
declaringMember = member;
}
}
}
// ### TODO: remove me. This is just a quick and dirty hack to get some completion
// for the property definitions.
SearchPropertyDefinitions searchPropertyDefinitions;
const QList<AST::UiPublicMember *> properties = searchPropertyDefinitions(qmlDocument);
foreach (AST::UiPublicMember *prop, properties) {
if (! (prop->name && prop->memberType))
continue;
const QString propName = prop->name->asString();
const QString propType = prop->memberType->asString();
// ### TODO: generalize
if (propType == QLatin1String("string"))
interp.globalObject()->setProperty(propName, interp.stringValue());
else if (propType == QLatin1String("bool"))
interp.globalObject()->setProperty(propName, interp.booleanValue());
else if (propType == QLatin1String("int") || propType == QLatin1String("real"))
interp.globalObject()->setProperty(propName, interp.numberValue());
}
// Get the name of the declaring item.
QString declaringItemName = QLatin1String("Item");
if (AST::UiObjectDefinition *binding = AST::cast<AST::UiObjectDefinition *>(declaringMember))
declaringItemName = qualifiedNameId(binding->qualifiedTypeNameId);
else if (AST::UiObjectBinding *binding = AST::cast<AST::UiObjectBinding *>(declaringMember))
declaringItemName = qualifiedNameId(binding->qualifiedTypeNameId);
Interpreter::ObjectValue *declaringItem = interp.newQmlObject(declaringItemName);
if (! declaringItem)
declaringItem = interp.newQmlObject(QLatin1String("Item"));
if (declaringItem) {
scope->setScope(declaringItem);
declaringItem->setScope(interp.globalObject());
}
// Get the name of the parent of the declaring item.
QString parentItemName = QLatin1String("Item");
if (AST::UiObjectDefinition *binding = AST::cast<AST::UiObjectDefinition *>(parentMember))
parentItemName = qualifiedNameId(binding->qualifiedTypeNameId);
else if (AST::UiObjectBinding *binding = AST::cast<AST::UiObjectBinding *>(parentMember))
parentItemName = qualifiedNameId(binding->qualifiedTypeNameId);
Interpreter::ObjectValue *parentItem = interp.newQmlObject(declaringItemName);
if (! parentItem)
parentItem = interp.newQmlObject(QLatin1String("Item"));
if (parentItem)
scope->setProperty(QLatin1String("parent"), parentItem);
// Search for the operator that triggered the completion.
QChar completionOperator;
if (m_startPosition > 0)
......@@ -784,27 +868,6 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
Evaluate evaluate(&interp);
evaluate.setScope(scope);
// ### TODO: remove me. This is just a quick and dirty hack to get some completion
// for the property definitions.
SearchPropertyDefinitions searchPropertyDefinitions;
const QList<AST::UiPublicMember *> properties = searchPropertyDefinitions(qmlDocument);
foreach (AST::UiPublicMember *prop, properties) {
if (! (prop->name && prop->memberType))
continue;
const QString propName = prop->name->asString();
const QString propType = prop->memberType->asString();
// ### TODO: generalize
if (propType == QLatin1String("string"))
interp.globalObject()->setProperty(propName, interp.stringValue());
else if (propType == QLatin1String("bool"))
interp.globalObject()->setProperty(propName, interp.booleanValue());
else if (propType == QLatin1String("int") || propType == QLatin1String("real"))
interp.globalObject()->setProperty(propName, interp.numberValue());
}
// Evaluate the expression under cursor.
const Interpreter::Value *value = interp.convertToObject(evaluate(exprDoc->ast()));
//qDebug() << "type:" << interp.typeId(value);
......
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