forked from qt-creator/qt-creator
Some initial support for relative imports.
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "parser/qmljsast_p.h"
|
||||
#include "qmljsbind.h"
|
||||
#include "qmljsmetatypesystem.h"
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace QmlJS;
|
||||
using namespace QmlJS::AST;
|
||||
@@ -125,7 +126,10 @@ static QString serialize(UiQualifiedId *qualifiedId, QChar delimiter)
|
||||
*/
|
||||
bool Bind::visit(UiImport *ast)
|
||||
{
|
||||
ObjectValue *namespaceObject;
|
||||
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)
|
||||
@@ -142,32 +146,57 @@ bool Bind::visit(UiImport *ast)
|
||||
// look at files first
|
||||
|
||||
// else try the metaobject system
|
||||
if (!ast->importUri)
|
||||
return false;
|
||||
if (ast->importUri) {
|
||||
const QString package = serialize(ast->importUri, '/');
|
||||
int majorVersion = -1; // ### TODO: Check these magic version numbers
|
||||
int minorVersion = -1; // ### TODO: Check these magic version numbers
|
||||
|
||||
const QString package = serialize(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) {
|
||||
// got an import "contents"
|
||||
const QString relativePath = ast->fileName->asString();
|
||||
const QList<Document::Ptr> userComponents = _snapshot.importedDocuments(_doc, relativePath);
|
||||
foreach (Document::Ptr userComponent, userComponents) {
|
||||
if (UiProgram *program = userComponent->qmlProgram()) {
|
||||
if (UiObjectMemberList *members = program->members) {
|
||||
if (UiObjectDefinition *def = cast<UiObjectDefinition *>(members->member)) {
|
||||
const ObjectValue *prototype = lookupType(def->qualifiedTypeNameId);
|
||||
ObjectValue *objectValue = _interp->newObject(prototype);
|
||||
if (def->initializer) {
|
||||
for (AST::UiObjectMemberList *it = def->initializer->members; it; it = it->next) {
|
||||
if (AST::UiPublicMember *prop = AST::cast<AST::UiPublicMember *>(it->member)) {
|
||||
if (prop->name && prop->memberType) {
|
||||
const QString propName = prop->name->asString();
|
||||
const QString propType = prop->memberType->asString();
|
||||
objectValue->setProperty(propName, _interp->defaultValueForBuiltinType(propType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
_typeEnvironment->setProperty(userComponent->componentName(), objectValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_DECLARATIVE_BACKEND
|
||||
foreach (QmlObjectValue *object, _interp->metaTypeSystem().staticTypesForImport(package, majorVersion, minorVersion)) {
|
||||
namespaceObject->setProperty(object->qmlTypeName(), object);
|
||||
}
|
||||
#endif // NO_DECLARATIVE_BACKEND
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -199,15 +228,15 @@ const ObjectValue *Bind::lookupType(UiQualifiedId *qualifiedTypeNameId)
|
||||
{
|
||||
const ObjectValue *objectValue = _typeEnvironment;
|
||||
|
||||
for (UiQualifiedId *iter = qualifiedTypeNameId; iter; iter = iter->next) {
|
||||
if (! (iter->name))
|
||||
for (UiQualifiedId *iter = qualifiedTypeNameId; objectValue && iter; iter = iter->next) {
|
||||
if (! iter->name)
|
||||
return 0;
|
||||
|
||||
const Value *value = objectValue->property(iter->name->asString());
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
objectValue = value->asObjectValue();
|
||||
if (!objectValue)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return objectValue;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <qmljs/parser/qmljsparser_p.h>
|
||||
#include <qmljs/parser/qmljsnodepool_p.h>
|
||||
#include <qmljs/parser/qmljsastfwd_p.h>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
using namespace QmlJS;
|
||||
using namespace QmlJS;
|
||||
@@ -47,12 +48,14 @@ Document::Document(const QString &fileName)
|
||||
, _parsedCorrectly(false)
|
||||
, _fileName(fileName)
|
||||
{
|
||||
const int slashIdx = fileName.lastIndexOf('/');
|
||||
if (slashIdx != -1)
|
||||
_path = fileName.left(slashIdx);
|
||||
|
||||
if (fileName.toLower().endsWith(".qml"))
|
||||
_componentName = fileName.mid(slashIdx + 1, fileName.size() - (slashIdx + 1) - 4);
|
||||
QFileInfo fileInfo(fileName);
|
||||
_path = fileInfo.absolutePath();
|
||||
_componentName = fileInfo.baseName();
|
||||
if (! _componentName.isEmpty()) {
|
||||
// ### TODO: check the component name.
|
||||
if (! _componentName.at(0).isUpper())
|
||||
_componentName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Document::~Document()
|
||||
@@ -220,7 +223,7 @@ Snapshot::~Snapshot()
|
||||
void Snapshot::insert(const Document::Ptr &document)
|
||||
{
|
||||
if (document && (document->qmlProgram() || document->jsProgram()))
|
||||
QMap<QString, Document::Ptr>::insert(document->fileName(), document);
|
||||
_documents.insert(document->fileName(), document);
|
||||
}
|
||||
|
||||
Document::PtrList Snapshot::importedDocuments(const Document::Ptr &doc, const QString &importPath) const
|
||||
@@ -229,11 +232,16 @@ Document::PtrList Snapshot::importedDocuments(const Document::Ptr &doc, const QS
|
||||
|
||||
Document::PtrList result;
|
||||
|
||||
const QString docPath = doc->path() + '/' + importPath;
|
||||
QString docPath = doc->path();
|
||||
docPath += QLatin1Char('/');
|
||||
docPath += importPath;
|
||||
docPath = QDir::cleanPath(docPath);
|
||||
|
||||
foreach (Document::Ptr candidate, *this) {
|
||||
foreach (Document::Ptr candidate, _documents) {
|
||||
if (candidate == doc)
|
||||
continue;
|
||||
continue; // ignore this document
|
||||
else if (! candidate->qmlProgram())
|
||||
continue; // skip JS documents
|
||||
|
||||
if (candidate->path() == doc->path() || candidate->path() == docPath)
|
||||
result.append(candidate);
|
||||
|
||||
@@ -101,16 +101,25 @@ private:
|
||||
QmlJS::Symbol::List _symbols;
|
||||
};
|
||||
|
||||
class QMLJS_EXPORT Snapshot: public QMap<QString, Document::Ptr>
|
||||
class QMLJS_EXPORT Snapshot
|
||||
{
|
||||
typedef QMap<QString, Document::Ptr> _Base;
|
||||
QMap<QString, Document::Ptr> _documents;
|
||||
|
||||
public:
|
||||
Snapshot();
|
||||
~Snapshot();
|
||||
|
||||
typedef _Base::iterator iterator;
|
||||
typedef _Base::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return _documents.begin(); }
|
||||
const_iterator end() const { return _documents.end(); }
|
||||
|
||||
void insert(const Document::Ptr &document);
|
||||
|
||||
Document::Ptr document(const QString &fileName) const
|
||||
{ return value(fileName); }
|
||||
{ return _documents.value(fileName); }
|
||||
|
||||
Document::PtrList importedDocuments(const Document::Ptr &doc, const QString &importPath) const;
|
||||
QMap<QString, Document::Ptr> componentsDefinedByImportedDocuments(const Document::Ptr &doc, const QString &importPath) const;
|
||||
|
||||
Reference in New Issue
Block a user