qmllint: Fix accessing attached types with prefixes

When ever a attached type lookup fails we have check whether combining it with the next member would make it work.

Fixes: QTBUG-83762
Change-Id: I8d159ccc07442f3939b40ea5f6b737da18439615
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Maximilian Goldstein 2021-03-17 17:51:58 +01:00
parent cd074545c3
commit b07d653c09
2 changed files with 17 additions and 7 deletions

View File

@ -311,11 +311,9 @@ void TestQmllint::dirtyQmlCode_data()
<< QStringLiteral("brokenNamespace.qml")
<< QString("Warning: type not found in namespace at %1:4:17")
<< QString();
// TODO: This fails but currently for the wrong reasons, make sure to add a warning message requirement
// once it does fail properly in order to avoid regressions.
QTest::newRow("segFault (bad)")
<< QStringLiteral("SegFault.bad.qml")
<< QString()
<< QStringLiteral("Property \"foobar\" not found on type \"QQuickScreenAttached\"")
<< QString();
QTest::newRow("VariableUsedBeforeDeclaration")
<< QStringLiteral("useBeforeDeclaration.qml")
@ -459,7 +457,6 @@ void TestQmllint::cleanQmlCode()
{
QFETCH(QString, filename);
const QString warnings = runQmllint(filename, true);
QEXPECT_FAIL("segFault", "This property exists and should not produce a warning", Abort);
QVERIFY2(warnings.isEmpty(), qPrintable(warnings));
}
@ -505,7 +502,6 @@ QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed, c
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
QEXPECT_FAIL("segFault", "This property exists and should not produce a warning", Abort);
if (shouldSucceed)
QCOMPARE(process.exitCode(), 0);
else

View File

@ -123,7 +123,9 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<FieldMember> &members,
}
QQmlJSScope::ConstPtr scope = outerScope;
for (const FieldMember &access : members) {
for (qsizetype i = 0; i < members.size(); i++) {
const FieldMember &access = members.at(i);
if (scope.isNull()) {
m_colorOut->writePrefixedMessage(
QString::fromLatin1("Type \"%1\" of base \"%2\" not found when accessing member \"%3\" at %4:%5:%6.\n")
@ -254,7 +256,19 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<FieldMember> &members,
if (access.m_name.front().isUpper() && scope->scopeType() == QQmlJSScope::QMLScope) {
// may be an attached type
const auto it = m_types.find(access.m_name);
auto it = m_types.find(access.m_name);
// Something was found but it wasn't the attached type we were looking for, it could be a prefix
if (it != m_types.end() && !(*it) && i+1 < members.length()) {
// See whether this is due to us getting the prefixed property in two accesses (i.e. "T" and "Item")
// by checking again with a fixed name.
it = m_types.find(access.m_name + QLatin1Char('.') + members[++i].m_name);
if (it == m_types.end() || !(*it) || (*it)->attachedTypeName().isEmpty())
--i;
}
if (it != m_types.end() && *it && !(*it)->attachedTypeName().isEmpty()) {
if (const auto attached = (*it)->attachedType()) {
scope = attached;