forked from qt-creator/qt-creator
Completion for global variables in JS.
* Support for lookup JS vs Qml * Bind global variables. Done-with: ckamm
This commit is contained in:
@@ -41,88 +41,6 @@ using namespace QmlJS;
|
||||
using namespace QmlJS::AST;
|
||||
using namespace QmlJS::Interpreter;
|
||||
|
||||
namespace {
|
||||
|
||||
class ASTObjectValue: public ObjectValue
|
||||
{
|
||||
UiQualifiedId *_typeName;
|
||||
UiObjectInitializer *_initializer;
|
||||
|
||||
public:
|
||||
ASTObjectValue(UiQualifiedId *typeName, UiObjectInitializer *initializer, Interpreter::Engine *engine)
|
||||
: ObjectValue(engine), _typeName(typeName), _initializer(initializer)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void processMembers(MemberProcessor *processor) const
|
||||
{
|
||||
if (_initializer) {
|
||||
for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
|
||||
UiObjectMember *member = it->member;
|
||||
if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
|
||||
if (def->name && def->memberType) {
|
||||
const QString propName = def->name->asString();
|
||||
const QString propType = def->memberType->asString();
|
||||
|
||||
processor->processProperty(propName, engine()->defaultValueForBuiltinType(propType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectValue::processMembers(processor);
|
||||
}
|
||||
};
|
||||
|
||||
class ASTFunctionValue: public FunctionValue
|
||||
{
|
||||
FunctionDeclaration *_ast;
|
||||
QList<NameId *> _argumentNames;
|
||||
|
||||
public:
|
||||
ASTFunctionValue(FunctionDeclaration *ast, Interpreter::Engine *engine)
|
||||
: FunctionValue(engine), _ast(ast)
|
||||
{
|
||||
setPrototype(engine->functionPrototype());
|
||||
|
||||
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
||||
_argumentNames.append(it->name);
|
||||
}
|
||||
|
||||
FunctionDeclaration *ast() const { return _ast; }
|
||||
|
||||
virtual const Value *returnValue() const
|
||||
{
|
||||
return engine()->undefinedValue();
|
||||
}
|
||||
|
||||
virtual int argumentCount() const
|
||||
{
|
||||
return _argumentNames.size();
|
||||
}
|
||||
|
||||
virtual const Value *argument(int) const
|
||||
{
|
||||
return engine()->undefinedValue();
|
||||
}
|
||||
|
||||
virtual QString argumentName(int index) const
|
||||
{
|
||||
if (index < _argumentNames.size()) {
|
||||
if (NameId *nameId = _argumentNames.at(index))
|
||||
return nameId->asString();
|
||||
}
|
||||
|
||||
return FunctionValue::argumentName(index);
|
||||
}
|
||||
|
||||
virtual bool isVariadic() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
Bind::Bind(Document *doc)
|
||||
: _doc(doc),
|
||||
_currentObjectValue(0),
|
||||
@@ -130,18 +48,8 @@ Bind::Bind(Document *doc)
|
||||
_functionEnvironment(0),
|
||||
_rootObjectValue(0)
|
||||
{
|
||||
if (!_doc)
|
||||
return;
|
||||
|
||||
if (_doc->qmlProgram()) {
|
||||
_idEnvironment = _interp.newObject(/*prototype =*/ 0);
|
||||
_functionEnvironment = _interp.newObject(/*prototype =*/ 0);
|
||||
} else if (_doc->jsProgram()) {
|
||||
_currentObjectValue = _interp.globalObject();
|
||||
_rootObjectValue = _interp.globalObject();
|
||||
}
|
||||
|
||||
accept(_doc->ast());
|
||||
if (_doc)
|
||||
accept(_doc->ast());
|
||||
}
|
||||
|
||||
Bind::~Bind()
|
||||
@@ -248,6 +156,20 @@ void Bind::accept(Node *node)
|
||||
Node::accept(node, this);
|
||||
}
|
||||
|
||||
bool Bind::visit(AST::UiProgram *)
|
||||
{
|
||||
_idEnvironment = _interp.newObject(/*prototype =*/ 0);
|
||||
_functionEnvironment = _interp.newObject(/*prototype =*/ 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bind::visit(AST::Program *)
|
||||
{
|
||||
_currentObjectValue = _interp.globalObject();
|
||||
_rootObjectValue = _interp.globalObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bind::visit(UiImport *ast)
|
||||
{
|
||||
if (ast->fileName) {
|
||||
@@ -305,6 +227,16 @@ bool Bind::visit(UiArrayBinding *)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bind::visit(VariableDeclaration *ast)
|
||||
{
|
||||
if (! ast->name)
|
||||
return false;
|
||||
|
||||
ASTVariableReference *ref = new ASTVariableReference(ast, &_interp);
|
||||
_currentObjectValue->setProperty(ast->name->asString(), ref);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bind::visit(FunctionDeclaration *ast)
|
||||
{
|
||||
if (!ast->name)
|
||||
|
||||
@@ -61,6 +61,9 @@ protected:
|
||||
|
||||
void accept(AST::Node *node);
|
||||
|
||||
virtual bool visit(AST::UiProgram *ast);
|
||||
virtual bool visit(AST::Program *ast);
|
||||
|
||||
// Ui
|
||||
virtual bool visit(AST::UiImport *ast);
|
||||
virtual bool visit(AST::UiPublicMember *ast);
|
||||
@@ -68,7 +71,10 @@ protected:
|
||||
virtual bool visit(AST::UiObjectBinding *ast);
|
||||
virtual bool visit(AST::UiScriptBinding *ast);
|
||||
virtual bool visit(AST::UiArrayBinding *ast);
|
||||
|
||||
// QML/JS
|
||||
virtual bool visit(AST::FunctionDeclaration *ast);
|
||||
virtual bool visit(AST::VariableDeclaration *ast);
|
||||
|
||||
protected:
|
||||
Interpreter::ObjectValue *switchObjectValue(Interpreter::ObjectValue *newObjectValue);
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
using namespace QmlJS;
|
||||
using namespace QmlJS::Interpreter;
|
||||
|
||||
Check::Check(Link *link)
|
||||
: _engine(link->engine()),
|
||||
_link(link),
|
||||
Check::Check(Context *context)
|
||||
: _engine(context->engine()),
|
||||
_context(context),
|
||||
_scope(_engine->globalObject()),
|
||||
_result(0)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ const Interpreter::Value *Check::check(AST::Node *ast)
|
||||
const Value *result = switchResult(previousResult);
|
||||
|
||||
if (const Reference *ref = value_cast<const Reference *>(result))
|
||||
result = ref->value(_link->context());
|
||||
result = ref->value(_context);
|
||||
|
||||
if (! result)
|
||||
result = _engine->undefinedValue();
|
||||
@@ -165,7 +165,7 @@ bool Check::visit(AST::UiQualifiedId *ast)
|
||||
if (! ast->name)
|
||||
return false;
|
||||
|
||||
const Value *value = _link->lookup(ast->name->asString());
|
||||
const Value *value = _context->lookup(ast->name->asString());
|
||||
if (! ast->next) {
|
||||
_result = value;
|
||||
|
||||
@@ -213,7 +213,7 @@ bool Check::visit(AST::IdentifierExpression *ast)
|
||||
if (! ast->name)
|
||||
return false;
|
||||
|
||||
_result = _link->lookup(ast->name->asString());
|
||||
_result = _context->lookup(ast->name->asString());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Interpreter {
|
||||
class QMLJS_EXPORT Check: protected AST::Visitor
|
||||
{
|
||||
public:
|
||||
Check(Link *link);
|
||||
Check(Interpreter::Context *context);
|
||||
virtual ~Check();
|
||||
|
||||
const Interpreter::Value *operator()(AST::Node *ast);
|
||||
@@ -158,7 +158,7 @@ protected:
|
||||
private:
|
||||
QmlJS::Document::Ptr _doc;
|
||||
Interpreter::Engine *_engine;
|
||||
Link *_link;
|
||||
Interpreter::Context *_context;
|
||||
const Interpreter::ObjectValue *_scope;
|
||||
const Interpreter::Value *_result;
|
||||
};
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "qmljsinterpreter.h"
|
||||
|
||||
#include "qmljscheck.h"
|
||||
#include "parser/qmljsast_p.h"
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QMetaProperty>
|
||||
#include <QtCore/QDebug>
|
||||
@@ -42,6 +43,7 @@
|
||||
#endif
|
||||
|
||||
using namespace QmlJS::Interpreter;
|
||||
using namespace QmlJS::AST;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -677,7 +679,8 @@ void StringValue::accept(ValueVisitor *visitor) const
|
||||
|
||||
|
||||
Context::Context(Engine *engine)
|
||||
: _engine(engine)
|
||||
: _engine(engine),
|
||||
_lookupMode(JSLookup)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -690,6 +693,46 @@ Engine *Context::engine() const
|
||||
return _engine;
|
||||
}
|
||||
|
||||
Context::ScopeChain Context::scopeChain() const
|
||||
{
|
||||
return _scopeChain;
|
||||
}
|
||||
|
||||
Context::LookupMode Context::lookupMode() const
|
||||
{
|
||||
return _lookupMode;
|
||||
}
|
||||
|
||||
void Context::setLookupMode(LookupMode lookupMode)
|
||||
{
|
||||
_lookupMode = lookupMode;
|
||||
}
|
||||
|
||||
void Context::pushScope(const ObjectValue *object)
|
||||
{
|
||||
_scopeChain.append(object);
|
||||
}
|
||||
|
||||
void Context::popScope()
|
||||
{
|
||||
_scopeChain.removeLast();
|
||||
}
|
||||
|
||||
const Value *Context::lookup(const QString &name) const
|
||||
{
|
||||
for (int index = _scopeChain.size() - 1; index != -1; --index) {
|
||||
const ObjectValue *scope = _scopeChain.at(index);
|
||||
|
||||
if (const Value *member = scope->lookupMember(name)) {
|
||||
if (_lookupMode == JSLookup || ! dynamic_cast<const ASTVariableReference *>(member)) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _engine->undefinedValue();
|
||||
}
|
||||
|
||||
const Value *Context::property(const ObjectValue *object, const QString &name) const
|
||||
{
|
||||
const Properties properties = _properties.value(object);
|
||||
@@ -701,14 +744,21 @@ void Context::setProperty(const ObjectValue *object, const QString &name, const
|
||||
_properties[object].insert(name, value);
|
||||
}
|
||||
|
||||
Reference::Reference()
|
||||
Reference::Reference(Engine *engine)
|
||||
: _engine(engine)
|
||||
{
|
||||
_engine->registerValue(this);
|
||||
}
|
||||
|
||||
Reference::~Reference()
|
||||
{
|
||||
}
|
||||
|
||||
Engine *Reference::engine() const
|
||||
{
|
||||
return _engine;
|
||||
}
|
||||
|
||||
const Reference *Reference::asReference() const
|
||||
{
|
||||
return this;
|
||||
@@ -719,6 +769,10 @@ void Reference::accept(ValueVisitor *visitor) const
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
const Value *Reference::value(Context *) const
|
||||
{
|
||||
return _engine->undefinedValue();
|
||||
}
|
||||
|
||||
MemberProcessor::MemberProcessor()
|
||||
{
|
||||
@@ -757,7 +811,7 @@ ObjectValue::ObjectValue(Engine *engine)
|
||||
: _engine(engine),
|
||||
_prototype(0)
|
||||
{
|
||||
engine->registerObject(this);
|
||||
engine->registerValue(this);
|
||||
}
|
||||
|
||||
ObjectValue::~ObjectValue()
|
||||
@@ -1314,7 +1368,7 @@ Engine::Engine()
|
||||
|
||||
Engine::~Engine()
|
||||
{
|
||||
qDeleteAll(_registeredObjects);
|
||||
qDeleteAll(_registeredValues);
|
||||
}
|
||||
|
||||
const NullValue *Engine::nullValue() const
|
||||
@@ -1456,9 +1510,9 @@ const ObjectValue *Engine::mathObject() const
|
||||
return _mathObject;
|
||||
}
|
||||
|
||||
void Engine::registerObject(ObjectValue *object)
|
||||
void Engine::registerValue(Value *value)
|
||||
{
|
||||
_registeredObjects.append(object);
|
||||
_registeredValues.append(value);
|
||||
}
|
||||
|
||||
const Value *Engine::convertToBoolean(const Value *value)
|
||||
@@ -1802,3 +1856,94 @@ QmlObjectValue *Engine::newQmlObject(const QString &name, const QString &prefix,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ASTObjectValue::ASTObjectValue(UiQualifiedId *typeName, UiObjectInitializer *initializer, Engine *engine)
|
||||
: ObjectValue(engine), _typeName(typeName), _initializer(initializer)
|
||||
{
|
||||
}
|
||||
|
||||
ASTObjectValue::~ASTObjectValue()
|
||||
{
|
||||
}
|
||||
|
||||
void ASTObjectValue::processMembers(MemberProcessor *processor) const
|
||||
{
|
||||
if (_initializer) {
|
||||
for (UiObjectMemberList *it = _initializer->members; it; it = it->next) {
|
||||
UiObjectMember *member = it->member;
|
||||
if (UiPublicMember *def = cast<UiPublicMember *>(member)) {
|
||||
if (def->name && def->memberType) {
|
||||
const QString propName = def->name->asString();
|
||||
const QString propType = def->memberType->asString();
|
||||
|
||||
processor->processProperty(propName, engine()->defaultValueForBuiltinType(propType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectValue::processMembers(processor);
|
||||
}
|
||||
|
||||
ASTVariableReference::ASTVariableReference(VariableDeclaration *ast, Engine *engine)
|
||||
: Reference(engine), _ast(ast)
|
||||
{
|
||||
}
|
||||
|
||||
ASTVariableReference::~ASTVariableReference()
|
||||
{
|
||||
}
|
||||
|
||||
const Value *ASTVariableReference::value(Context *context) const
|
||||
{
|
||||
Check check(context);
|
||||
return check(_ast->expression);
|
||||
}
|
||||
|
||||
ASTFunctionValue::ASTFunctionValue(FunctionDeclaration *ast, Engine *engine)
|
||||
: FunctionValue(engine), _ast(ast)
|
||||
{
|
||||
setPrototype(engine->functionPrototype());
|
||||
|
||||
for (FormalParameterList *it = ast->formals; it; it = it->next)
|
||||
_argumentNames.append(it->name);
|
||||
}
|
||||
|
||||
ASTFunctionValue::~ASTFunctionValue()
|
||||
{
|
||||
}
|
||||
|
||||
FunctionDeclaration *ASTFunctionValue::ast() const
|
||||
{
|
||||
return _ast;
|
||||
}
|
||||
|
||||
const Value *ASTFunctionValue::returnValue() const
|
||||
{
|
||||
return engine()->undefinedValue();
|
||||
}
|
||||
|
||||
int ASTFunctionValue::argumentCount() const
|
||||
{
|
||||
return _argumentNames.size();
|
||||
}
|
||||
|
||||
const Value *ASTFunctionValue::argument(int) const
|
||||
{
|
||||
return engine()->undefinedValue();
|
||||
}
|
||||
|
||||
QString ASTFunctionValue::argumentName(int index) const
|
||||
{
|
||||
if (index < _argumentNames.size()) {
|
||||
if (NameId *nameId = _argumentNames.at(index))
|
||||
return nameId->asString();
|
||||
}
|
||||
|
||||
return FunctionValue::argumentName(index);
|
||||
}
|
||||
|
||||
bool ASTFunctionValue::isVariadic() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <qmljs/qmljs_global.h>
|
||||
#include <qmljs/qmljsmetatypesystem.h>
|
||||
#include <qmljs/parser/qmljsastfwd_p.h>
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QString>
|
||||
@@ -39,6 +40,9 @@
|
||||
#include <QtCore/QSet>
|
||||
|
||||
namespace QmlJS {
|
||||
|
||||
class NameId;
|
||||
|
||||
namespace Interpreter {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -207,11 +211,28 @@ public:
|
||||
|
||||
class QMLJS_EXPORT Context
|
||||
{
|
||||
public:
|
||||
typedef QList<const ObjectValue *> ScopeChain;
|
||||
|
||||
enum LookupMode {
|
||||
JSLookup,
|
||||
QmlLookup
|
||||
};
|
||||
|
||||
public:
|
||||
Context(Engine *engine);
|
||||
virtual ~Context();
|
||||
~Context();
|
||||
|
||||
Engine *engine() const;
|
||||
ScopeChain scopeChain() const;
|
||||
|
||||
LookupMode lookupMode() const;
|
||||
void setLookupMode(LookupMode lookupMode);
|
||||
|
||||
void pushScope(const ObjectValue *object);
|
||||
void popScope();
|
||||
|
||||
const Value *lookup(const QString &name) const;
|
||||
|
||||
const Value *property(const ObjectValue *object, const QString &name) const;
|
||||
void setProperty(const ObjectValue *object, const QString &name, const Value *value);
|
||||
@@ -220,20 +241,26 @@ private:
|
||||
typedef QHash<QString, const Value *> Properties;
|
||||
|
||||
Engine *_engine;
|
||||
LookupMode _lookupMode;
|
||||
QHash<const ObjectValue *, Properties> _properties;
|
||||
ScopeChain _scopeChain;
|
||||
};
|
||||
|
||||
class QMLJS_EXPORT Reference: public Value
|
||||
{
|
||||
public:
|
||||
Reference();
|
||||
Reference(Engine *engine);
|
||||
virtual ~Reference();
|
||||
|
||||
virtual const Value *value(const Context *context) const = 0;
|
||||
Engine *engine() const;
|
||||
virtual const Value *value(Context *context) const;
|
||||
|
||||
// Value interface
|
||||
virtual const Reference *asReference() const;
|
||||
virtual void accept(ValueVisitor *) const;
|
||||
|
||||
private:
|
||||
Engine *_engine;
|
||||
};
|
||||
|
||||
class QMLJS_EXPORT ObjectValue: public Value
|
||||
@@ -506,8 +533,6 @@ public:
|
||||
ObjectValue *globalObject() const;
|
||||
const ObjectValue *mathObject() const;
|
||||
|
||||
void registerObject(ObjectValue *object);
|
||||
|
||||
// prototypes
|
||||
ObjectValue *objectPrototype() const;
|
||||
ObjectValue *functionPrototype() const;
|
||||
@@ -539,6 +564,8 @@ public:
|
||||
const MetaTypeSystem &metaTypeSystem() const
|
||||
{ return _metaTypeSystem; }
|
||||
|
||||
void registerValue(Value *value); // internal
|
||||
|
||||
private:
|
||||
void initializePrototypes();
|
||||
|
||||
@@ -575,7 +602,7 @@ private:
|
||||
NumberValue _numberValue;
|
||||
BooleanValue _booleanValue;
|
||||
StringValue _stringValue;
|
||||
QList<ObjectValue *> _registeredObjects;
|
||||
QList<Value *> _registeredValues;
|
||||
|
||||
ConvertToNumber _convertToNumber;
|
||||
ConvertToString _convertToString;
|
||||
@@ -585,6 +612,51 @@ private:
|
||||
MetaTypeSystem _metaTypeSystem;
|
||||
};
|
||||
|
||||
|
||||
// internal
|
||||
class QMLJS_EXPORT ASTObjectValue: public ObjectValue
|
||||
{
|
||||
AST::UiQualifiedId *_typeName;
|
||||
AST::UiObjectInitializer *_initializer;
|
||||
|
||||
public:
|
||||
ASTObjectValue(AST::UiQualifiedId *typeName, AST::UiObjectInitializer *initializer, Engine *engine);
|
||||
virtual ~ASTObjectValue();
|
||||
|
||||
virtual void processMembers(MemberProcessor *processor) const;
|
||||
};
|
||||
|
||||
class QMLJS_EXPORT ASTVariableReference: public Reference
|
||||
{
|
||||
AST::VariableDeclaration *_ast;
|
||||
|
||||
public:
|
||||
ASTVariableReference(AST::VariableDeclaration *ast, Engine *engine);
|
||||
virtual ~ASTVariableReference();
|
||||
|
||||
virtual const Value *value(Context *context) const;
|
||||
};
|
||||
|
||||
class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
|
||||
{
|
||||
AST::FunctionDeclaration *_ast;
|
||||
QList<NameId *> _argumentNames;
|
||||
|
||||
public:
|
||||
ASTFunctionValue(AST::FunctionDeclaration *ast, Engine *engine);
|
||||
virtual ~ASTFunctionValue();
|
||||
|
||||
AST::FunctionDeclaration *ast() const;
|
||||
|
||||
virtual const Value *returnValue() const;
|
||||
virtual int argumentCount() const;
|
||||
virtual const Value *argument(int) const;
|
||||
virtual QString argumentName(int index) const;
|
||||
virtual bool isVariadic() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} } // end of namespace QmlJS::Interpreter
|
||||
|
||||
#endif // QMLJS_INTERPRETER_H
|
||||
|
||||
@@ -14,7 +14,6 @@ using namespace QmlJS::AST;
|
||||
|
||||
Link::Link(Document::Ptr currentDoc, const Snapshot &snapshot, Interpreter::Engine *interp)
|
||||
: _snapshot(snapshot)
|
||||
, _interp(interp)
|
||||
, _context(interp)
|
||||
{
|
||||
_docs = reachableDocuments(currentDoc, snapshot);
|
||||
@@ -41,64 +40,58 @@ Context *Link::context()
|
||||
return &_context;
|
||||
}
|
||||
|
||||
Link::ScopeChain Link::scopeChain() const
|
||||
{
|
||||
return _scopeChain;
|
||||
}
|
||||
|
||||
Interpreter::Engine *Link::engine()
|
||||
{
|
||||
return _interp;
|
||||
return _context.engine();
|
||||
}
|
||||
|
||||
void Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
|
||||
{
|
||||
_scopeChain.clear();
|
||||
_context.pushScope(engine()->globalObject());
|
||||
|
||||
if (! doc) {
|
||||
_scopeChain.append(_interp->globalObject());
|
||||
if (! doc)
|
||||
return;
|
||||
}
|
||||
|
||||
if (doc->qmlProgram() != 0)
|
||||
_context.setLookupMode(Context::QmlLookup);
|
||||
|
||||
BindPtr bind = doc->bind();
|
||||
|
||||
// Build the scope chain.
|
||||
_scopeChain.append(_typeEnvironments.value(doc.data()));
|
||||
_scopeChain.append(bind->_idEnvironment);
|
||||
_scopeChain.append(bind->_functionEnvironment);
|
||||
|
||||
foreach (const QString &scriptFile, doc->bind()->includedScripts()) {
|
||||
// ### FIXME: May want to link to instantiating components from here.
|
||||
|
||||
if (bind->_rootObjectValue)
|
||||
_context.pushScope(bind->_rootObjectValue);
|
||||
|
||||
ObjectValue *scopeObject = 0;
|
||||
if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(currentObject))
|
||||
scopeObject = bind->_qmlObjects.value(definition);
|
||||
else if (UiObjectBinding *binding = cast<UiObjectBinding *>(currentObject))
|
||||
scopeObject = bind->_qmlObjects.value(binding);
|
||||
|
||||
if (scopeObject && scopeObject != bind->_rootObjectValue)
|
||||
_context.pushScope(scopeObject);
|
||||
|
||||
const QStringList &includedScripts = bind->includedScripts();
|
||||
for (int index = includedScripts.size() - 1; index != -1; --index) {
|
||||
const QString &scriptFile = includedScripts.at(index);
|
||||
|
||||
if (Document::Ptr scriptDoc = _snapshot.document(scriptFile)) {
|
||||
if (scriptDoc->jsProgram()) {
|
||||
_scopeChain.append(scriptDoc->bind()->_rootObjectValue);
|
||||
_context.pushScope(scriptDoc->bind()->_rootObjectValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bind->_functionEnvironment)
|
||||
_context.pushScope(bind->_functionEnvironment);
|
||||
|
||||
if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(currentObject)) {
|
||||
ObjectValue *scopeObject = bind->_qmlObjects.value(definition);
|
||||
_scopeChain.append(scopeObject);
|
||||
if (bind->_idEnvironment)
|
||||
_context.pushScope(bind->_idEnvironment);
|
||||
|
||||
// ### FIXME: should add the root regardless
|
||||
if (scopeObject != bind->_rootObjectValue)
|
||||
_scopeChain.append(bind->_rootObjectValue);
|
||||
}
|
||||
|
||||
_scopeChain.append(bind->_interp.globalObject());
|
||||
|
||||
// May want to link to instantiating components from here.
|
||||
}
|
||||
|
||||
const Value *Link::lookup(const QString &name) const
|
||||
{
|
||||
foreach (const ObjectValue *scope, _scopeChain) {
|
||||
if (const Value *member = scope->lookupMember(name)) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
|
||||
return _interp->undefinedValue();
|
||||
if (const ObjectValue *typeEnvironment = _typeEnvironments.value(doc.data()))
|
||||
_context.pushScope(typeEnvironment);
|
||||
}
|
||||
|
||||
void Link::linkImports()
|
||||
@@ -106,7 +99,7 @@ void Link::linkImports()
|
||||
foreach (Document::Ptr doc, _docs) {
|
||||
BindPtr bind = doc->bind();
|
||||
|
||||
ObjectValue *typeEnv = _interp->newObject(/*prototype =*/0);
|
||||
ObjectValue *typeEnv = engine()->newObject(/*prototype =*/0); // ### FIXME
|
||||
_typeEnvironments.insert(doc.data(), typeEnv);
|
||||
|
||||
// Populate the _typeEnvironment with imports.
|
||||
@@ -205,7 +198,7 @@ void Link::importFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc,
|
||||
continue;
|
||||
|
||||
if (directoryImport && import->importId && !importNamespace) {
|
||||
importNamespace = _interp->newObject(/*prototype =*/0);
|
||||
importNamespace = engine()->newObject(/*prototype =*/0);
|
||||
typeEnv->setProperty(import->importId->asString(), importNamespace);
|
||||
}
|
||||
|
||||
@@ -234,7 +227,7 @@ void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, A
|
||||
ObjectValue *namespaceObject = 0;
|
||||
|
||||
if (import->importId) { // with namespace we insert an object in the type env. to hold the imported types
|
||||
namespaceObject = _interp->newObject(/*prototype */ 0);
|
||||
namespaceObject = engine()->newObject(/*prototype */ 0);
|
||||
typeEnv->setProperty(import->importId->asString(), namespaceObject);
|
||||
|
||||
} else { // without namespace we insert all types directly into the type env.
|
||||
@@ -260,7 +253,7 @@ void Link::importNonFile(Interpreter::ObjectValue *typeEnv, Document::Ptr doc, A
|
||||
}
|
||||
}
|
||||
#ifndef NO_DECLARATIVE_BACKEND
|
||||
foreach (QmlObjectValue *object, _interp->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) {
|
||||
foreach (QmlObjectValue *object, engine()->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) {
|
||||
namespaceObject->setProperty(object->qmlTypeName(), object);
|
||||
}
|
||||
#endif // NO_DECLARATIVE_BACKEND
|
||||
|
||||
@@ -18,23 +18,17 @@ namespace QmlJS {
|
||||
*/
|
||||
class QMLJS_EXPORT Link
|
||||
{
|
||||
public:
|
||||
typedef QList<const Interpreter::ObjectValue *> ScopeChain;
|
||||
|
||||
public:
|
||||
// Link all documents in snapshot reachable from doc.
|
||||
Link(Document::Ptr doc, const Snapshot &snapshot, Interpreter::Engine *interp);
|
||||
~Link();
|
||||
|
||||
Interpreter::Context *context();
|
||||
ScopeChain scopeChain() const;
|
||||
Interpreter::Engine *engine();
|
||||
|
||||
// Get the scope chain for the currentObject inside doc.
|
||||
void scopeChainAt(Document::Ptr doc, AST::Node *currentObject);
|
||||
|
||||
const Interpreter::Value *lookup(const QString &name) const;
|
||||
|
||||
private:
|
||||
static QList<Document::Ptr> reachableDocuments(Document::Ptr startDoc, const Snapshot &snapshot);
|
||||
static const Interpreter::ObjectValue *lookupType(Interpreter::ObjectValue *env, AST::UiQualifiedId *id);
|
||||
@@ -51,11 +45,9 @@ private:
|
||||
|
||||
private:
|
||||
Snapshot _snapshot;
|
||||
Interpreter::Engine *_interp;
|
||||
Interpreter::Context _context;
|
||||
QList<Document::Ptr> _docs;
|
||||
QHash<Document *, Interpreter::ObjectValue *> _typeEnvironments;
|
||||
ScopeChain _scopeChain;
|
||||
};
|
||||
|
||||
} // namespace QmlJS
|
||||
|
||||
Reference in New Issue
Block a user