QmlJS: Fix completion for grouped property bindings.

Task-number: QTCREATORBUG-1388
Reviewed-by: Roberto Raggi
This commit is contained in:
Christian Kamm
2010-05-12 13:58:23 +02:00
parent f88b9d5ab7
commit 28ec223314
5 changed files with 64 additions and 5 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;