forked from qt-creator/qt-creator
Bind each QML document after parsing. Link them before use.
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
@@ -121,76 +121,27 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ProcessSourceElements: protected AST::Visitor
|
||||
{
|
||||
Interpreter::Engine *_interp;
|
||||
|
||||
public:
|
||||
ProcessSourceElements(Interpreter::Engine *interp)
|
||||
: _interp(interp),
|
||||
typeOfExpression(interp)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(AST::Node *node)
|
||||
{
|
||||
if (node)
|
||||
node->accept(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
using AST::Visitor::visit;
|
||||
|
||||
virtual bool visit(FunctionDeclaration *ast)
|
||||
{
|
||||
if (ast->name)
|
||||
_interp->globalObject()->setProperty(ast->name->asString(), new ASTFunctionValue(ast, _interp));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(VariableDeclaration *ast)
|
||||
{
|
||||
if (ast->name) {
|
||||
const Value *value = _interp->undefinedValue();
|
||||
|
||||
if (ast->expression)
|
||||
value = typeOfExpression(ast->expression, _interp->globalObject());
|
||||
|
||||
_interp->globalObject()->setProperty(ast->name->asString(), value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Check typeOfExpression;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
Bind::Bind(Document::Ptr doc, Interpreter::Engine *interp)
|
||||
Bind::Bind(Document *doc)
|
||||
: _doc(doc),
|
||||
_interp(interp),
|
||||
_currentObjectValue(0),
|
||||
_typeEnvironment(0),
|
||||
_idEnvironment(0),
|
||||
_functionEnvironment(0),
|
||||
_rootObjectValue(0)
|
||||
{
|
||||
if (_doc && _doc->qmlProgram() != 0) {
|
||||
UiProgram *program = _doc->qmlProgram();
|
||||
if (!_doc)
|
||||
return;
|
||||
|
||||
_currentObjectValue = 0;
|
||||
_typeEnvironment = _interp->newObject(/*prototype =*/ 0);
|
||||
_idEnvironment = _interp->newObject(/*prototype =*/ 0);
|
||||
_functionEnvironment = _interp->newObject(/*prototype =*/ 0);
|
||||
_rootObjectValue = 0;
|
||||
|
||||
_qmlObjectDefinitions.clear();
|
||||
_qmlObjectBindings.clear();
|
||||
|
||||
accept(program);
|
||||
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());
|
||||
}
|
||||
|
||||
Bind::~Bind()
|
||||
@@ -214,77 +165,6 @@ ObjectValue *Bind::switchObjectValue(ObjectValue *newObjectValue)
|
||||
return oldObjectValue;
|
||||
}
|
||||
|
||||
ObjectValue *Bind::scopeChainAt(Document::Ptr currentDocument, const Snapshot &snapshot,
|
||||
Interpreter::Engine *interp, AST::UiObjectMember *currentObject)
|
||||
{
|
||||
Bind *currentBind = 0;
|
||||
QList<Bind *> binds;
|
||||
|
||||
QSet<QString> processed;
|
||||
QStringList todo;
|
||||
|
||||
QMultiHash<QString, Document::Ptr> documentByPath;
|
||||
foreach (Document::Ptr doc, snapshot)
|
||||
documentByPath.insert(doc->path(), doc);
|
||||
|
||||
todo.append(currentDocument->path());
|
||||
|
||||
// Bind the reachable documents.
|
||||
while (! todo.isEmpty()) {
|
||||
const QString path = todo.takeFirst();
|
||||
|
||||
if (processed.contains(path))
|
||||
continue;
|
||||
|
||||
processed.insert(path);
|
||||
|
||||
QStringList localImports;
|
||||
foreach (Document::Ptr doc, documentByPath.values(path)) {
|
||||
Bind *newBind = new Bind(doc, interp);
|
||||
binds += newBind;
|
||||
|
||||
localImports += newBind->localImports();
|
||||
|
||||
if (doc == currentDocument)
|
||||
currentBind = newBind;
|
||||
}
|
||||
|
||||
localImports.removeDuplicates();
|
||||
todo += localImports;
|
||||
}
|
||||
|
||||
LinkImports linkImports;
|
||||
Link link;
|
||||
|
||||
// link the import directives
|
||||
linkImports(binds);
|
||||
|
||||
// link the scripts
|
||||
QStringList includedScriptFiles;
|
||||
foreach (Bind *bind, binds)
|
||||
includedScriptFiles += bind->includedScripts();
|
||||
|
||||
includedScriptFiles.removeDuplicates();
|
||||
|
||||
ProcessSourceElements processSourceElements(interp);
|
||||
|
||||
foreach (const QString &scriptFile, includedScriptFiles) {
|
||||
if (Document::Ptr scriptDoc = snapshot.document(scriptFile)) {
|
||||
if (AST::Program *program = scriptDoc->jsProgram()) {
|
||||
processSourceElements(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectValue *scope = interp->globalObject();
|
||||
if (currentBind)
|
||||
scope = link(binds, currentBind, currentObject);
|
||||
|
||||
qDeleteAll(binds);
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
QString Bind::toString(UiQualifiedId *qualifiedId, QChar delimiter)
|
||||
{
|
||||
QString result;
|
||||
@@ -350,7 +230,7 @@ ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitia
|
||||
}
|
||||
|
||||
// normal component instance
|
||||
ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, _interp);
|
||||
ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, &_interp);
|
||||
parentObjectValue = switchObjectValue(objectValue);
|
||||
|
||||
if (parentObjectValue)
|
||||
@@ -368,64 +248,9 @@ void Bind::accept(Node *node)
|
||||
Node::accept(node, this);
|
||||
}
|
||||
|
||||
/*
|
||||
import Qt 4.6
|
||||
import Qt 4.6 as Xxx
|
||||
(import com.nokia.qt is the same as the ones above)
|
||||
|
||||
import "content"
|
||||
import "content" as Xxx
|
||||
import "content" 4.6
|
||||
import "content" 4.6 as Xxx
|
||||
|
||||
import "http://www.ovi.com/" as Ovi
|
||||
*/
|
||||
// ### TODO: Move to LinkImports
|
||||
bool Bind::visit(UiImport *ast)
|
||||
{
|
||||
if (! (ast->importUri || ast->fileName))
|
||||
return false; // nothing to do.
|
||||
|
||||
ObjectValue *namespaceObject = 0;
|
||||
|
||||
if (ast->asToken.isValid()) { // with namespace we insert an object in the type env. to hold the imported types
|
||||
if (!ast->importId)
|
||||
return false; // this should never happen, but better be safe than sorry
|
||||
|
||||
namespaceObject = _interp->newObject(/*prototype */ 0);
|
||||
|
||||
_typeEnvironment->setProperty(ast->importId->asString(), namespaceObject);
|
||||
|
||||
} else { // without namespace we insert all types directly into the type env.
|
||||
namespaceObject = _typeEnvironment;
|
||||
}
|
||||
|
||||
// look at files first
|
||||
|
||||
// else try the metaobject system
|
||||
if (ast->importUri) {
|
||||
const QString package = toString(ast->importUri, '/');
|
||||
int majorVersion = -1; // ### TODO: Check these magic version numbers
|
||||
int minorVersion = -1; // ### TODO: Check these magic version numbers
|
||||
|
||||
if (ast->versionToken.isValid()) {
|
||||
const QString versionString = _doc->source().mid(ast->versionToken.offset, ast->versionToken.length);
|
||||
const int dotIdx = versionString.indexOf(QLatin1Char('.'));
|
||||
if (dotIdx == -1) {
|
||||
// only major (which is probably invalid, but let's handle it anyway)
|
||||
majorVersion = versionString.toInt();
|
||||
minorVersion = 0; // ### TODO: Check with magic version numbers above
|
||||
} else {
|
||||
majorVersion = versionString.left(dotIdx).toInt();
|
||||
minorVersion = versionString.mid(dotIdx + 1).toInt();
|
||||
}
|
||||
}
|
||||
#ifndef NO_DECLARATIVE_BACKEND
|
||||
foreach (QmlObjectValue *object, _interp->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) {
|
||||
namespaceObject->setProperty(object->qmlTypeName(), object);
|
||||
}
|
||||
#endif // NO_DECLARATIVE_BACKEND
|
||||
} else if (ast->fileName) {
|
||||
if (ast->fileName) {
|
||||
QString path = _doc->path();
|
||||
path += QLatin1Char('/');
|
||||
path += ast->fileName->asString();
|
||||
@@ -488,7 +313,7 @@ bool Bind::visit(FunctionDeclaration *ast)
|
||||
if (_currentObjectValue->property(ast->name->asString()))
|
||||
return false;
|
||||
|
||||
ASTFunctionValue *function = new ASTFunctionValue(ast, _interp);
|
||||
ASTFunctionValue *function = new ASTFunctionValue(ast, &_interp);
|
||||
_currentObjectValue->setProperty(ast->name->asString(), function);
|
||||
return false; // ### eventually want to visit function bodies
|
||||
}
|
||||
|
Reference in New Issue
Block a user