aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qqmljsimportvisitor.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2025-01-16 17:04:23 +0100
committerUlf Hermann <ulf.hermann@qt.io>2025-01-17 14:13:48 +0100
commitc159f4e837d99c8cb4b260e7bbc390cdb83d5e19 (patch)
tree0fcdb73fa180b2a0d98b46d9e8bfbd4a4717e57b /src/qmlcompiler/qqmljsimportvisitor.cpp
parent0208321b8a571b9156a922305c200336a5b82a88 (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.cpp78
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,