aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmllint/findwarnings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qmllint/findwarnings.cpp')
-rw-r--r--tools/qmllint/findwarnings.cpp277
1 files changed, 1 insertions, 276 deletions
diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp
index 09ef63d4bd..b28a4ee695 100644
--- a/tools/qmllint/findwarnings.cpp
+++ b/tools/qmllint/findwarnings.cpp
@@ -43,21 +43,6 @@
#include <QtCore/qdiriterator.h>
#include <QtCore/qscopedvaluerollback.h>
-static const QString prefixedName(const QString &prefix, const QString &name)
-{
- Q_ASSERT(!prefix.endsWith('.'));
- return prefix.isEmpty() ? name : (prefix + QLatin1Char('.') + name);
-}
-
-static QQmlDirParser createQmldirParserForFile(const QString &filename)
-{
- QFile f(filename);
- f.open(QFile::ReadOnly);
- QQmlDirParser parser;
- parser.parse(f.readAll());
- return parser;
-}
-
void FindWarningVisitor::enterEnvironment(ScopeType type, const QString &name)
{
m_currentScope = ScopeTree::create(type, m_currentScope);
@@ -70,266 +55,6 @@ void FindWarningVisitor::leaveEnvironment()
m_currentScope = m_currentScope->parentScope();
}
-static const QLatin1String SlashQmldir = QLatin1String("/qmldir");
-static const QLatin1String SlashPluginsDotQmltypes = QLatin1String("/plugins.qmltypes");
-
-void FindWarningVisitor::Importer::readQmltypes(
- const QString &filename, QHash<QString, ScopeTree::Ptr> *objects)
-{
- const QFileInfo fileInfo(filename);
- if (!fileInfo.exists()) {
- m_warnings.append(QLatin1String("QML types file does not exist: ") + filename);
- return;
- }
-
- if (fileInfo.isDir()) {
- m_warnings.append(QLatin1String("QML types file cannot be a directory: ") + filename);
- return;
- }
-
- QFile file(filename);
- file.open(QFile::ReadOnly);
- TypeDescriptionReader reader { filename, file.readAll() };
- QStringList dependencies;
- auto succ = reader(objects, &dependencies);
- if (!succ)
- m_warnings.append(reader.errorMessage());
-}
-
-FindWarningVisitor::Importer::Import FindWarningVisitor::Importer::readQmldir(const QString &path)
-{
- Import result;
- auto reader = createQmldirParserForFile(path + SlashQmldir);
- result.imports.append(reader.imports());
- result.dependencies.append(reader.dependencies());
-
- QHash<QString, ScopeTree::Ptr> qmlComponents;
- const auto components = reader.components();
- for (auto it = components.begin(), end = components.end(); it != end; ++it) {
- const QString filePath = path + QLatin1Char('/') + it->fileName;
- if (!QFile::exists(filePath)) {
- m_warnings.append(it->fileName + QLatin1String(" is listed as component in ")
- + path + SlashQmldir
- + QLatin1String(" but does not exist.\n"));
- continue;
- }
-
- auto mo = qmlComponents.find(it.key());
- if (mo == qmlComponents.end())
- mo = qmlComponents.insert(it.key(), localFile2ScopeTree(filePath));
-
- (*mo)->addExport(
- it.key(), reader.typeNamespace(),
- ComponentVersion(it->version));
- }
- for (auto it = qmlComponents.begin(), end = qmlComponents.end(); it != end; ++it)
- result.objects.insert(it.key(), it.value());
-
- if (!reader.plugins().isEmpty() && QFile::exists(path + SlashPluginsDotQmltypes))
- readQmltypes(path + SlashPluginsDotQmltypes, &result.objects);
-
- const auto scripts = reader.scripts();
- for (const auto &script : scripts) {
- const QString filePath = path + QLatin1Char('/') + script.fileName;
- result.scripts.insert(script.nameSpace, localFile2ScopeTree(filePath));
- }
- return result;
-}
-
-void FindWarningVisitor::Importer::importDependencies(
- const FindWarningVisitor::Importer::Import &import,
- FindWarningVisitor::ImportedTypes *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.
- const QString invalidPrefix = QString::fromLatin1("$dependency$");
- for (auto const &dependency : qAsConst(import.dependencies))
- importHelper(dependency.module, types, invalidPrefix, dependency.version);
-
- for (auto const &import : qAsConst(import.imports)) {
- importHelper(import.module, types, prefix,
- import.isAutoImport ? version : import.version);
- }
-}
-
-void FindWarningVisitor::Importer::processImport(
- const FindWarningVisitor::Importer::Import &import,
- FindWarningVisitor::ImportedTypes *types,
- const QString &prefix)
-{
- for (auto it = import.scripts.begin(); it != import.scripts.end(); ++it) {
- types->importedQmlNames.insert(prefixedName(prefix, it.key()), it.value());
- types->exportedQmlNames.insert(it.key(), it.value());
- }
-
- // add objects
- for (auto it = import.objects.begin(); it != import.objects.end(); ++it) {
- const auto &val = it.value();
- types->cppNames.insert(val->internalName(), val);
-
- const auto exports = val->exports();
- for (const auto &valExport : exports) {
- types->importedQmlNames.insert(prefixedName(prefix, valExport.type()), val);
- types->exportedQmlNames.insert(valExport.type(), val);
- }
- }
-
- for (auto it = import.objects.begin(); it != import.objects.end(); ++it) {
- const auto &val = it.value();
- if (!val->isComposite()) // Otherwise we have already done it in localFile2ScopeTree()
- val->resolveTypes(types->cppNames);
- }
-}
-
-FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importBareQmlTypes(
- const QStringList &qmltypesFiles)
-{
- ImportedTypes types;
-
- for (auto const &dir : m_importPaths) {
- Import result;
- QDirIterator it { dir, QStringList() << QLatin1String("builtins.qmltypes"), QDir::NoFilter,
- QDirIterator::Subdirectories };
- while (it.hasNext())
- readQmltypes(it.next(), &result.objects);
- importDependencies(result, &types);
- processImport(result, &types);
- }
-
- if (qmltypesFiles.isEmpty()) {
- for (auto const &qmltypesPath : m_importPaths) {
- if (QFile::exists(qmltypesPath + SlashQmldir))
- continue;
- Import result;
- QDirIterator it {
- qmltypesPath, QStringList { QLatin1String("*.qmltypes") }, QDir::Files };
-
- while (it.hasNext()) {
- const QString name = it.next();
- if (!name.endsWith(QLatin1String("/builtins.qmltypes")))
- readQmltypes(name, &result.objects);
- }
-
- importDependencies(result, &types);
- processImport(result, &types);
- }
- } else {
- Import result;
-
- for (const auto &qmltypeFile : qmltypesFiles)
- readQmltypes(qmltypeFile, &result.objects);
-
- importDependencies(result, &types);
- processImport(result, &types);
- }
-
- return types;
-}
-
-FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importModule(
- const QString &module, const QString &prefix, QTypeRevision version)
-{
- ImportedTypes result;
- importHelper(module, &result, prefix, version);
- return result;
-}
-
-void FindWarningVisitor::Importer::importHelper(const QString &module, ImportedTypes *types,
- const QString &prefix, QTypeRevision version)
-{
-
- const QPair<QString, QTypeRevision> importId { module, version };
- const auto it = m_seenImports.find(importId);
- if (it != m_seenImports.end()) {
- importDependencies(*it, types, prefix, version);
- processImport(*it, types, prefix);
- return;
- }
-
- const auto qmltypesPaths = qQmlResolveImportPaths(module, m_importPaths, version);
- for (auto const &qmltypesPath : qmltypesPaths) {
- const QFileInfo file(qmltypesPath + SlashQmldir);
- if (file.exists()) {
- const auto import = readQmldir(file.canonicalPath());
- m_seenImports.insert(importId, import);
- importDependencies(import, types, prefix, version);
- processImport(import, types, prefix);
- return;
- }
- }
-
- m_seenImports.insert(importId, {});
-}
-
-ScopeTree::Ptr FindWarningVisitor::Importer::localFile2ScopeTree(const QString &filePath)
-{
- const auto seen = m_importedFiles.find(filePath);
- if (seen != m_importedFiles.end())
- return *seen;
-
- QmlJSTypeReader typeReader(filePath);
- ScopeTree::Ptr result = typeReader();
- m_importedFiles.insert(filePath, result);
-
- const QStringList errors = typeReader.errors();
- for (const QString &error : errors)
- m_warnings.append(error);
-
- ImportedTypes types;
-
- QDirIterator it {
- QFileInfo(filePath).canonicalPath(),
- QStringList() << QLatin1String("*.qml"),
- QDir::NoFilter
- };
- while (it.hasNext()) {
- ScopeTree::Ptr scope(localFile2ScopeTree(it.next()));
- if (!scope->internalName().isEmpty())
- types.importedQmlNames.insert(scope->internalName(), scope);
- }
-
- const auto imports = typeReader.imports();
- for (const auto &import : imports)
- importHelper(import.module, &types, import.prefix, import.version);
-
- result->resolveTypes(types.importedQmlNames);
- return result;
-}
-
-FindWarningVisitor::ImportedTypes FindWarningVisitor::Importer::importFileOrDirectory(
- const QString &fileOrDirectory, const QString &prefix)
-{
- ImportedTypes result;
-
- QString name = fileOrDirectory;
-
- if (QFileInfo(name).isRelative())
- name = QDir(m_currentDir).filePath(name);
-
- QFileInfo fileInfo(name);
- if (fileInfo.isFile()) {
- ScopeTree::Ptr scope(localFile2ScopeTree(fileInfo.canonicalFilePath()));
- result.importedQmlNames.insert(prefix.isEmpty() ? scope->internalName() : prefix, scope);
- result.exportedQmlNames.insert(scope->internalName(), scope);
- return result;
- }
-
- QDirIterator it {
- fileInfo.canonicalFilePath(),
- QStringList() << QLatin1String("*.qml"),
- QDir::NoFilter
- };
- while (it.hasNext()) {
- ScopeTree::Ptr scope(localFile2ScopeTree(it.next()));
- if (!scope->internalName().isEmpty()) {
- result.importedQmlNames.insert(prefixedName(prefix, scope->internalName()), scope);
- result.exportedQmlNames.insert(scope->internalName(), scope);
- }
- }
-
- return result;
-}
-
void FindWarningVisitor::importExportedNames(ScopeTree::ConstPtr scope)
{
QList<ScopeTree::ConstPtr> scopes;
@@ -388,7 +113,7 @@ void FindWarningVisitor::throwRecursionDepthError()
bool FindWarningVisitor::visit(QQmlJS::AST::UiProgram *)
{
enterEnvironment(ScopeType::QMLScope, "program");
- m_rootScopeImports = m_importer.importBareQmlTypes(m_qmltypesFiles);
+ m_rootScopeImports = m_importer.importBaseQmlTypes(m_qmltypesFiles);
// add "self" (as we only ever check the first part of a qualified identifier, we get away with
// using an empty ScopeTree