From ce99372c63eb5738460f11600fdc619ab7b7eadb Mon Sep 17 00:00:00 2001 From: Christian Kamm <christian.d.kamm@nokia.com> Date: Tue, 20 Apr 2010 15:19:37 +0200 Subject: [PATCH] QmlJS: Add variables and functions in a JS function to code model. Allows completion of local variable and function names. Task-number: QTCREATORBUG-942 Reviewed-by: Roberto Raggi --- src/libs/qmljs/qmljsbind.cpp | 39 +++++++++++++++++++++++++--- src/libs/qmljs/qmljsbind.h | 3 +++ src/libs/qmljs/qmljsscopebuilder.cpp | 8 ++---- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp index daa047c50e6..dba6cbe0aca 100644 --- a/src/libs/qmljs/qmljsbind.cpp +++ b/src/libs/qmljs/qmljsbind.cpp @@ -107,6 +107,11 @@ bool Bind::usesQmlPrototype(ObjectValue *prototype, return false; } +Interpreter::ObjectValue *Bind::findFunctionScope(AST::FunctionDeclaration *node) const +{ + return _functionScopes.value(node); +} + ObjectValue *Bind::switchObjectValue(ObjectValue *newObjectValue) { ObjectValue *oldObjectValue = _currentObjectValue; @@ -289,9 +294,37 @@ bool Bind::visit(FunctionDeclaration *ast) // return false; ASTFunctionValue *function = new ASTFunctionValue(ast, &_engine); - // ### set the function's scope. - _currentObjectValue->setProperty(ast->name->asString(), function); - return false; // ### eventually want to visit function bodies + // build function scope + ObjectValue *functionScope = _engine.newObject(/*prototype=*/0); + _functionScopes.insert(ast, functionScope); + ObjectValue *parent = switchObjectValue(functionScope); + + // The order of the following is important. Example: A function with name "arguments" + // overrides the arguments object, a variable doesn't. + + // 1. Function formal arguments + for (FormalParameterList *it = ast->formals; it; it = it->next) { + if (it->name) + functionScope->setProperty(it->name->asString(), _engine.undefinedValue()); + } + + // 2. Functions defined inside the function body + // ### TODO, currently covered by the accept(body) + + // 3. Arguments object + ObjectValue *arguments = _engine.newObject(/*prototype=*/0); + arguments->setProperty(QLatin1String("callee"), function); + arguments->setProperty(QLatin1String("length"), _engine.numberValue()); + functionScope->setProperty(QLatin1String("arguments"), arguments); + + // 4. Variables defined inside the function body + // ### TODO, currently covered by the accept(body) + + // visit body + accept(ast->body); + switchObjectValue(parent); + + return false; } diff --git a/src/libs/qmljs/qmljsbind.h b/src/libs/qmljs/qmljsbind.h index 82ed248ce53..a74d8c92ccd 100644 --- a/src/libs/qmljs/qmljsbind.h +++ b/src/libs/qmljs/qmljsbind.h @@ -63,6 +63,8 @@ public: bool usesQmlPrototype(Interpreter::ObjectValue *prototype, Interpreter::Context *context) const; + Interpreter::ObjectValue *findFunctionScope(AST::FunctionDeclaration *node) const; + static QString toString(AST::UiQualifiedId *qualifiedId, QChar delimiter = QChar('.')); protected: @@ -101,6 +103,7 @@ private: Interpreter::ObjectValue *_rootObjectValue; QHash<AST::Node *, Interpreter::ObjectValue *> _qmlObjects; + QHash<AST::FunctionDeclaration *, Interpreter::ObjectValue *> _functionScopes; QStringList _includedScripts; QStringList _fileImports; diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp index 9c63ebbc3a1..a8b84fc5500 100644 --- a/src/libs/qmljs/qmljsscopebuilder.cpp +++ b/src/libs/qmljs/qmljsscopebuilder.cpp @@ -32,12 +32,8 @@ void ScopeBuilder::push(AST::Node *node) // JS scopes if (FunctionDeclaration *fun = cast<FunctionDeclaration *>(node)) { - ObjectValue *activation = _context->engine()->newObject(/*prototype = */ 0); - for (FormalParameterList *it = fun->formals; it; it = it->next) { - if (it->name) - activation->setProperty(it->name->asString(), _context->engine()->undefinedValue()); - } - _context->scopeChain().jsScopes += activation; + ObjectValue *functionScope = _doc->bind()->findFunctionScope(fun); + _context->scopeChain().jsScopes += functionScope; } _context->scopeChain().update(); -- GitLab