qmllint: Move deprecation logic to qmlcompiler
Moves the remaining logic for handling deprecation warnings to qmlcompiler furthering the goal of removing checkidentifiers for good. Change-Id: I21ac524ea9c02b2e8c8f65962011976927fd7432 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
96de5c702b
commit
ad02973c05
|
@ -237,7 +237,7 @@ void QQmlJSTypePropagator::generate_LoadGlobalLookup(int index)
|
|||
generate_LoadName(m_jsUnitGenerator->lookupNameIndex(index));
|
||||
}
|
||||
|
||||
void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name)
|
||||
QQmlJS::SourceLocation QQmlJSTypePropagator::getCurrentSourceLocation() const
|
||||
{
|
||||
Q_ASSERT(m_currentContext->sourceLocationTable);
|
||||
const auto &entries = m_currentContext->sourceLocationTable->entries;
|
||||
|
@ -247,6 +247,13 @@ void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name)
|
|||
Q_ASSERT(item != entries.end());
|
||||
auto location = item->location;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name) const
|
||||
{
|
||||
auto location = getCurrentSourceLocation();
|
||||
|
||||
if (m_currentScope->isInCustomParserParent()) {
|
||||
Q_ASSERT(!m_currentScope->baseType().isNull());
|
||||
// Only ignore custom parser based elements if it's not Connections.
|
||||
|
@ -339,6 +346,54 @@ void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name)
|
|||
}
|
||||
}
|
||||
|
||||
void QQmlJSTypePropagator::checkDeprecated(QQmlJSScope::ConstPtr scope, const QString &name,
|
||||
bool isMethod) const
|
||||
{
|
||||
Q_ASSERT(!scope.isNull());
|
||||
auto qmlScope = QQmlJSScope::findCurrentQMLScope(scope);
|
||||
if (qmlScope.isNull())
|
||||
return;
|
||||
|
||||
QList<QQmlJSAnnotation> annotations;
|
||||
|
||||
QQmlJSMetaMethod method;
|
||||
|
||||
if (isMethod) {
|
||||
const QVector<QQmlJSMetaMethod> methods = qmlScope->methods(name);
|
||||
if (methods.isEmpty())
|
||||
return;
|
||||
method = methods.constFirst();
|
||||
annotations = method.annotations();
|
||||
} else {
|
||||
QQmlJSMetaProperty property = qmlScope->property(name);
|
||||
if (!property.isValid())
|
||||
return;
|
||||
annotations = property.annotations();
|
||||
}
|
||||
|
||||
auto deprecationAnn = std::find_if(
|
||||
annotations.constBegin(), annotations.constEnd(),
|
||||
[](const QQmlJSAnnotation &annotation) { return annotation.isDeprecation(); });
|
||||
|
||||
if (deprecationAnn == annotations.constEnd())
|
||||
return;
|
||||
|
||||
QQQmlJSDeprecation deprecation = deprecationAnn->deprecation();
|
||||
|
||||
QString descriptor = name;
|
||||
if (isMethod)
|
||||
descriptor += u'(' + method.parameterNames().join(u", "_qs) + u')';
|
||||
|
||||
QString message = QStringLiteral("%1 \"%2\" is deprecated")
|
||||
.arg(isMethod ? u"Method"_qs : u"Property"_qs)
|
||||
.arg(descriptor);
|
||||
|
||||
if (!deprecation.reason.isEmpty())
|
||||
message.append(QStringLiteral(" (Reason: %1)").arg(deprecation.reason));
|
||||
|
||||
m_logger->logWarning(message, Log_Deprecation, getCurrentSourceLocation());
|
||||
}
|
||||
|
||||
void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index)
|
||||
{
|
||||
const QString name =
|
||||
|
@ -353,8 +408,9 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index)
|
|||
return;
|
||||
}
|
||||
|
||||
m_state.savedPrefix.clear();
|
||||
checkDeprecated(m_currentScope, name, false);
|
||||
|
||||
m_state.savedPrefix.clear();
|
||||
if (!m_state.accumulatorOut.isValid()) {
|
||||
setError(u"Cannot access value for name "_qs + name, true);
|
||||
handleUnqualifiedAccess(name);
|
||||
|
@ -554,6 +610,8 @@ void QQmlJSTypePropagator::generate_CallProperty(int nameIndex, int base, int ar
|
|||
return;
|
||||
}
|
||||
|
||||
checkDeprecated(containedType, propertyName, true);
|
||||
|
||||
propagateCall(member.method(), argc, argv);
|
||||
}
|
||||
|
||||
|
@ -670,7 +728,9 @@ void QQmlJSTypePropagator::generate_CallGlobalLookup(int index, int argc, int ar
|
|||
|
||||
void QQmlJSTypePropagator::generate_CallQmlContextPropertyLookup(int index, int argc, int argv)
|
||||
{
|
||||
propagateScopeLookupCall(m_jsUnitGenerator->lookupName(index), argc, argv);
|
||||
const QString name = m_jsUnitGenerator->lookupName(index);
|
||||
propagateScopeLookupCall(name, argc, argv);
|
||||
checkDeprecated(m_currentScope, name, true);
|
||||
}
|
||||
|
||||
void QQmlJSTypePropagator::generate_CallWithSpread(int func, int thisObject, int argc, int argv)
|
||||
|
|
|
@ -260,7 +260,9 @@ private:
|
|||
bool needsMorePasses = false;
|
||||
};
|
||||
|
||||
void handleUnqualifiedAccess(const QString &name);
|
||||
void handleUnqualifiedAccess(const QString &name) const;
|
||||
void checkDeprecated(QQmlJSScope::ConstPtr scope, const QString &name, bool isMethod) const;
|
||||
QQmlJS::SourceLocation getCurrentSourceLocation() const;
|
||||
|
||||
void propagateBinaryOperation(QSOperator::Op op, int lhs);
|
||||
void propagateCall(const QList<QQmlJSMetaMethod> &methods, int argc, int argv);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import QtQml
|
||||
|
||||
QtObject {
|
||||
@Deprecated {}
|
||||
property int deprecated: 10
|
||||
|
|
|
@ -306,48 +306,11 @@ void CheckIdentifiers::operator()(
|
|||
}
|
||||
|
||||
auto qmlScope = QQmlJSScope::findCurrentQMLScope(currentScope);
|
||||
if (qmlScope->hasMethod(memberAccessBase.m_name)) {
|
||||
// a property of a JavaScript function, or a method
|
||||
auto methods = qmlScope->methods(memberAccessBase.m_name);
|
||||
const QQmlJSMetaMethod &method = methods.constFirst();
|
||||
const auto &annotations = method.annotations();
|
||||
auto deprecationAnn = std::find_if(annotations.constBegin(), annotations.constEnd(), [](const QQmlJSAnnotation& annotation) {
|
||||
return annotation.isDeprecation();
|
||||
});
|
||||
|
||||
// Once we encountered one possible method that is not deprecated,
|
||||
// we can assume that the one beyond that is not what was being referenced
|
||||
if (deprecationAnn == annotations.constEnd())
|
||||
continue;
|
||||
|
||||
QQQmlJSDeprecation deprecation = deprecationAnn->deprecation();
|
||||
|
||||
QString message = QStringLiteral("Method \"%1(%2)\" is deprecated")
|
||||
.arg(memberAccessBase.m_name, method.parameterNames().join(QStringLiteral(", ")));
|
||||
|
||||
if (!deprecation.reason.isEmpty())
|
||||
message.append(QStringLiteral(" (Reason: %1)").arg(deprecation.reason));
|
||||
|
||||
m_logger->logWarning(message, Log_Deprecation, memberAccessBase.m_location);
|
||||
if (qmlScope->hasMethod(memberAccessBase.m_name))
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto property = qmlScope->property(memberAccessBase.m_name);
|
||||
if (!property.propertyName().isEmpty()) {
|
||||
for (const QQmlJSAnnotation &annotation : property.annotations()) {
|
||||
if (annotation.isDeprecation()) {
|
||||
QQQmlJSDeprecation deprecation = annotation.deprecation();
|
||||
|
||||
QString message = QStringLiteral("Property \"%1\" is deprecated")
|
||||
.arg(memberAccessBase.m_name);
|
||||
|
||||
if (!deprecation.reason.isEmpty())
|
||||
message.append(QStringLiteral(" (Reason: %1)").arg(deprecation.reason));
|
||||
|
||||
m_logger->logWarning(message, Log_Deprecation, memberAccessBase.m_location);
|
||||
}
|
||||
}
|
||||
|
||||
if (memberAccessChain.isEmpty() || unknownBuiltins.contains(property.typeName()))
|
||||
continue;
|
||||
|
||||
|
|
Loading…
Reference in New Issue