Commit 28ec2233 authored by Christian Kamm's avatar Christian Kamm

QmlJS: Fix completion for grouped property bindings.

Task-number: QTCREATORBUG-1388
Reviewed-by: Roberto Raggi
parent f88b9d5a
......@@ -106,6 +106,11 @@ Interpreter::ObjectValue *Bind::findFunctionScope(AST::FunctionDeclaration *node
return _functionScopes.value(node);
}
bool Bind::isGroupedPropertyBinding(AST::Node *node) const
{
return _groupedPropertyBindings.contains(node);
}
ObjectValue *Bind::switchObjectValue(ObjectValue *newObjectValue)
{
ObjectValue *oldObjectValue = _currentObjectValue;
......@@ -139,7 +144,6 @@ ExpressionNode *Bind::expression(UiScriptBinding *ast) const
ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer)
{
ObjectValue *parentObjectValue = 0;
const QString typeName = toString(qualifiedTypeNameId);
// normal component instance
ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, _doc, &_engine);
......@@ -204,8 +208,20 @@ bool Bind::visit(UiPublicMember *)
bool Bind::visit(UiObjectDefinition *ast)
{
ObjectValue *value = bindObject(ast->qualifiedTypeNameId, ast->initializer);
_qmlObjects.insert(ast, value);
// an UiObjectDefinition may be used to group property bindings
// think anchors { ... }
bool isGroupedBinding = false;
for (UiQualifiedId *it = ast->qualifiedTypeNameId; it; it = it->next) {
if (!it->next)
isGroupedBinding = it->name->asString().at(0).isLower();
}
if (!isGroupedBinding) {
ObjectValue *value = bindObject(ast->qualifiedTypeNameId, ast->initializer);
_qmlObjects.insert(ast, value);
} else {
_groupedPropertyBindings.insert(ast);
}
return false;
}
......
......@@ -63,6 +63,7 @@ public:
Interpreter::Context *context) const;
Interpreter::ObjectValue *findFunctionScope(AST::FunctionDeclaration *node) const;
bool isGroupedPropertyBinding(AST::Node *node) const;
static QString toString(AST::UiQualifiedId *qualifiedId, QChar delimiter = QChar('.'));
......@@ -100,6 +101,7 @@ private:
Interpreter::ObjectValue *_rootObjectValue;
QHash<AST::Node *, Interpreter::ObjectValue *> _qmlObjects;
QSet<AST::Node *> _groupedPropertyBindings;
QHash<AST::FunctionDeclaration *, Interpreter::ObjectValue *> _functionScopes;
QStringList _includedScripts;
......
......@@ -66,10 +66,24 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
{
ScopeChain &scopeChain = _context->scopeChain();
scopeChain.qmlScopeObjects.clear();
if (_doc->bind()->isGroupedPropertyBinding(node)) {
UiObjectDefinition *definition = cast<UiObjectDefinition *>(node);
if (!definition)
return;
const Value *v = scopeObjectLookup(definition->qualifiedTypeNameId);
if (!v)
return;
const ObjectValue *object = v->asObjectValue();
if (!object)
return;
scopeChain.qmlScopeObjects.clear();
scopeChain.qmlScopeObjects += object;
}
const ObjectValue *scopeObject = _doc->bind()->findQmlObject(node);
if (scopeObject) {
scopeChain.qmlScopeObjects.clear();
scopeChain.qmlScopeObjects += scopeObject;
} else {
return; // Probably syntax errors, where we're working with a "recovered" AST.
......@@ -130,3 +144,28 @@ void ScopeBuilder::setQmlScopeObject(Node *node)
}
}
}
const Value *ScopeBuilder::scopeObjectLookup(AST::UiQualifiedId *id)
{
// do a name lookup on the scope objects
const Value *result = 0;
foreach (const ObjectValue *scopeObject, _context->scopeChain().qmlScopeObjects) {
const ObjectValue *object = scopeObject;
for (UiQualifiedId *it = id; it; it = it->next) {
result = object->property(it->name->asString(), _context);
if (!result)
break;
if (it->next) {
object = result->asObjectValue();
if (!object) {
result = 0;
break;
}
}
}
if (result)
break;
}
return result;
}
......@@ -13,6 +13,7 @@ namespace AST {
namespace Interpreter {
class Context;
class Value;
}
class QMLJS_EXPORT ScopeBuilder
......@@ -27,6 +28,7 @@ public:
private:
void setQmlScopeObject(AST::Node *node);
const Interpreter::Value *scopeObjectLookup(AST::UiQualifiedId *id);
Document::Ptr _doc;
Interpreter::Context *_context;
......
......@@ -630,7 +630,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
// Set up the current scope chain.
QList<AST::Node *> astPath = semanticInfo.astPath(editor->position());
context.build(astPath , document, snapshot, m_modelManager->importPaths());
context.build(astPath, document, snapshot, m_modelManager->importPaths());
// Search for the operator that triggered the completion.
QChar completionOperator;
......
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