diff options
author | Sami Shalayel <sami.shalayel@qt.io> | 2023-08-29 16:15:21 +0200 |
---|---|---|
committer | Sami Shalayel <sami.shalayel@qt.io> | 2023-09-12 21:03:21 +0200 |
commit | 2bee7cf744f711df3b8ab9fa3905de086bb019bb (patch) | |
tree | 4be807dd1568a68a9721b2fc5d534f605598721f /src | |
parent | 410c2a4440d64c4b4b4896e156ed038a1d6e5773 (diff) |
qmljsimportvisitor: add warnings for lower case
Replace an assert with a warning, and warn when qualified import names
start with a lower case letter. Add a test for that.
Also warn when using a qualified import with a name starting with a
lower case, so users can fix their mistake more easily.
Change-Id: Iff2b9148c5a36625baad70798e2efe006905e2a3
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit eae7381b91192f6021e84f99be4d5c416aae9510)
Diffstat (limited to 'src')
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 1bdf98822e..6acd1d144b 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "qqmljsimportvisitor_p.h" +#include "qqmljslogger_p.h" #include "qqmljsmetatypes_p.h" #include "qqmljsresourcefilemapper_p.h" @@ -1385,13 +1386,35 @@ inline QQmlJSImportVisitor::UnfinishedBinding createNonUniqueScopeBinding(QQmlJSScope::Ptr &scope, const QString &name, const QQmlJS::SourceLocation &srcLocation); +static void logLowerCaseImport(QStringView superType, QQmlJS::SourceLocation location, + QQmlJSLogger *logger) +{ + QStringView namespaceName{ superType }; + namespaceName = namespaceName.first(namespaceName.indexOf(u'.')); + logger->log(u"Namespace '%1' of '%2' must start with an upper case letter."_s.arg(namespaceName) + .arg(superType), + qmlUncreatableType, location, true, true); +} + bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition) { const QString superType = buildName(definition->qualifiedTypeNameId); const bool isRoot = !rootScopeIsValid(); Q_ASSERT(!superType.isEmpty()); - if (superType.front().isUpper()) { + + // we need to assume that it is a type based on its capitalization. Types defined in inline + // components, for example, can have their type definition after their type usages: + // Item { property IC myIC; component IC: Item{}; } + const qsizetype indexOfTypeName = superType.lastIndexOf(u'.'); + const bool looksLikeGroupedProperty = superType.front().isLower(); + + if (indexOfTypeName != -1 && looksLikeGroupedProperty) { + logLowerCaseImport(superType, definition->qualifiedTypeNameId->identifierToken, + m_logger); + } + + if (!looksLikeGroupedProperty) { if (!isRoot) { enterEnvironment(QQmlSA::ScopeType::QMLScope, superType, definition->firstSourceLocation()); @@ -1438,7 +1461,6 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition) } else { enterEnvironmentNonUnique(QQmlSA::ScopeType::GroupedPropertyScope, superType, definition->firstSourceLocation()); - Q_ASSERT(rootScopeIsValid()); m_bindings.append(createNonUniqueScopeBinding(m_currentScope, superType, definition->firstSourceLocation())); QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); @@ -1509,6 +1531,10 @@ bool QQmlJSImportVisitor::visit(UiPublicMember *publicMember) publicMember->firstSourceLocation()); } QString typeName = buildName(publicMember->memberType); + if (typeName.contains(u'.') && typeName.front().isLower()) { + logLowerCaseImport(typeName, publicMember->typeToken, m_logger); + } + QString aliasExpr; const bool isAlias = (typeName == u"alias"_s); if (isAlias) { @@ -2202,6 +2228,11 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) QString prefix = QLatin1String(""); if (import->asToken.isValid()) { prefix += import->importId; + if (!import->importId.isEmpty() && !import->importId.front().isUpper()) { + m_logger->log(u"Import qualifier '%1' must start with a capital letter."_s.arg( + import->importId), + qmlImport, import->importIdToken, true, true); + } } auto filename = import->fileName.toString(); @@ -2483,6 +2514,11 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) bool needsResolution = false; int scopesEnteredCounter = 0; + const QString typeName = buildName(uiob->qualifiedTypeNameId); + if (typeName.front().isLower() && typeName.contains(u'.')) { + logLowerCaseImport(typeName, uiob->qualifiedTypeNameId->identifierToken, m_logger); + } + QString prefix; for (auto group = uiob->qualifiedId; group->next; group = group->next) { const QString idName = group->name.toString(); @@ -2518,7 +2554,7 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) if (needsResolution) QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); - enterEnvironment(QQmlSA::ScopeType::QMLScope, buildName(uiob->qualifiedTypeNameId), + enterEnvironment(QQmlSA::ScopeType::QMLScope, typeName, uiob->qualifiedTypeNameId->identifierToken); QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports, &m_usedTypes); |