diff options
Diffstat (limited to 'src/qmlcompiler/qqmljstypepropagator.cpp')
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 203890d89b..6222b8acb1 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -257,7 +257,7 @@ QQmlJS::SourceLocation QQmlJSTypePropagator::getCurrentBindingSourceLocation() c return combine(entries.constFirst().location, entries.constLast().location); } -void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name) const +void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name, bool isMethod) const { auto location = getCurrentSourceLocation(); @@ -268,8 +268,12 @@ void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name) const return; } - if (isMissingPropertyType(m_function->qmlScope, name)) + if (isMethod) { + if (isCallingProperty(m_function->qmlScope, name)) + return; + } else if (isMissingPropertyType(m_function->qmlScope, name)) { return; + } std::optional<FixSuggestion> suggestion; @@ -445,6 +449,46 @@ bool QQmlJSTypePropagator::isMissingPropertyType(QQmlJSScope::ConstPtr scope, return true; } +bool QQmlJSTypePropagator::isCallingProperty(QQmlJSScope::ConstPtr scope, const QString &name) const +{ + auto property = scope->property(name); + if (!property.isValid()) + return false; + + QString propertyType = u"Property"_qs; + + auto methods = scope->methods(name); + + QString errorType; + if (!methods.isEmpty()) { + errorType = u"shadowed by a property."_qs; + switch (methods.first().methodType()) { + case QQmlJSMetaMethod::Signal: + propertyType = u"Signal"_qs; + break; + case QQmlJSMetaMethod::Slot: + propertyType = u"Slot"_qs; + break; + case QQmlJSMetaMethod::Method: + propertyType = u"Method"_qs; + break; + } + } else if (property.type() == m_typeResolver->varType()) { + errorType = + u"a variant property. It may or may not be a method. Use a regular function instead."_qs; + } else if (property.type() == m_typeResolver->jsValueType()) { + errorType = + u"a QJSValue property. It may or may not be a method. Use a regular Q_INVOKABLE instead."_qs; + } else { + errorType = u"not a method"_qs; + } + + m_logger->logWarning(u"%1 \"%2\" is %3"_qs.arg(propertyType, name, errorType), Log_Type, + getCurrentSourceLocation(), true, true, {}); + + return true; +} + void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index) { const int nameIndex = m_jsUnitGenerator->lookupNameIndex(index); @@ -475,7 +519,7 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index) setError(u"Cannot access value for name "_qs + name); if (!isRestricted) - handleUnqualifiedAccess(name); + handleUnqualifiedAccess(name, false); } else if (m_typeResolver->genericType(m_state.accumulatorOut.storedType()).isNull()) { // It should really be valid. // We get the generic type from aotContext->loadQmlContextPropertyIdLookup(). @@ -777,6 +821,9 @@ void QQmlJSTypePropagator::generate_CallProperty(int nameIndex, int base, int ar setError(u"Type %1 does not have a property %2 for calling"_qs .arg(callBase.descriptiveName(), propertyName)); + if (callBase.isType() && isCallingProperty(callBase.type(), propertyName)) + return; + if (checkRestricted(propertyName)) return; @@ -909,6 +956,8 @@ void QQmlJSTypePropagator::propagateScopeLookupCall(const QString &functionName, m_state.accumulatorOut = m_typeResolver->globalType(m_typeResolver->jsValueType()); setError(u"Cannot find function '%1'"_qs.arg(functionName)); + + handleUnqualifiedAccess(functionName, true); } void QQmlJSTypePropagator::generate_CallGlobalLookup(int index, int argc, int argv) |