aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Piira <apiira@blackberry.com>2013-09-24 12:49:10 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-21 21:43:32 +0200
commit9de3630a513aa598855f7d40461c5aec9ecce319 (patch)
tree69eb5b78efbfe6cba7b7266a9adbe0e2bce77336
parentde31a57672ec461c2081f65e3631134ee45de887 (diff)
Add support CompositeSingleton to the new V4 compiler.v5.2.0-beta1
Implements QQmlCodeGenerator::visit(AST::UiPragma *) to process any pragma statements in a QML file for the new V4 compiler approach. Only pragma Singleton is supported, others will generate errors. Also adds necessary hooks to treat types as Singletons. Basic functionality is working, but three of the QML Singleton unit tests fail. Some of them are dependent on other language capabilities that seem to have problems. In addition removes unnecessary toString() call in the equivalent visit(AST::UiPragma *) function of the old parser. Change-Id: Iec9fa887f953b80b7f9a11878d846637a8f519ef Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp48
-rw-r--r--src/qml/compiler/qqmlcodegenerator_p.h12
-rw-r--r--src/qml/compiler/qv4compileddata_p.h8
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp5
-rw-r--r--src/qml/qml/qqmlscript.cpp2
-rw-r--r--src/qml/qml/qqmltypeloader.cpp25
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
7 files changed, 95 insertions, 6 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index ed5f4c3772..2aa5aa5a3c 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -118,6 +118,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
output->program = program;
qSwap(_imports, output->imports);
+ qSwap(_pragmas, output->pragmas);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
qSwap(_typeReferences, output->typeReferences);
@@ -147,6 +148,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
collectTypeReferences();
qSwap(_imports, output->imports);
+ qSwap(_pragmas, output->pragmas);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
qSwap(_typeReferences, output->typeReferences);
@@ -403,6 +405,11 @@ bool QQmlCodeGenerator::visit(AST::UiImport *node)
error.setColumn(node->importIdToken.startColumn);
errors << error;
return false;
+ } else {
+ // For backward compatibility in how the imports are loaded we
+ // must otherwise initialize the major and minor version to -1.
+ import->majorVersion = -1;
+ import->minorVersion = -1;
}
import->location.line = node->importToken.startLine;
@@ -415,9 +422,38 @@ bool QQmlCodeGenerator::visit(AST::UiImport *node)
return false;
}
-bool QQmlCodeGenerator::visit(AST::UiPragma *ast)
+bool QQmlCodeGenerator::visit(AST::UiPragma *node)
{
- return true;
+ Pragma *pragma = New<Pragma>();
+
+ // For now the only valid pragma is Singleton, so lets validate the input
+ if (!node->pragmaType->name.isNull())
+ {
+ if (QLatin1String("Singleton") == node->pragmaType->name)
+ {
+ pragma->type = Pragma::PragmaSingleton;
+ } else {
+ QQmlError error;
+ error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
+ error.setLine(node->pragmaToken.startLine);
+ error.setColumn(node->pragmaToken.startColumn);
+ errors << error;
+ return false;
+ }
+ } else {
+ QQmlError error;
+ error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
+ error.setLine(node->pragmaToken.startLine);
+ error.setColumn(node->pragmaToken.startColumn);
+ errors << error;
+ return false;
+ }
+
+ pragma->location.line = node->pragmaToken.startLine;
+ pragma->location.column = node->pragmaToken.startColumn;
+ _pragmas.append(pragma);
+
+ return false;
}
static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
@@ -1146,6 +1182,14 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
objectPtr += signalTableSize;
}
+ // enable flag if we encountered pragma Singleton
+ foreach (Pragma *p, output.pragmas) {
+ if (p->type == Pragma::PragmaSingleton) {
+ qmlUnit->header.flags |= QV4::CompiledData::Unit::IsSingleton;
+ break;
+ }
+ }
+
return qmlUnit;
}
diff --git a/src/qml/compiler/qqmlcodegenerator_p.h b/src/qml/compiler/qqmlcodegenerator_p.h
index b6749516d3..8de08a81d1 100644
--- a/src/qml/compiler/qqmlcodegenerator_p.h
+++ b/src/qml/compiler/qqmlcodegenerator_p.h
@@ -154,6 +154,16 @@ struct QmlObject
void dump(DebugStream &out);
};
+struct Pragma
+{
+ enum PragmaType {
+ PragmaSingleton = 0x1
+ };
+ quint32 type;
+
+ QV4::CompiledData::Location location;
+};
+
struct ParsedQML
{
ParsedQML()
@@ -163,6 +173,7 @@ struct ParsedQML
QQmlJS::Engine jsParserEngine;
V4IR::Module jsModule;
QList<QV4::CompiledData::Import*> imports;
+ QList<Pragma*> pragmas;
AST::UiProgram *program;
int indexOfRootObject;
QList<QmlObject*> objects;
@@ -253,6 +264,7 @@ public:
QList<QQmlError> errors;
QList<QV4::CompiledData::Import*> _imports;
+ QList<Pragma*> _pragmas;
QList<QmlObject*> _objects;
QList<AST::Node*> _functions;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index bf6794e182..2c0a46f3c5 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -148,7 +148,8 @@ struct Unit
enum {
IsJavascript = 0x1,
IsQml = 0x2,
- StaticData = 0x4 // Unit data persistent in memory?
+ StaticData = 0x4, // Unit data persistent in memory?
+ IsSingleton = 0x8
};
quint32 flags;
uint stringTableSize;
@@ -414,7 +415,6 @@ struct Import
Location location;
};
-
struct QmlUnit
{
Unit header;
@@ -433,6 +433,10 @@ struct QmlUnit
const uint offset = offsetTable[idx];
return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
}
+
+ bool isSingleton() const {
+ return header.flags & Unit::IsSingleton;
+ }
};
// This is how this hooks into the existing structures:
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 4e70e14894..56776dcb82 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1239,6 +1239,11 @@ QObject *QmlObjectCreator::createInstance(int index, QObject *parent)
}
} else {
Q_ASSERT(typeRef.component);
+ if (typeRef.component->qmlUnit->isSingleton())
+ {
+ recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
+ return 0;
+ }
QmlObjectCreator subCreator(context, typeRef.component);
instance = subCreator.create();
if (!instance) {
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index cc01307e54..9fd06aa934 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -895,7 +895,7 @@ bool ProcessAST::visit(AST::UiPragma *node)
// For now the only valid pragma is Singleton, so lets validate the input
if (!node->pragmaType->name.isNull())
{
- if (QLatin1String("Singleton") == node->pragmaType->name.toString())
+ if (QLatin1String("Singleton") == node->pragmaType->name)
{
pragma.type = QQmlScript::Pragma::Singleton;
} else {
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 932faf4b88..601c1b8bdc 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2218,7 +2218,24 @@ void QQmlTypeData::dataReceived(const Data &data)
}
}
- foreach (const QQmlScript::Pragma &pragma, scriptParser.pragmas()) {
+ // ### convert to use new data structure once old compiler is gone.
+ if (m_useNewCompiler && m_newPragmas.isEmpty()) {
+ m_newPragmas.reserve(parsedQML->pragmas.size());
+ foreach (QtQml::Pragma *p, parsedQML->pragmas) {
+ QQmlScript::Pragma pragma;
+ pragma.location.start.line = p->location.line;
+ pragma.location.start.column = p->location.column;
+
+ switch (p->type) {
+ case QtQml::Pragma::PragmaSingleton: pragma.type = QQmlScript::Pragma::Singleton; break;
+ default: break;
+ }
+
+ m_newPragmas << pragma;
+ }
+ }
+
+ foreach (const QQmlScript::Pragma &pragma, m_useNewCompiler ? m_newPragmas : scriptParser.pragmas()) {
if (!addPragma(pragma, &errors)) {
Q_ASSERT(errors.size());
setError(errors);
@@ -2280,6 +2297,12 @@ void QQmlTypeData::compile()
foreach (const QString &ns, m_namespaces)
m_compiledData->importCache->add(ns);
+ // Add any Composite Singletons that were used to the import cache
+ for (int i = 0; i < compositeSingletons().count(); ++i) {
+ m_compiledData->importCache->add(compositeSingletons().at(i).type->qmlTypeName(),
+ compositeSingletons().at(i).type->sourceUrl(), compositeSingletons().at(i).prefix);
+ }
+
m_imports.populateCache(m_compiledData->importCache);
m_compiledData->importCache->addref();
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b9bf056cb3..b93cf2942d 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -460,6 +460,7 @@ private:
// --- new compiler
QScopedPointer<QtQml::ParsedQML> parsedQML;
QList<QQmlScript::Import> m_newImports;
+ QList<QQmlScript::Pragma> m_newPragmas;
// ---
QList<ScriptReference> m_scripts;