forked from qt-creator/qt-creator
QmlJS: Fix completion for grouped property bindings.
Task-number: QTCREATORBUG-1388 Reviewed-by: Roberto Raggi
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user