aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorChristian Kamm <[email protected]>2011-10-12 08:36:02 +0200
committerChristian Kamm <[email protected]>2011-10-21 08:21:00 +0200
commit0b75a66407eda8de22f0ab141ccbc976daff44b4 (patch)
tree70cb46d5cbd4f4d032c956189cb676650b1358d4 /src/libs
parent55420e2b7070b552fe7790935e56b846d10242f7 (diff)
QmlJS: Support module apis defined by QML modules.
Change-Id: I18ec9daf8088f7db5ff2da11da14b539f501bab3 Reviewed-by: Fawzi Mohamed <[email protected]>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/qmljs/qmljsdocument.h15
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp10
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h2
-rw-r--r--src/libs/qmljs/qmljslink.cpp38
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.cpp68
-rw-r--r--src/libs/qmljs/qmljstypedescriptionreader.h9
6 files changed, 132 insertions, 10 deletions
diff --git a/src/libs/qmljs/qmljsdocument.h b/src/libs/qmljs/qmljsdocument.h
index 65c500c119d..50e7a81034d 100644
--- a/src/libs/qmljs/qmljsdocument.h
+++ b/src/libs/qmljs/qmljsdocument.h
@@ -128,6 +128,14 @@ private:
friend class Snapshot;
};
+class QMLJS_EXPORT ModuleApiInfo
+{
+public:
+ QString uri;
+ LanguageUtils::ComponentVersion version;
+ QString cppName;
+};
+
class QMLJS_EXPORT LibraryInfo
{
public:
@@ -152,6 +160,7 @@ private:
QList<QmlDirParser::TypeInfo> _typeinfos;
typedef QList<LanguageUtils::FakeMetaObject::ConstPtr> FakeMetaObjectList;
FakeMetaObjectList _metaObjects;
+ QList<ModuleApiInfo> _moduleApis;
PluginTypeInfoStatus _dumpStatus;
QString _dumpError;
@@ -176,6 +185,12 @@ public:
void setMetaObjects(const FakeMetaObjectList &objects)
{ _metaObjects = objects; }
+ QList<ModuleApiInfo> moduleApis() const
+ { return _moduleApis; }
+
+ void setModuleApis(const QList<ModuleApiInfo> &apis)
+ { _moduleApis = apis; }
+
bool isValid() const
{ return _status == Found; }
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index b448212e3d9..3a1ff62e8c2 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -1285,13 +1285,10 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
QString error, warning;
QFile file(qmlTypeFile.absoluteFilePath());
if (file.open(QIODevice::ReadOnly)) {
- QString contents = QString::fromUtf8(file.readAll());
+ QByteArray contents = file.readAll();
file.close();
- TypeDescriptionReader reader(contents);
- if (!reader(&newObjects))
- error = reader.errorMessage();
- warning = reader.warningMessage();
+ parseQmlTypeDescriptions(contents, &newObjects, 0, &error, &warning);
} else {
error = file.errorString();
}
@@ -1312,13 +1309,14 @@ CppQmlTypesLoader::BuiltinObjects CppQmlTypesLoader::loadQmlTypes(const QFileInf
void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml,
BuiltinObjects *newObjects,
+ QList<ModuleApiInfo> *newModuleApis,
QString *errorMessage,
QString *warningMessage)
{
errorMessage->clear();
warningMessage->clear();
TypeDescriptionReader reader(QString::fromUtf8(xml));
- if (!reader(newObjects)) {
+ if (!reader(newObjects, newModuleApis)) {
if (reader.errorMessage().isEmpty()) {
*errorMessage = QLatin1String("unknown error");
} else {
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index c914d28d0f8..7b95f2d31fc 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -643,7 +643,7 @@ public:
static void parseQmlTypeDescriptions(
const QByteArray &qmlTypes,
BuiltinObjects *newObjects,
- QString *errorMessage, QString *warningMessage);
+ QList<ModuleApiInfo> *newModuleApis, QString *errorMessage, QString *warningMessage);
};
class QMLJS_EXPORT CppQmlTypes
diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp
index 3e8cc72f147..0c78ab56c24 100644
--- a/src/libs/qmljs/qmljslink.cpp
+++ b/src/libs/qmljs/qmljslink.cpp
@@ -89,6 +89,8 @@ public:
QHash<ImportCacheKey, Import> importCache;
+ QHash<QString, QList<ModuleApiInfo> > importableModuleApis;
+
Document::Ptr document;
QList<DiagnosticMessage> *diagnosticMessages;
@@ -231,6 +233,8 @@ Context::ImportsPerDocument LinkPrivate::linkImports()
void LinkPrivate::populateImportedTypes(Imports *imports, Document::Ptr doc)
{
+ importableModuleApis.clear();
+
// implicit imports: the <default> package is always available
loadImplicitDefaultImports(imports);
@@ -315,6 +319,18 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i
return import;
}
+static ModuleApiInfo findBestModuleApi(const QList<ModuleApiInfo> &apis, const ComponentVersion &version)
+{
+ ModuleApiInfo best;
+ foreach (const ModuleApiInfo &moduleApi, apis) {
+ if (moduleApi.version <= version
+ && (!best.version.isValid() || best.version < moduleApi.version)) {
+ best = moduleApi;
+ }
+ }
+ return best;
+}
+
/*
import Qt 4.6
import Qt 4.6 as Xxx
@@ -372,6 +388,13 @@ Import LinkPrivate::importNonFile(Document::Ptr doc, const ImportInfo &importInf
}
}
+ // check module apis that previous imports may have enabled
+ ModuleApiInfo moduleApi = findBestModuleApi(importableModuleApis.value(packageName), version);
+ if (moduleApi.version.isValid()) {
+ importFound = true;
+ import.object->setPrototype(valueOwner->cppQmlTypes().objectByCppName(moduleApi.name));
+ }
+
if (!importFound && importInfo.ast()) {
import.valid = false;
error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
@@ -442,6 +465,21 @@ bool LinkPrivate::importLibrary(Document::Ptr doc,
foreach (const CppComponentValue *object, valueOwner->cppQmlTypes().createObjectsForImport(packageName, version)) {
import->object->setMember(object->className(), object);
}
+
+ // all but no-uri module apis become available for import
+ QList<ModuleApiInfo> noUriModuleApis;
+ foreach (const ModuleApiInfo &moduleApi, libraryInfo.moduleApis()) {
+ if (moduleApi.uri.isEmpty()) {
+ noUriModuleApis += moduleApi;
+ } else {
+ importableModuleApis[moduleApi.uri] += moduleApi;
+ }
+ }
+
+ // if a module api has no uri, it shares the same name
+ ModuleApiInfo sameUriModuleApi = findBestModuleApi(noUriModuleApis, version);
+ if (sameUriModuleApi.version.isValid())
+ import->object->setPrototype(valueOwner->cppQmlTypes().objectByCppName(sameUriModuleApi.name));
}
}
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.cpp b/src/libs/qmljs/qmljstypedescriptionreader.cpp
index 02b7a034653..44b7a47e15f 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.cpp
+++ b/src/libs/qmljs/qmljstypedescriptionreader.cpp
@@ -59,7 +59,9 @@ TypeDescriptionReader::~TypeDescriptionReader()
{
}
-bool TypeDescriptionReader::operator()(QHash<QString, FakeMetaObject::ConstPtr> *objects)
+bool TypeDescriptionReader::operator()(
+ QHash<QString, FakeMetaObject::ConstPtr> *objects,
+ QList<ModuleApiInfo> *moduleApis)
{
Engine engine;
@@ -77,6 +79,7 @@ bool TypeDescriptionReader::operator()(QHash<QString, FakeMetaObject::ConstPtr>
}
_objects = objects;
+ _moduleApis = moduleApis;
readDocument(parser.ast());
return _errorMessage.isEmpty();
@@ -152,8 +155,11 @@ void TypeDescriptionReader::readModule(UiObjectDefinition *ast)
continue;
}
- if (typeName == QLatin1String("Component"))
+ if (typeName == QLatin1String("Component")) {
readComponent(component);
+ } else if (typeName == QLatin1String("ModuleApi")) {
+ readModuleApi(component);
+ }
}
}
@@ -226,6 +232,40 @@ void TypeDescriptionReader::readComponent(UiObjectDefinition *ast)
_objects->insert(fmo->className(), fmo);
}
+void TypeDescriptionReader::readModuleApi(UiObjectDefinition *ast)
+{
+ ModuleApiInfo apiInfo;
+
+ for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) {
+ UiObjectMember *member = it->member;
+ UiScriptBinding *script = dynamic_cast<UiScriptBinding *>(member);
+
+ if (script) {
+ const QString name = toString(script->qualifiedId);
+ if (name == "uri") {
+ apiInfo.uri = readStringBinding(script);
+ } else if (name == "version") {
+ apiInfo.version = readNumericVersionBinding(script);
+ } else if (name == "name") {
+ apiInfo.name = readStringBinding(script);
+ } else {
+ addWarning(script->firstSourceLocation(),
+ "Expected only uri, version and name script bindings");
+ }
+ } else {
+ addWarning(member->firstSourceLocation(), "Expected only script bindings");
+ }
+ }
+
+ if (!apiInfo.version.isValid()) {
+ addError(ast->firstSourceLocation(), "ModuleApi definition has no or invalid 'version' binding");
+ return;
+ }
+
+ if (_moduleApis)
+ _moduleApis->append(apiInfo);
+}
+
void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isMethod, FakeMetaObject::Ptr fmo)
{
FakeMetaMethod fmm;
@@ -438,6 +478,30 @@ double TypeDescriptionReader::readNumericBinding(AST::UiScriptBinding *ast)
return numericLit->value;
}
+ComponentVersion TypeDescriptionReader::readNumericVersionBinding(UiScriptBinding *ast)
+{
+ ComponentVersion invalidVersion;
+
+ if (!ast || !ast->statement) {
+ addError(ast->colonToken, "Expected numeric literal after colon");
+ return invalidVersion;
+ }
+
+ ExpressionStatement *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
+ if (!expStmt) {
+ addError(ast->statement->firstSourceLocation(), "Expected numeric literal after colon");
+ return invalidVersion;
+ }
+
+ NumericLiteral *numericLit = AST::cast<NumericLiteral *>(expStmt->expression);
+ if (!numericLit) {
+ addError(expStmt->firstSourceLocation(), "Expected numeric literal after colon");
+ return invalidVersion;
+ }
+
+ return ComponentVersion(_source.mid(numericLit->literalToken.begin(), numericLit->literalToken.length));
+}
+
int TypeDescriptionReader::readIntBinding(AST::UiScriptBinding *ast)
{
double v = readNumericBinding(ast);
diff --git a/src/libs/qmljs/qmljstypedescriptionreader.h b/src/libs/qmljs/qmljstypedescriptionreader.h
index f8e5366e9d2..6292d5f2800 100644
--- a/src/libs/qmljs/qmljstypedescriptionreader.h
+++ b/src/libs/qmljs/qmljstypedescriptionreader.h
@@ -34,6 +34,8 @@
#define QMLJSTYPEDESCRIPTIONREADER_H
#include <languageutils/fakemetaobject.h>
+#include <languageutils/componentversion.h>
+#include "qmljsdocument.h"
// for Q_DECLARE_TR_FUNCTIONS
#include <QtCore/QCoreApplication>
@@ -60,7 +62,9 @@ public:
explicit TypeDescriptionReader(const QString &data);
~TypeDescriptionReader();
- bool operator()(QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects);
+ bool operator()(
+ QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *objects,
+ QList<ModuleApiInfo> *moduleApis);
QString errorMessage() const;
QString warningMessage() const;
@@ -68,6 +72,7 @@ private:
void readDocument(AST::UiProgram *ast);
void readModule(AST::UiObjectDefinition *ast);
void readComponent(AST::UiObjectDefinition *ast);
+ void readModuleApi(AST::UiObjectDefinition *ast);
void readSignalOrMethod(AST::UiObjectDefinition *ast, bool isMethod, LanguageUtils::FakeMetaObject::Ptr fmo);
void readProperty(AST::UiObjectDefinition *ast, LanguageUtils::FakeMetaObject::Ptr fmo);
void readEnum(AST::UiObjectDefinition *ast, LanguageUtils::FakeMetaObject::Ptr fmo);
@@ -76,6 +81,7 @@ private:
QString readStringBinding(AST::UiScriptBinding *ast);
bool readBoolBinding(AST::UiScriptBinding *ast);
double readNumericBinding(AST::UiScriptBinding *ast);
+ LanguageUtils::ComponentVersion readNumericVersionBinding(AST::UiScriptBinding *ast);
int readIntBinding(AST::UiScriptBinding *ast);
void readExports(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaObject::Ptr fmo);
void readMetaObjectRevisions(AST::UiScriptBinding *ast, LanguageUtils::FakeMetaObject::Ptr fmo);
@@ -88,6 +94,7 @@ private:
QString _errorMessage;
QString _warningMessage;
QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> *_objects;
+ QList<ModuleApiInfo> *_moduleApis;
};
} // namespace QmlJS