qmllint: Remove C++ types from the importer interface

We don't use them anymore. Now we can also make all the ScopeTrees const
again as we don't need to modify them anymore after importing.

Change-Id: I3ece767f4f62f06cb0640f1f191eb8d98400717c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2020-09-29 17:56:46 +02:00
parent e548c8576d
commit 5296c163ac
6 changed files with 51 additions and 49 deletions

View File

@ -188,8 +188,8 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<ScopeTree::FieldMember> &
if (unknownBuiltins.contains(typeName))
return true;
const auto it = m_types.qmlNames.find(typeName);
if (it == m_types.qmlNames.end()) {
const auto it = m_types.find(typeName);
if (it == m_types.end()) {
detectedRestrictiveKind = typeName;
detectedRestrictiveName = access.m_name;
scope = nullptr;
@ -232,7 +232,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<ScopeTree::FieldMember> &
ScopeTree::ConstPtr rootType;
if (!access.m_parentType.isEmpty())
rootType = m_types.qmlNames.value(access.m_parentType);
rootType = m_types.value(access.m_parentType);
else
rootType = scope;
@ -260,8 +260,8 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<ScopeTree::FieldMember> &
if (access.m_name.front().isUpper() && scope->scopeType() == ScopeType::QMLScope) {
// may be an attached type
const auto it = m_types.qmlNames.find(access.m_name);
if (it != m_types.qmlNames.end() && !(*it)->attachedTypeName().isEmpty()) {
const auto it = m_types.find(access.m_name);
if (it != m_types.end() && !(*it)->attachedTypeName().isEmpty()) {
if (const auto attached = (*it)->attachedType()) {
scope = attached;
continue;
@ -326,8 +326,8 @@ bool CheckIdentifiers::operator()(const QHash<QString, ScopeTree::ConstPtr> &qml
if (scopedName.front().isUpper()) {
const QString qualified = memberAccessBase.m_name + QLatin1Char('.')
+ scopedName;
const auto typeIt = m_types.qmlNames.find(qualified);
if (typeIt != m_types.qmlNames.end()) {
const auto typeIt = m_types.find(qualified);
if (typeIt != m_types.end()) {
memberAccessChain.takeFirst();
if (!checkMemberAccess(memberAccessChain, *typeIt))
noUnqualifiedIdentifier = false;
@ -370,8 +370,8 @@ bool CheckIdentifiers::operator()(const QHash<QString, ScopeTree::ConstPtr> &qml
if (memberAccessBase.m_name == QLatin1String("Qt"))
continue;
const auto typeIt = m_types.qmlNames.find(memberAccessBase.m_name);
if (typeIt != m_types.qmlNames.end()) {
const auto typeIt = m_types.find(memberAccessBase.m_name);
if (typeIt != m_types.end()) {
if (!checkMemberAccess(memberAccessChain, *typeIt))
noUnqualifiedIdentifier = false;
continue;

View File

@ -117,15 +117,15 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiProgram *)
if (!m_qmltypesFiles.isEmpty()) {
const auto baseTypes = m_importer.importQmltypes(m_qmltypesFiles);
m_rootScopeImports.qmlNames.insert(baseTypes.qmlNames);
m_rootScopeImports.insert(baseTypes);
}
// add "self" (as we only ever check the first part of a qualified identifier, we get away with
// using an empty ScopeTree
m_rootScopeImports.qmlNames.insert(QFileInfo { m_filePath }.baseName(), {});
m_rootScopeImports.insert(QFileInfo { m_filePath }.baseName(), {});
const auto imported = m_importer.importFileOrDirectory(QFileInfo(m_filePath).path());
m_rootScopeImports.qmlNames.insert(imported.qmlNames);
m_rootScopeImports.insert(imported);
const QStringList warnings = m_importer.takeWarnings();
for (const QString &warning : warnings) {
@ -328,7 +328,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.qmlNames.value(property.typeName()));
property.setType(m_rootScopeImports.value(property.typeName()));
m_currentScope->insertPropertyIdentifier(property);
}
return true;
@ -478,14 +478,14 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiImport *import)
const auto imported = m_importer.importFileOrDirectory(
file.isRelative() ? QFileInfo(m_filePath).dir().filePath(filename) : filename,
prefix);
m_rootScopeImports.qmlNames.insert(imported.qmlNames);
m_rootScopeImports.insert(imported);
}
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.qmlNames.value(importId));
m_qmlid2scope.insert(importId, m_rootScopeImports.value(importId));
}
auto uri = import->importUri;
while (uri) {
@ -498,7 +498,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiImport *import)
const auto imported = m_importer.importModule(
path, prefix, import->version ? import->version->version : QTypeRevision());
m_rootScopeImports.qmlNames.insert(imported.qmlNames);
m_rootScopeImports.insert(imported);
const QStringList warnings = m_importer.takeWarnings();
for (const QString &warning : warnings) {
@ -530,11 +530,11 @@ 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.qmlNames.value(uiob->qualifiedTypeNameId->name.toString()));
prop.setType(m_rootScopeImports.value(uiob->qualifiedTypeNameId->name.toString()));
m_currentScope->addProperty(prop);
enterEnvironment(ScopeType::QMLScope, name);
m_currentScope->resolveTypes(m_rootScopeImports.qmlNames);
m_currentScope->resolveTypes(m_rootScopeImports);
importExportedNames(m_currentScope);
return true;
}
@ -565,7 +565,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiObjectDefinition *uiod)
if (name.isLower())
return false; // Ignore grouped properties for now
m_currentScope->resolveTypes(m_rootScopeImports.qmlNames);
m_currentScope->resolveTypes(m_rootScopeImports);
importExportedNames(m_currentScope);
if (name.endsWith("Connections")) {
@ -595,7 +595,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiObjectDefinition *uiod)
do {
scope = scope->parentScope(); // TODO: rename method
} while (scope->scopeType() != ScopeType::QMLScope);
targetScope = m_rootScopeImports.qmlNames.value(scope->baseTypeName());
targetScope = m_rootScopeImports.value(scope->baseTypeName());
} else {
// there was a target, check if we already can find it
auto scopeIt = m_qmlid2scope.find(target);

View File

@ -118,7 +118,7 @@ QmlJSImporter::Import QmlJSImporter::readQmldir(const QString &path)
void QmlJSImporter::importDependencies(
const QmlJSImporter::Import &import,
QmlJSImporter::ImportedTypes *types, const QString &prefix, QTypeRevision version)
QmlJSImporter::AvailableTypes *types, const QString &prefix, QTypeRevision version)
{
// Import the dependencies with an invalid prefix. The prefix will never be matched by actual
// QML code but the C++ types will be visible.
@ -134,7 +134,7 @@ void QmlJSImporter::importDependencies(
void QmlJSImporter::processImport(
const QmlJSImporter::Import &import,
QmlJSImporter::ImportedTypes *types,
QmlJSImporter::AvailableTypes *types,
const QString &prefix)
{
for (auto it = import.scripts.begin(); it != import.scripts.end(); ++it)
@ -162,7 +162,7 @@ void QmlJSImporter::processImport(
*/
QmlJSImporter::ImportedTypes QmlJSImporter::importBuiltins()
{
ImportedTypes types;
AvailableTypes types;
for (auto const &dir : m_importPaths) {
Import result;
@ -174,7 +174,7 @@ QmlJSImporter::ImportedTypes QmlJSImporter::importBuiltins()
processImport(result, &types);
}
return types;
return types.qmlNames;
}
/*!
@ -182,7 +182,7 @@ QmlJSImporter::ImportedTypes QmlJSImporter::importBuiltins()
*/
QmlJSImporter::ImportedTypes QmlJSImporter::importQmltypes(const QStringList &qmltypesFiles)
{
ImportedTypes types;
AvailableTypes types;
Import result;
for (const auto &qmltypeFile : qmltypesFiles)
@ -191,18 +191,18 @@ QmlJSImporter::ImportedTypes QmlJSImporter::importQmltypes(const QStringList &qm
importDependencies(result, &types);
processImport(result, &types);
return types;
return types.qmlNames;
}
QmlJSImporter::ImportedTypes QmlJSImporter::importModule(
const QString &module, const QString &prefix, QTypeRevision version)
{
ImportedTypes result;
AvailableTypes result;
importHelper(module, &result, prefix, version);
return result;
return result.qmlNames;
}
void QmlJSImporter::importHelper(const QString &module, ImportedTypes *types,
void QmlJSImporter::importHelper(const QString &module, AvailableTypes *types,
const QString &prefix, QTypeRevision version)
{
@ -243,7 +243,7 @@ ScopeTree::Ptr QmlJSImporter::localFile2ScopeTree(const QString &filePath)
for (const QString &error : errors)
m_warnings.append(error);
ImportedTypes types;
AvailableTypes types;
QDirIterator it {
QFileInfo(filePath).canonicalPath(),
@ -267,7 +267,7 @@ ScopeTree::Ptr QmlJSImporter::localFile2ScopeTree(const QString &filePath)
QmlJSImporter::ImportedTypes QmlJSImporter::importFileOrDirectory(
const QString &fileOrDirectory, const QString &prefix)
{
ImportedTypes result;
AvailableTypes result;
QString name = fileOrDirectory;
@ -275,7 +275,7 @@ QmlJSImporter::ImportedTypes QmlJSImporter::importFileOrDirectory(
if (fileInfo.isFile()) {
ScopeTree::Ptr scope(localFile2ScopeTree(fileInfo.canonicalFilePath()));
result.qmlNames.insert(prefix.isEmpty() ? scope->internalName() : prefix, scope);
return result;
return result.qmlNames;
}
QDirIterator it {
@ -289,5 +289,5 @@ QmlJSImporter::ImportedTypes QmlJSImporter::importFileOrDirectory(
result.qmlNames.insert(prefixedName(prefix, scope->internalName()), scope);
}
return result;
return result.qmlNames;
}

View File

@ -45,14 +45,7 @@
class QmlJSImporter
{
public:
struct ImportedTypes
{
// C++ names used in qmltypes files for non-composite types
QHash<QString, ScopeTree::Ptr> cppNames;
// Names the importing component sees, including any prefixes
QHash<QString, ScopeTree::Ptr> qmlNames;
};
using ImportedTypes = QHash<QString, ScopeTree::ConstPtr>;
QmlJSImporter(const QStringList &importPaths) : m_importPaths(importPaths) {}
@ -72,6 +65,15 @@ public:
}
private:
struct AvailableTypes
{
// C++ names used in qmltypes files for non-composite types
QHash<QString, ScopeTree::ConstPtr> cppNames;
// Names the importing component sees, including any prefixes
QHash<QString, ScopeTree::ConstPtr> qmlNames;
};
struct Import {
QHash<QString, ScopeTree::Ptr> objects;
QHash<QString, ScopeTree::Ptr> scripts;
@ -79,13 +81,13 @@ private:
QList<QQmlDirParser::Import> dependencies;
};
void importHelper(const QString &module, ImportedTypes *types,
void importHelper(const QString &module, AvailableTypes *types,
const QString &prefix = QString(),
QTypeRevision version = QTypeRevision());
void processImport(const Import &import, ImportedTypes *types,
void processImport(const Import &import, AvailableTypes *types,
const QString &prefix = QString());
void importDependencies(const QmlJSImporter::Import &import,
ImportedTypes *types,
AvailableTypes *types,
const QString &prefix = QString(),
QTypeRevision version = QTypeRevision());
void readQmltypes(const QString &filename, QHash<QString, ScopeTree::Ptr> *objects);

View File

@ -144,14 +144,14 @@ bool ScopeTree::isIdInjectedFromSignal(const QString &id) const
return findCurrentQMLScope(parentScope())->m_injectedSignalIdentifiers.contains(id);
}
void ScopeTree::resolveTypes(const QHash<QString, ScopeTree::Ptr> &contextualTypes)
void ScopeTree::resolveTypes(const QHash<QString, ScopeTree::ConstPtr> &contextualTypes)
{
auto findType = [&](const QString &name) {
auto type = contextualTypes.constFind(name);
if (type != contextualTypes.constEnd())
return *type;
return ScopeTree::Ptr();
return ScopeTree::ConstPtr();
};
m_baseType = findType(m_baseTypeName);

View File

@ -208,7 +208,7 @@ public:
return m_injectedSignalIdentifiers;
}
void resolveTypes(const QHash<QString, ScopeTree::Ptr> &contextualTypes);
void resolveTypes(const QHash<QString, ConstPtr> &contextualTypes);
private:
ScopeTree(ScopeType type, const ScopeTree::Ptr &parentScope = ScopeTree::Ptr());
@ -229,14 +229,14 @@ private:
QString m_fileName;
QString m_internalName;
QString m_baseTypeName;
ScopeTree::WeakPtr m_baseType;
ScopeTree::WeakConstPtr m_baseType;
ScopeType m_scopeType = ScopeType::QMLScope;
QList<Export> m_exports;
QString m_defaultPropertyName;
QString m_attachedTypeName;
ScopeTree::WeakPtr m_attachedType;
ScopeTree::WeakConstPtr m_attachedType;
Flags m_flags;
AccessSemantics m_semantics = AccessSemantics::Reference;