diff options
Diffstat (limited to 'src/qmlcompiler/qqmljsimportvisitor.cpp')
| -rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 167 |
1 files changed, 93 insertions, 74 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index edc65fc6fe..cb5abd5d7e 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -131,8 +131,10 @@ QQmlJSImportVisitor::QQmlJSImportVisitor( m_importer(importer), m_logger(logger), m_rootScopeImports( - QQmlJSImporter::ImportedTypes::QML, {}, - importer->builtinInternalNames().arrayType()) + QQmlJS::ContextualTypes( + QQmlJS::ContextualTypes::QML, {}, + importer->builtinInternalNames().contextualTypes().arrayType()), + {}) { m_currentScope->setScopeType(QQmlSA::ScopeType::JSFunctionScope); Q_ASSERT(logger); // must be valid @@ -340,7 +342,8 @@ void QQmlJSImportVisitor::resolveAliasesAndIds() const QQmlJSScope::ConstPtr deferred = m_scopesById.scope(name, childScope); if (!deferred.isNull()) { QQmlJSScope::resolveGeneralizedGroup( - childScope, deferred, m_rootScopeImports, &m_usedTypes); + childScope, deferred, m_rootScopeImports.contextualTypes(), + &m_usedTypes); } } } @@ -387,9 +390,9 @@ QString QQmlJSImportVisitor::implicitImportDirectory( } void QQmlJSImportVisitor::processImportWarnings( - const QString &what, const QQmlJS::SourceLocation &srcLocation) + const QString &what, const QList<QQmlJS::DiagnosticMessage> &warnings, + const QQmlJS::SourceLocation &srcLocation) { - const auto warnings = m_importer->takeWarnings(); if (warnings.isEmpty()) return; @@ -400,24 +403,21 @@ void QQmlJSImportVisitor::processImportWarnings( void QQmlJSImportVisitor::importBaseModules() { - Q_ASSERT(m_rootScopeImports.types().isEmpty()); + Q_ASSERT(m_rootScopeImports.isEmpty()); m_rootScopeImports = m_importer->importBuiltins(); const QQmlJS::SourceLocation invalidLoc; - for (auto it = m_rootScopeImports.types().keyBegin(), end = m_rootScopeImports.types().keyEnd(); - it != end; it++) { + const auto types = m_rootScopeImports.types(); + for (auto it = types.keyBegin(), end = types.keyEnd(); it != end; it++) addImportWithLocation(*it, invalidLoc); - } if (!m_qmldirFiles.isEmpty()) - m_importer->importQmldirs(m_qmldirFiles); + m_rootScopeImports.addWarnings(m_importer->importQmldirs(m_qmldirFiles)); // Pulling in the modules and neighboring qml files of the qmltypes we're trying to lint is not // something we need to do. if (!m_logger->fileName().endsWith(u".qmltypes"_s)) { - QQmlJS::ContextualTypes fromDirectory = - m_importer->importDirectory(m_implicitImportDirectory); - m_rootScopeImports.addTypes(std::move(fromDirectory)); + m_rootScopeImports.add(m_importer->importDirectory(m_implicitImportDirectory)); // Import all possible resource directories the file may belong to. // This is somewhat fuzzy, but if you're mapping the same file to multiple resource @@ -429,12 +429,12 @@ void QQmlJSImportVisitor::importBaseModules() const qsizetype lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash == -1) continue; - m_rootScopeImports.addTypes(m_importer->importDirectory(path.first(lastSlash))); + m_rootScopeImports.add(m_importer->importDirectory(path.first(lastSlash))); } } } - processImportWarnings(QStringLiteral("base modules")); + processImportWarnings(QStringLiteral("base modules"), m_rootScopeImports.warnings()); } bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiProgram *) @@ -659,8 +659,8 @@ void QQmlJSImportVisitor::processPropertyTypes() auto property = type.scope->ownProperty(type.name); - if (const auto propertyType = - QQmlJSScope::findType(property.typeName(), m_rootScopeImports).scope) { + if (const auto propertyType = QQmlJSScope::findType( + property.typeName(), m_rootScopeImports.contextualTypes()).scope) { property.setType(propertyType); type.scope->addOwnProperty(property); } else { @@ -676,8 +676,8 @@ void QQmlJSImportVisitor::processMethodTypes() for (auto [it, end] = method.scope->mutableOwnMethodsRange(method.methodName); it != end; ++it) { const auto [parameterBegin, parameterEnd] = it->mutableParametersRange(); for (auto parameter = parameterBegin; parameter != parameterEnd; ++parameter) { - if (const auto parameterType = - QQmlJSScope::findType(parameter->typeName(), m_rootScopeImports) .scope) { + if (const auto parameterType = QQmlJSScope::findType( + parameter->typeName(), m_rootScopeImports.contextualTypes()).scope) { parameter->setType({ parameterType }); } else { m_logger->log( @@ -687,8 +687,8 @@ void QQmlJSImportVisitor::processMethodTypes() } } - if (const auto returnType = - QQmlJSScope::findType(it->returnTypeName(), m_rootScopeImports).scope) { + if (const auto returnType = QQmlJSScope::findType( + it->returnTypeName(), m_rootScopeImports.contextualTypes()).scope) { it->setReturnType({ returnType }); } else { m_logger->log(u"\"%1\" was not found for the return type of method \"%2\"."_s.arg( @@ -1488,7 +1488,7 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition) } const QTypeRevision revision = QQmlJSScope::resolveTypes( - m_currentScope, m_rootScopeImports, &m_usedTypes); + m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); if (auto base = m_currentScope->baseType(); base) { if (isRoot && base->internalName() == u"QQmlComponent") { m_logger->log(u"Qml top level type cannot be 'Component'."_s, qmlTopLevelComponent, @@ -1527,7 +1527,8 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition) definition->firstSourceLocation()); m_bindings.append(createNonUniqueScopeBinding(m_currentScope, superType, definition->firstSourceLocation())); - QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes( + m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); } m_currentScope->setAnnotations(parseAnnotations(definition->annotations)); @@ -1537,7 +1538,7 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition) void QQmlJSImportVisitor::endVisit(UiObjectDefinition *) { - QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); leaveEnvironment(); } @@ -2271,14 +2272,14 @@ void QQmlJSImportVisitor::addImportWithLocation(const QString &name, m_importLocations.insert(loc); } -void QQmlJSImportVisitor::importFromHost(const QString &path, const QString &prefix, - const QQmlJS::SourceLocation &location) +QList<QQmlJS::DiagnosticMessage> QQmlJSImportVisitor::importFromHost( + const QString &path, const QString &prefix, const QQmlJS::SourceLocation &location) { QFileInfo fileInfo(path); if (!fileInfo.exists()) { m_logger->log("File or directory you are trying to import does not exist: %1."_L1.arg(path), qmlImport, location); - return; + return {}; } if (fileInfo.isFile()) { @@ -2286,40 +2287,53 @@ void QQmlJSImportVisitor::importFromHost(const QString &path, const QString &pre const QString actualPrefix = prefix.isEmpty() ? scope->internalName() : prefix; m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); addImportWithLocation(actualPrefix, location); - } else if (fileInfo.isDir()) { - const auto scopes = m_importer->importDirectory(path, prefix); - m_rootScopeImports.addTypes(scopes); - for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; it++) + return {}; + } + + if (fileInfo.isDir()) { + auto scopes = m_importer->importDirectory(path, prefix); + const auto types = scopes.types(); + const auto warnings = scopes.warnings(); + m_rootScopeImports.add(std::move(scopes)); + for (auto it = types.keyBegin(), end = types.keyEnd(); it != end; it++) addImportWithLocation(*it, location); - } else { - m_logger->log( - "%1 is neither a file nor a directory. Are sure the import path is correct?"_L1.arg( - path), - qmlImport, location); + return warnings; } + + m_logger->log( + "%1 is neither a file nor a directory. Are sure the import path is correct?"_L1.arg( + path), + qmlImport, location); + return {}; } -void QQmlJSImportVisitor::importFromQrc(const QString &path, const QString &prefix, - const QQmlJS::SourceLocation &location) +QList<QQmlJS::DiagnosticMessage> QQmlJSImportVisitor::importFromQrc( + const QString &path, const QString &prefix, const QQmlJS::SourceLocation &location) { Q_ASSERT(path.startsWith(u':')); - if (const QQmlJSResourceFileMapper *mapper = m_importer->resourceFileMapper()) { - const auto pathNoColon = QStringView(path).mid(1); - if (mapper->isFile(pathNoColon)) { - const auto entry = m_importer->resourceFileMapper()->entry( - QQmlJSResourceFileMapper::resourceFileFilter(pathNoColon.toString())); - const auto scope = m_importer->importFile(entry.filePath); - const QString actualPrefix = - prefix.isEmpty() ? QFileInfo(entry.resourcePath).baseName() : prefix; - m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); - addImportWithLocation(actualPrefix, location); - } else { - const auto scopes = m_importer->importDirectory(path, prefix); - m_rootScopeImports.addTypes(scopes); - for (auto it = scopes.types().keyBegin(), end = scopes.types().keyEnd(); it != end; it++) - addImportWithLocation(*it, location); - } + const QQmlJSResourceFileMapper *mapper = m_importer->resourceFileMapper(); + if (!mapper) + return {}; + + const auto pathNoColon = QStringView(path).mid(1); + if (mapper->isFile(pathNoColon)) { + const auto entry = m_importer->resourceFileMapper()->entry( + QQmlJSResourceFileMapper::resourceFileFilter(pathNoColon.toString())); + const auto scope = m_importer->importFile(entry.filePath); + const QString actualPrefix = + prefix.isEmpty() ? QFileInfo(entry.resourcePath).baseName() : prefix; + m_rootScopeImports.setType(actualPrefix, { scope, QTypeRevision() }); + addImportWithLocation(actualPrefix, location); + return {}; } + + auto scopes = m_importer->importDirectory(path, prefix); + const auto types = scopes.types(); + const auto warnings = scopes.warnings(); + m_rootScopeImports.add(std::move(scopes)); + for (auto it = types.keyBegin(), end = types.keyEnd(); it != end; it++) + addImportWithLocation(*it, location); + return warnings; } bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) @@ -2346,20 +2360,18 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) QString absolute = fileInfo.isRelative() ? QDir::cleanPath(QDir(m_implicitImportDirectory).filePath(filename)) : filename; - if (absolute.startsWith(u':')) { - importFromQrc(absolute, prefix, importLocation); - } else { - importFromHost(absolute, prefix, importLocation); - } - processImportWarnings("path \"%1\""_L1.arg(url.path()), importLocation); + auto warnings = absolute.startsWith(u':') + ? importFromQrc(absolute, prefix, importLocation) + : importFromHost(absolute, prefix, importLocation); + processImportWarnings("path \"%1\""_L1.arg(url.path()), warnings, importLocation); return true; } else if (scheme == "file"_L1) { - importFromHost(url.path(), prefix, importLocation); - processImportWarnings("URL \"%1\""_L1.arg(url.path()), importLocation); + auto warnings = importFromHost(url.path(), prefix, importLocation); + processImportWarnings("URL \"%1\""_L1.arg(url.path()), warnings, importLocation); return true; } else if (scheme == "qrc"_L1) { - importFromQrc(":"_L1 + url.path(), prefix, importLocation); - processImportWarnings("URL \"%1\""_L1.arg(url.path()), importLocation); + auto warnings = importFromQrc(":"_L1 + url.path(), prefix, importLocation); + processImportWarnings("URL \"%1\""_L1.arg(url.path()), warnings, importLocation); return true; } else { m_logger->log("Unknown import syntax. Imports can be paths, qrc urls or file urls"_L1, @@ -2371,11 +2383,13 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) QStringList staticModulesProvided; - const auto imported = m_importer->importModule( + auto imported = m_importer->importModule( path, prefix, import->version ? import->version->version : QTypeRevision(), &staticModulesProvided); - m_rootScopeImports.addTypes(imported); - for (auto it = imported.types().keyBegin(), end = imported.types().keyEnd(); it != end; it++) + const auto types = imported.types(); + const auto warnings = imported.warnings(); + m_rootScopeImports.add(std::move(imported)); + for (auto it = types.keyBegin(), end = types.keyEnd(); it != end; it++) addImportWithLocation(*it, import->firstSourceLocation()); if (prefix.isEmpty()) { @@ -2388,7 +2402,8 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) } } - processImportWarnings(QStringLiteral("module \"%1\"").arg(path), import->firstSourceLocation()); + processImportWarnings( + QStringLiteral("module \"%1\"").arg(path), warnings, import->firstSourceLocation()); return true; } @@ -2650,12 +2665,14 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) } // recursively resolve types for current scope if new scopes are found - if (needsResolution) - QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); + if (needsResolution) { + QQmlJSScope::resolveTypes( + m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); + } enterEnvironment(QQmlSA::ScopeType::QMLScope, typeName, uiob->qualifiedTypeNameId->identifierToken); - QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); m_qmlTypes.append(m_currentScope); // new QMLScope is created here, so add it m_objectBindingScopes << m_currentScope; @@ -2664,7 +2681,7 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) void QQmlJSImportVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob) { - QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); // must be mutable, as we might mark it as implicitly wrapped in a component const QQmlJSScope::Ptr childScope = m_currentScope; leaveEnvironment(); @@ -2779,7 +2796,8 @@ bool QQmlJSImportVisitor::visit(ESModule *module) void QQmlJSImportVisitor::endVisit(ESModule *) { - QQmlJSScope::resolveTypes(m_exportedRootScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes( + m_exportedRootScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); } bool QQmlJSImportVisitor::visit(Program *) @@ -2795,7 +2813,8 @@ bool QQmlJSImportVisitor::visit(Program *) void QQmlJSImportVisitor::endVisit(Program *) { - QQmlJSScope::resolveTypes(m_exportedRootScope, m_rootScopeImports, &m_usedTypes); + QQmlJSScope::resolveTypes( + m_exportedRootScope, m_rootScopeImports.contextualTypes(), &m_usedTypes); } void QQmlJSImportVisitor::endVisit(QQmlJS::AST::FieldMemberExpression *fieldMember) |
