aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-11-24 14:14:46 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-11-25 12:51:34 +0100
commit140a34afdd9ecbb7bc5f9db3f68dcd43a6c534e3 (patch)
treeb235dbaabac9e900992c76baf6b7f919b9a7195a /src/qmlcompiler
parent927dd69db9bbffcc423b735a7f89e950e052892a (diff)
QmlCompiler: Unify parsing of QML components, JS programs, ES modules
There is no reason to duplicate the code for retrieving method signatures 3 times over. As an added benefit, the types on those methods are resolved now. Change-Id: I2f9681911b938c4a260b6593ab49e9cc5098c546 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmlcompiler')
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp95
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor_p.h12
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h5
-rw-r--r--src/qmlcompiler/qqmljstypereader.cpp58
4 files changed, 96 insertions, 74 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 0e16b02846..c4f99f48b2 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -67,7 +67,7 @@ void QQmlJSImportVisitor::leaveEnvironment()
void QQmlJSImportVisitor::resolveAliases()
{
QQueue<QQmlJSScope::Ptr> objects;
- objects.enqueue(m_qmlRootScope);
+ objects.enqueue(m_exportedRootScope);
while (!objects.isEmpty()) {
const QQmlJSScope::Ptr object = objects.dequeue();
@@ -90,19 +90,24 @@ void QQmlJSImportVisitor::resolveAliases()
QQmlJSScope::Ptr QQmlJSImportVisitor::result() const
{
- return m_qmlRootScope;
+ return m_exportedRootScope;
}
-bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiProgram *)
+void QQmlJSImportVisitor::importBaseModules()
{
+ Q_ASSERT(m_rootScopeImports.isEmpty());
m_rootScopeImports = m_importer->importBuiltins();
if (!m_qmltypesFiles.isEmpty())
m_rootScopeImports.insert(m_importer->importQmltypes(m_qmltypesFiles));
m_rootScopeImports.insert(m_importer->importDirectory(m_implicitImportDirectory));
-
m_errors.append(m_importer->takeWarnings());
+}
+
+bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiProgram *)
+{
+ importBaseModules();
return true;
}
@@ -120,8 +125,8 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition)
superType.append(segment->name.toString());
}
enterEnvironment(QQmlJSScope::QMLScope, superType, definition->firstSourceLocation());
- if (!m_qmlRootScope)
- m_qmlRootScope = m_currentScope;
+ if (!m_exportedRootScope)
+ m_exportedRootScope = m_currentScope;
m_currentScope->resolveTypes(m_rootScopeImports);
return true;
@@ -178,22 +183,22 @@ void QQmlJSImportVisitor::visitFunctionExpressionHelper(QQmlJS::AST::FunctionExp
using namespace QQmlJS::AST;
auto name = fexpr->name.toString();
if (!name.isEmpty()) {
- if (m_currentScope->scopeType() == QQmlJSScope::QMLScope) {
- QQmlJSMetaMethod method(name);
- method.setMethodType(QQmlJSMetaMethod::Method);
- if (const auto *formals = fexpr->formals) {
- const auto parameters = formals->formals();
- for (const auto &parameter : parameters) {
- const QString type = parameter.typeName();
- method.addParameter(parameter.id,
- type.isEmpty() ? QStringLiteral("var") : type);
- }
+ QQmlJSMetaMethod method(name);
+ method.setMethodType(QQmlJSMetaMethod::Method);
+ if (const auto *formals = fexpr->formals) {
+ const auto parameters = formals->formals();
+ for (const auto &parameter : parameters) {
+ const QString type = parameter.typeName();
+ method.addParameter(parameter.id,
+ type.isEmpty() ? QStringLiteral("var") : type);
}
- method.setReturnTypeName(fexpr->typeAnnotation
- ? fexpr->typeAnnotation->type->toString()
- : QStringLiteral("var"));
- m_currentScope->addOwnMethod(method);
- } else {
+ }
+ method.setReturnTypeName(fexpr->typeAnnotation
+ ? fexpr->typeAnnotation->type->toString()
+ : QStringLiteral("var"));
+ m_currentScope->addOwnMethod(method);
+
+ if (m_currentScope->scopeType() != QQmlJSScope::QMLScope) {
m_currentScope->insertJSIdentifier(
name, {
QQmlJSScope::JavaScriptIdentifier::LexicalScoped,
@@ -504,4 +509,52 @@ void QQmlJSImportVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob)
m_currentScope->addOwnProperty(property);
}
+bool QQmlJSImportVisitor::visit(ExportDeclaration *)
+{
+ Q_ASSERT(!m_exportedRootScope.isNull());
+ Q_ASSERT(m_exportedRootScope != m_globalScope);
+ Q_ASSERT(m_currentScope == m_globalScope);
+ m_currentScope = m_exportedRootScope;
+ return true;
+}
+
+void QQmlJSImportVisitor::endVisit(ExportDeclaration *)
+{
+ Q_ASSERT(!m_exportedRootScope.isNull());
+ m_currentScope = m_exportedRootScope->parentScope();
+ Q_ASSERT(m_currentScope == m_globalScope);
+}
+
+bool QQmlJSImportVisitor::visit(ESModule *module)
+{
+ enterEnvironment(QQmlJSScope::JSLexicalScope, QStringLiteral("module"),
+ module->firstSourceLocation());
+ Q_ASSERT(m_exportedRootScope.isNull());
+ m_exportedRootScope = m_currentScope;
+ m_exportedRootScope->setIsScript(true);
+ importBaseModules();
+ leaveEnvironment();
+ return true;
+}
+
+void QQmlJSImportVisitor::endVisit(ESModule *)
+{
+ m_exportedRootScope->resolveTypes(m_rootScopeImports);
+}
+
+bool QQmlJSImportVisitor::visit(Program *)
+{
+ Q_ASSERT(m_globalScope == m_currentScope);
+ Q_ASSERT(m_exportedRootScope.isNull());
+ m_exportedRootScope = m_currentScope;
+ m_exportedRootScope->setIsScript(true);
+ importBaseModules();
+ return true;
+}
+
+void QQmlJSImportVisitor::endVisit(Program *)
+{
+ m_exportedRootScope->resolveTypes(m_rootScopeImports);
+}
+
QT_END_NAMESPACE
diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h
index dfb4b13c41..14fe2236e1 100644
--- a/src/qmlcompiler/qqmljsimportvisitor_p.h
+++ b/src/qmlcompiler/qqmljsimportvisitor_p.h
@@ -95,12 +95,21 @@ protected:
bool visit(QQmlJS::AST::UiObjectBinding *uiob) override;
void endVisit(QQmlJS::AST::UiObjectBinding *uiob) override;
+ bool visit(QQmlJS::AST::ExportDeclaration *exp) override;
+ void endVisit(QQmlJS::AST::ExportDeclaration *exp) override;
+
+ bool visit(QQmlJS::AST::ESModule *module) override;
+ void endVisit(QQmlJS::AST::ESModule *module) override;
+
+ bool visit(QQmlJS::AST::Program *program) override;
+ void endVisit(QQmlJS::AST::Program *program) override;
+
void throwRecursionDepthError() override;
QString m_implicitImportDirectory;
QStringList m_qmltypesFiles;
QQmlJSScope::Ptr m_currentScope;
- QQmlJSScope::Ptr m_qmlRootScope;
+ QQmlJSScope::Ptr m_exportedRootScope;
QQmlJSScope::ConstPtr m_globalScope;
QHash<QString, QQmlJSScope::ConstPtr> m_scopesById;
QHash<QString, QQmlJSScope::ConstPtr> m_rootScopeImports;
@@ -113,6 +122,7 @@ protected:
void leaveEnvironment();
private:
+ void importBaseModules();
void resolveAliases();
void visitFunctionExpressionHelper(QQmlJS::AST::FunctionExpression *fexpr);
};
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index 0801e6eb7e..711d24c7aa 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -108,7 +108,8 @@ public:
enum Flag {
Creatable = 0x1,
Composite = 0x2,
- Singleton = 0x4
+ Singleton = 0x4,
+ Script = 0x8,
};
Q_DECLARE_FLAGS(Flags, Flag)
Q_FLAGS(Flags);
@@ -216,9 +217,11 @@ public:
bool isSingleton() const { return m_flags & Singleton; }
bool isCreatable() const { return m_flags & Creatable; }
bool isComposite() const { return m_flags & Composite; }
+ bool isScript() const { return m_flags & Script; }
void setIsSingleton(bool v) { m_flags = v ? (m_flags | Singleton) : (m_flags & ~Singleton); }
void setIsCreatable(bool v) { m_flags = v ? (m_flags | Creatable) : (m_flags & ~Creatable); }
void setIsComposite(bool v) { m_flags = v ? (m_flags | Composite) : (m_flags & ~Composite); }
+ void setIsScript(bool v) { m_flags = v ? (m_flags | Script) : (m_flags & ~Script); }
void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; }
AccessSemantics accessSemantics() const { return m_semantics; }
diff --git a/src/qmlcompiler/qqmljstypereader.cpp b/src/qmlcompiler/qqmljstypereader.cpp
index 789166a301..25636dbe32 100644
--- a/src/qmlcompiler/qqmljstypereader.cpp
+++ b/src/qmlcompiler/qqmljstypereader.cpp
@@ -40,43 +40,6 @@
QT_BEGIN_NAMESPACE
-static QQmlJSScope::Ptr parseModule(QQmlJS::AST::ESModule *module, const QString &name)
-{
- using namespace QQmlJS::AST;
- QQmlJSScope::Ptr result = QQmlJSScope::create(QQmlJSScope::JSLexicalScope);
- result->setInternalName(name);
- for (auto *statement = module->body; statement; statement = statement->next) {
- if (auto *exp = cast<ExportDeclaration *>(statement->statement)) {
- // TODO: There are a number of other things we could find here
- if (auto *function = cast<FunctionDeclaration *>(exp->variableStatementOrDeclaration)) {
- QQmlJSMetaMethod method(function->name.toString());
- method.setMethodType(QQmlJSMetaMethod::Method);
- for (auto *argument = function->formals; argument; argument = argument->next)
- method.addParameter(argument->element->bindingIdentifier.toString(), QString());
- result->addOwnMethod(method);
- }
- }
- }
- return result;
-}
-
-static QQmlJSScope::Ptr parseProgram(QQmlJS::AST::Program *program, const QString &name)
-{
- using namespace QQmlJS::AST;
- QQmlJSScope::Ptr result = QQmlJSScope::create(QQmlJSScope::JSLexicalScope);
- result->setInternalName(name);
- for (auto *statement = program->statements; statement; statement = statement->next) {
- if (auto *function = cast<FunctionDeclaration *>(statement->statement)) {
- QQmlJSMetaMethod method(function->name.toString());
- method.setMethodType(QQmlJSMetaMethod::Method);
- for (auto *parameters = function->formals; parameters; parameters = parameters->next)
- method.addParameter(parameters->element->bindingIdentifier.toString(), QString());
- result->addOwnMethod(method);
- }
- }
- return result;
-}
-
QQmlJSScope::Ptr QQmlJSTypeReader::operator()()
{
using namespace QQmlJS::AST;
@@ -116,20 +79,13 @@ QQmlJSScope::Ptr QQmlJSTypeReader::operator()()
return result;
}
- if (!isJavaScript) {
- QQmlJS::AST::UiProgram *program = parser.ast();
- QQmlJSImportVisitor membersVisitor(m_importer, QFileInfo(m_file).canonicalPath(),
- m_qmltypesFiles);
- program->accept(&membersVisitor);
- m_errors = membersVisitor.errors();
- return membersVisitor.result();
- }
-
-
- if (isESModule)
- return parseModule(cast<ESModule *>(parser.rootNode()), scopeName);
- else
- return parseProgram(cast<Program *>(parser.rootNode()), scopeName);
+ QQmlJS::AST::Node *rootNode = parser.rootNode();
+ QQmlJSImportVisitor membersVisitor(m_importer, QFileInfo(m_file).canonicalPath(),
+ m_qmltypesFiles);
+ rootNode->accept(&membersVisitor);
+ auto result = membersVisitor.result();
+ result->setInternalName(scopeName);
+ return result;
}
QT_END_NAMESPACE