aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmllint
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-24 15:09:38 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-25 23:57:59 +0200
commit8c8df9e02567f408a5b5516987459f9973d4d092 (patch)
tree6e723446d81087715c6ae0f5c06147eb3ac31a83 /tools/qmllint
parent294bcb3f3c59ebe9229205a204dacafa6642e0df (diff)
qmllint: Split available names into exported, imported, C++ names
exported names are the names a component intends to export. imported names are the names the importing component sees, possibly adding a prefix. C++ names are only used in qmltypes files for non-composite types. Change-Id: I843e34f07a026a06931ed76d72a3cce98e3e5552 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools/qmllint')
-rw-r--r--tools/qmllint/checkidentifiers.cpp2
-rw-r--r--tools/qmllint/checkidentifiers.h4
-rw-r--r--tools/qmllint/findwarnings.cpp93
-rw-r--r--tools/qmllint/findwarnings.h24
4 files changed, 79 insertions, 44 deletions
diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp
index c5897b1df3..fdffb556b6 100644
--- a/tools/qmllint/checkidentifiers.cpp
+++ b/tools/qmllint/checkidentifiers.cpp
@@ -84,7 +84,7 @@ void CheckIdentifiers::printContext(const QQmlJS::SourceLocation &location) cons
}
static bool walkViaParentAndAttachedScopes(ScopeTree::ConstPtr rootType,
- const QHash<QString, ScopeTree::ConstPtr> &allTypes,
+ const QHash<QString, ScopeTree::Ptr> &allTypes,
std::function<bool(ScopeTree::ConstPtr)> visit)
{
if (rootType == nullptr)
diff --git a/tools/qmllint/checkidentifiers.h b/tools/qmllint/checkidentifiers.h
index 36de88a846..8fd605f454 100644
--- a/tools/qmllint/checkidentifiers.h
+++ b/tools/qmllint/checkidentifiers.h
@@ -37,7 +37,7 @@ class CheckIdentifiers
{
public:
CheckIdentifiers(ColorOutput *colorOut, const QString &code, const QHash<QString,
- ScopeTree::ConstPtr> &types, const QString &fileName) :
+ ScopeTree::Ptr> &types, const QString &fileName) :
m_colorOut(colorOut), m_code(code), m_types(types), m_fileName(fileName)
{}
@@ -52,7 +52,7 @@ private:
ColorOutput *m_colorOut = nullptr;
QString m_code;
- QHash<QString, ScopeTree::ConstPtr> m_types;
+ QHash<QString, ScopeTree::Ptr> m_types;
QString m_fileName;
};
diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp
index 997b8eda3a..3e3d63f8ad 100644
--- a/tools/qmllint/findwarnings.cpp
+++ b/tools/qmllint/findwarnings.cpp
@@ -151,25 +151,28 @@ void FindWarningVisitor::Importer::processImport(
}
for (const auto &it : qAsConst(import.scripts)) {
- m_exportedName2Scope.insert(it.first, it.second);
+ m_exportedName2Scope.importedQmlNames.insert(prefixedName(prefix, it.first), it.second);
+ m_exportedName2Scope.exportedQmlNames.insert(it.first, it.second);
}
// add objects
for (auto it = import.objects.begin(); it != import.objects.end(); ++it) {
const auto &val = it.value();
- m_exportedName2Scope.insert(val->internalName(), val);
+ m_exportedName2Scope.cppNames.insert(val->internalName(), val);
const auto exports = val->exports();
- for (const auto &valExport : exports)
- m_exportedName2Scope.insert(prefixedName(prefix, valExport.type()), val);
+ for (const auto &valExport : exports) {
+ m_exportedName2Scope.importedQmlNames.insert(prefixedName(prefix, valExport.type()), val);
+ m_exportedName2Scope.exportedQmlNames.insert(valExport.type(), val);
+ }
}
}
-QHash<QString, ScopeTree::ConstPtr> FindWarningVisitor::Importer::importBareQmlTypes(
+FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importBareQmlTypes(
const QStringList &qmltypesFiles)
{
- QHash<QString, ScopeTree::ConstPtr> result;
- result.swap(m_exportedName2Scope);
+ ImportedTypes result;
+ qSwap(result, m_exportedName2Scope);
for (auto const &dir : m_importPaths) {
Import result;
@@ -205,17 +208,17 @@ QHash<QString, ScopeTree::ConstPtr> FindWarningVisitor::Importer::importBareQmlT
processImport("", result, QTypeRevision());
}
- result.swap(m_exportedName2Scope);
+ qSwap(result, m_exportedName2Scope);
return result;
}
-QHash<QString, ScopeTree::ConstPtr> FindWarningVisitor::Importer::importModule(
+FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importModule(
const QString &module, const QString &prefix, QTypeRevision version)
{
- QHash<QString, ScopeTree::ConstPtr> result;
- result.swap(m_exportedName2Scope);
+ ImportedTypes result;
+ qSwap(result, m_exportedName2Scope);
importHelper(module, prefix, version);
- result.swap(m_exportedName2Scope);
+ qSwap(result, m_exportedName2Scope);
return result;
}
@@ -252,11 +255,11 @@ ScopeTree::Ptr FindWarningVisitor::Importer::localFile2ScopeTree(const QString &
return result;
}
-QHash<QString, ScopeTree::ConstPtr> FindWarningVisitor::Importer::importFileOrDirectory(
+FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importFileOrDirectory(
const QString &fileOrDirectory, const QString &prefix)
{
- QHash<QString, ScopeTree::ConstPtr> result;
- result.swap(m_exportedName2Scope);
+ ImportedTypes result;
+ qSwap(result, m_exportedName2Scope);
QString name = fileOrDirectory;
@@ -265,28 +268,34 @@ QHash<QString, ScopeTree::ConstPtr> FindWarningVisitor::Importer::importFileOrDi
if (QFileInfo(name).isFile()) {
ScopeTree::Ptr scope(localFile2ScopeTree(name));
- m_exportedName2Scope.insert(prefix, scope);
- result.swap(m_exportedName2Scope);
+ m_exportedName2Scope.importedQmlNames.insert(
+ prefix.isEmpty() ? scope->internalName() : prefix, scope);
+ m_exportedName2Scope.exportedQmlNames.insert(scope->internalName(), scope);
+ qSwap(result, m_exportedName2Scope);
return result;
}
QDirIterator it { name, QStringList() << QLatin1String("*.qml"), QDir::NoFilter };
while (it.hasNext()) {
ScopeTree::Ptr scope(localFile2ScopeTree(it.next()));
- if (!scope->internalName().isEmpty())
- m_exportedName2Scope.insert(prefixedName(prefix, scope->internalName()), scope);
+ if (!scope->internalName().isEmpty()) {
+ m_exportedName2Scope.importedQmlNames.insert(prefixedName(prefix, scope->internalName()), scope);
+ m_exportedName2Scope.exportedQmlNames.insert(scope->internalName(), scope);
+ }
}
- result.swap(m_exportedName2Scope);
+ qSwap(result, m_exportedName2Scope);
return result;
}
void FindWarningVisitor::importExportedNames(QStringView prefix, QString name)
{
QList<ScopeTree::ConstPtr> scopes;
+ ScopeTree::ConstPtr scope = m_rootScopeImports.importedQmlNames.value(
+ m_rootScopeImports.importedQmlNames.contains(name)
+ ? name
+ : prefix + QLatin1Char('.') + name);
for (;;) {
- ScopeTree::ConstPtr scope = m_rootScopeImports.value(
- m_rootScopeImports.contains(name) ? name : prefix + QLatin1Char('.') + name);
if (scope) {
if (scopes.contains(scope)) {
QString inheritenceCycle = name;
@@ -310,7 +319,9 @@ void FindWarningVisitor::importExportedNames(QStringView prefix, QString name)
scopes.append(scope);
const auto properties = scope->properties();
for (auto property : properties) {
- property.setType(m_rootScopeImports.value(property.typeName()));
+ property.setType(scope->isComposite()
+ ? m_rootScopeImports.importedQmlNames.value(property.typeName())
+ : m_rootScopeImports.cppNames.value(property.typeName()));
m_currentScope->insertPropertyIdentifier(property);
}
@@ -318,6 +329,10 @@ void FindWarningVisitor::importExportedNames(QStringView prefix, QString name)
name = scope->baseTypeName();
if (name.isEmpty() || name == QLatin1String("QObject"))
break;
+
+ scope = scope->isComposite()
+ ? m_rootScopeImports.importedQmlNames.value(name)
+ : m_rootScopeImports.cppNames.value(name);
} else {
m_colorOut.write(QLatin1String("warning: "), Warning);
m_colorOut.write(name + QLatin1String(" was not found."
@@ -343,8 +358,11 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiProgram *)
// add "self" (as we only ever check the first part of a qualified identifier, we get away with
// using an empty ScopeTree
- m_rootScopeImports.insert(QFileInfo { m_filePath }.baseName(), {});
- m_rootScopeImports.insert(m_importer.importFileOrDirectory(".", QString()));
+ m_rootScopeImports.importedQmlNames.insert(QFileInfo { m_filePath }.baseName(), {});
+
+ const auto imported = m_importer.importFileOrDirectory(".");
+ m_rootScopeImports.importedQmlNames.insert(imported.importedQmlNames);
+ m_rootScopeImports.cppNames.insert(imported.cppNames);
const QStringList warnings = m_importer.takeWarnings();
for (const QString &warning : warnings) {
@@ -547,7 +565,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiPublicMember *uipm)
uipm->memberType ? uipm->memberType->name.toString() : QString(),
uipm->typeModifier == QLatin1String("list"), !uipm->isReadonlyMember, false,
uipm->memberType ? (uipm->memberType->name == QLatin1String("alias")) : false, 0);
- property.setType(m_rootScopeImports.value(property.typeName()));
+ property.setType(m_rootScopeImports.importedQmlNames.value(property.typeName()));
m_currentScope->insertPropertyIdentifier(property);
}
return true;
@@ -623,7 +641,7 @@ bool FindWarningVisitor::check()
if (!m_warnUnqualified)
return true;
- CheckIdentifiers check(&m_colorOut, m_code, m_rootScopeImports, m_filePath);
+ CheckIdentifiers check(&m_colorOut, m_code, m_rootScopeImports.importedQmlNames, m_filePath);
return check(m_qmlid2scope, m_rootScope, m_rootId);
}
@@ -692,14 +710,17 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiImport *import)
prefix += import->importId;
}
auto dirname = import->fileName.toString();
- if (!dirname.isEmpty())
- m_rootScopeImports.insert(m_importer.importFileOrDirectory(dirname, prefix));
+ if (!dirname.isEmpty()) {
+ const auto imported = m_importer.importFileOrDirectory(dirname, prefix);
+ m_rootScopeImports.importedQmlNames.insert(imported.importedQmlNames);
+ m_rootScopeImports.cppNames.insert(imported.cppNames);
+ }
QString path {};
if (!import->importId.isEmpty()) {
// TODO: do not put imported ids into the same space as qml IDs
const QString importId = import->importId.toString();
- m_qmlid2scope.insert(importId, m_rootScopeImports.value(importId));
+ m_qmlid2scope.insert(importId, m_rootScopeImports.importedQmlNames.value(importId));
}
auto uri = import->importUri;
while (uri) {
@@ -709,9 +730,11 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiImport *import)
}
path.chop(1);
- m_rootScopeImports.insert(
- m_importer.importModule(
- path, prefix, import->version ? import->version->version : QTypeRevision()));
+ const auto imported = m_importer.importModule(
+ path, prefix, import->version ? import->version->version : QTypeRevision());
+
+ m_rootScopeImports.importedQmlNames.insert(imported.importedQmlNames);
+ m_rootScopeImports.cppNames.insert(imported.cppNames);
const QStringList warnings = m_importer.takeWarnings();
for (const QString &warning : warnings) {
@@ -746,7 +769,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob)
MetaProperty prop(uiob->qualifiedId->name.toString(), name, false, true, true,
name == QLatin1String("alias"), 0);
- prop.setType(m_rootScopeImports.value(uiob->qualifiedTypeNameId->name.toString()));
+ prop.setType(m_rootScopeImports.importedQmlNames.value(uiob->qualifiedTypeNameId->name.toString()));
m_currentScope->addProperty(prop);
enterEnvironment(ScopeType::QMLScope, name);
@@ -811,7 +834,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiObjectDefinition *uiod)
do {
scope = scope->parentScope(); // TODO: rename method
} while (scope->scopeType() != ScopeType::QMLScope);
- targetScope = m_rootScopeImports.value(scope->internalName());
+ targetScope = m_rootScopeImports.importedQmlNames.value(scope->internalName());
} else {
// there was a target, check if we already can find it
auto scopeIt = m_qmlid2scope.find(target);
diff --git a/tools/qmllint/findwarnings.h b/tools/qmllint/findwarnings.h
index f16cff595c..7e3ea14128 100644
--- a/tools/qmllint/findwarnings.h
+++ b/tools/qmllint/findwarnings.h
@@ -60,16 +60,28 @@ public:
bool check();
private:
+ struct ImportedTypes
+ {
+ // C++ names used in qmltypes files for non-composite types
+ QHash<QString, ScopeTree::Ptr> cppNames;
+
+ // Names a component intends to export, without prefix
+ QHash<QString, ScopeTree::Ptr> exportedQmlNames;
+
+ // Names the importing component sees, possibly adding a prefix
+ QHash<QString, ScopeTree::Ptr> importedQmlNames;
+ };
+
class Importer
{
public:
Importer(const QString &currentDir, const QStringList &importPaths) :
m_currentDir(currentDir), m_importPaths(importPaths) {}
- QHash<QString, ScopeTree::ConstPtr> importBareQmlTypes(const QStringList &qmltypesFiles);
- QHash<QString, ScopeTree::ConstPtr> importFileOrDirectory(
- const QString &fileOrDirectory, const QString &prefix);
- QHash<QString, ScopeTree::ConstPtr> importModule(
+ ImportedTypes importBareQmlTypes(const QStringList &qmltypesFiles);
+ ImportedTypes importFileOrDirectory(
+ const QString &fileOrDirectory, const QString &prefix = QString());
+ ImportedTypes importModule(
const QString &module, const QString &prefix = QString(),
QTypeRevision version = QTypeRevision());
@@ -100,10 +112,10 @@ private:
QSet<QPair<QString, QString>> m_seenImports;
QStringList m_warnings;
- QHash<QString, ScopeTree::ConstPtr> m_exportedName2Scope;
+ ImportedTypes m_exportedName2Scope;
};
- QHash<QString, ScopeTree::ConstPtr> m_rootScopeImports;
+ ImportedTypes m_rootScopeImports;
ScopeTree::Ptr m_rootScope;
ScopeTree::Ptr m_currentScope;