diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-01-16 17:04:23 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-01-17 14:13:48 +0100 |
| commit | c159f4e837d99c8cb4b260e7bbc390cdb83d5e19 (patch) | |
| tree | 0fcdb73fa180b2a0d98b46d9e8bfbd4a4717e57b /src/qmlcompiler/qqmljsimportvisitor.cpp | |
| parent | 0208321b8a571b9156a922305c200336a5b82a88 (diff) | |
QmlCompiler: Reduce duplication of "not found" messages
Track the unresolved types in a central place and only warn once for
each of them. Make sure that we still mark them as wrapped in implicit
components even if we don't warn, though.
Realize that custom parser parents potentially obfuscate any types
defined inside their scope, not only the ones we look for when
setting bindings.
Pick-to: 6.9 6.8
Task-number: QTBUG-124913
Change-Id: I30d911dc92d1e4359db66671bf62393f2f852b6c
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'src/qmlcompiler/qqmljsimportvisitor.cpp')
| -rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 78 |
1 files changed, 36 insertions, 42 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index bb2c3b7750..62c08d2bfb 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -215,14 +215,11 @@ void QQmlJSImportVisitor::leaveEnvironment() m_currentScope = m_currentScope->parentScope(); } -bool QQmlJSImportVisitor::isTypeResolved(const QQmlJSScope::ConstPtr &type) +void QQmlJSImportVisitor::warnUnresolvedType(const QQmlJSScope::ConstPtr &type) const { - const auto handleUnresolvedType = [this](const QQmlJSScope::ConstPtr &type) { - m_logger->log(QStringLiteral("Type %1 is used but it is not resolved") - .arg(getScopeName(type, type->scopeType())), - qmlUnresolvedType, type->sourceLocation()); - }; - return isTypeResolved(type, handleUnresolvedType); + m_logger->log(QStringLiteral("Type %1 is used but it is not resolved") + .arg(getScopeName(type, type->scopeType())), + qmlUnresolvedType, type->sourceLocation()); } static bool mayBeUnresolvedGroupedProperty(const QQmlJSScope::ConstPtr &scope) @@ -548,18 +545,12 @@ QVector<QQmlJSAnnotation> QQmlJSImportVisitor::parseAnnotations(QQmlJS::AST::UiA void QQmlJSImportVisitor::setAllBindings() { - QDuplicateTracker<QQmlJSScope::ConstPtr> seenBadOwners; for (auto it = m_bindings.cbegin(); it != m_bindings.cend(); ++it) { - // ensure the scope is resolved, if not - it is an error - auto type = it->owner; - if (!type->isFullyResolved() && !type->isInCustomParserParent()) { // special otherwise - if (!seenBadOwners.hasSeen(type)) { - m_logger->log(QStringLiteral("'%1' is used but it is not resolved") - .arg(getScopeName(type, type->scopeType())), - qmlUnresolvedType, type->sourceLocation()); - } + // ensure the scope is resolved. If not, produce a warning. + const QQmlJSScope::Ptr type = it->owner; + if (!checkTypeResolved(type)) continue; - } + auto binding = it->create(); if (binding.isValid()) type->addOwnPropertyBinding(binding, it->specifier); @@ -614,12 +605,6 @@ void QQmlJSImportVisitor::processDefaultProperties() const QQmlJSMetaProperty defaultProp = parentScope->property(defaultPropertyName); auto propType = defaultProp.type(); const auto handleUnresolvedDefaultProperty = [&](const QQmlJSScope::ConstPtr &) { - - // Since we don't know the property type, we need to assume it's QQmlComponent and that - // IDs from the inner scopes are inaccessible. - for (const QQmlJSScope::Ptr &scope : std::as_const(*it)) - scope->setIsWrappedInImplicitComponent(true); - // Property type is not fully resolved we cannot tell any more than this m_logger->log(QStringLiteral("Property \"%1\" has incomplete type \"%2\". You may be " "missing an import.") @@ -628,8 +613,16 @@ void QQmlJSImportVisitor::processDefaultProperties() qmlUnresolvedType, it.value().constFirst()->sourceLocation()); }; + const auto wrapInImplicitComponent = [&]() { + // Since we don't know the property type, we need to assume it's QQmlComponent and that + // IDs from the inner scopes are inaccessible. + for (const QQmlJSScope::Ptr &scope : std::as_const(*it)) + scope->setIsWrappedInImplicitComponent(true); + }; + if (propType.isNull()) { handleUnresolvedDefaultProperty(propType); + wrapInImplicitComponent(); continue; } @@ -641,11 +634,13 @@ void QQmlJSImportVisitor::processDefaultProperties() qmlNonListProperty, it.value().constFirst()->sourceLocation()); } - if (!isTypeResolved(propType, handleUnresolvedDefaultProperty)) + if (!checkTypeResolved(propType, handleUnresolvedDefaultProperty)) { + wrapInImplicitComponent(); continue; + } for (const QQmlJSScope::Ptr &scope : std::as_const(*it)) { - if (!isTypeResolved(scope)) + if (!checkTypeResolved(scope)) continue; // Assigning any element to a QQmlComponent property implicitly wraps it into a Component @@ -747,19 +742,13 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() const QString propertyName = objectBinding.name; QQmlJSScope::Ptr childScope = objectBinding.childScope; - const auto handleUnresolvedType = [&](const QQmlJSScope::ConstPtr &type) { + // guarantees property lookup + if (!checkTypeResolved(objectBinding.scope)) { // Since we don't know the property type we need to assume that it's QQmlComponent and // that IDs from the child scope are inaccessible outside of it. childScope->setIsWrappedInImplicitComponent(true); - - m_logger->log(QStringLiteral("Type %1 is used but it is not resolved") - .arg(getScopeName(type, type->scopeType())), - qmlUnresolvedType, type->sourceLocation()); - }; - - // guarantees property lookup - if (!isTypeResolved(objectBinding.scope, handleUnresolvedType)) continue; + } QQmlJSMetaProperty property = objectBinding.scope->property(propertyName); @@ -769,11 +758,6 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() continue; } const auto handleUnresolvedProperty = [&](const QQmlJSScope::ConstPtr &) { - - // Since we don't know the property type we need to assume that it's QQmlComponent and - // that IDs from the child scope are inaccessible outside of it. - childScope->setIsWrappedInImplicitComponent(true); - // Property type is not fully resolved we cannot tell any more than this m_logger->log(QStringLiteral("Property \"%1\" has incomplete type \"%2\". You may be " "missing an import.") @@ -781,14 +765,24 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() .arg(property.typeName()), qmlUnresolvedType, objectBinding.location); }; + + const auto wrapInImplicitComponent = [&]() { + // Since we don't know the property type we need to assume that it's QQmlComponent and + // that IDs from the child scope are inaccessible outside of it. + childScope->setIsWrappedInImplicitComponent(true); + }; + if (property.type().isNull()) { + wrapInImplicitComponent(); handleUnresolvedProperty(property.type()); continue; } // guarantee that canAssign() can be called - if (!isTypeResolved(property.type(), handleUnresolvedProperty) - || !isTypeResolved(childScope)) { + if (!checkTypeResolved(property.type(), handleUnresolvedProperty)) { + wrapInImplicitComponent(); + continue; + } else if (!checkTypeResolved(childScope)) { continue; } @@ -1229,7 +1223,7 @@ void QQmlJSImportVisitor::breakInheritanceCycles(const QQmlJSScope::Ptr &origina const QString name = scope->baseTypeName(); if (!error.isEmpty()) { m_logger->log(error, qmlImport, scope->sourceLocation(), true, true); - } else if (!name.isEmpty()) { + } else if (!name.isEmpty() && !m_unresolvedTypes.hasSeen(scope)) { m_logger->log( name + ' '_L1 + wasNotFound + ' '_L1 + didYouAddAllImports, qmlImport, scope->sourceLocation(), true, true, |
