diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-01 12:40:01 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-10-05 14:58:32 +0200 |
commit | 767dd738d3de9306062707fe05d32c91ed755da3 (patch) | |
tree | ebadcc9809322d5d78ce28f9b82bad1db949f232 /tools/shared | |
parent | e7d90fc5268cdca6aa10f422f00ad4a0049ea157 (diff) |
Long live libQtQmlCompiler!
Move all the code from tools/shared into src/qmlcompiler and build a
static library from it so that we can re-use it in external tools.
Change-Id: I7c8d8e59063dc7c711f4072f103a01095e6f5997
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools/shared')
-rw-r--r-- | tools/shared/importedmembersvisitor.cpp | 170 | ||||
-rw-r--r-- | tools/shared/importedmembersvisitor.h | 71 | ||||
-rw-r--r-- | tools/shared/metatypes.h | 200 | ||||
-rw-r--r-- | tools/shared/qmljsimporter.cpp | 291 | ||||
-rw-r--r-- | tools/shared/qmljsimporter.h | 103 | ||||
-rw-r--r-- | tools/shared/qmljstypereader.cpp | 136 | ||||
-rw-r--r-- | tools/shared/qmljstypereader.h | 70 | ||||
-rw-r--r-- | tools/shared/qmlstreamwriter.cpp | 190 | ||||
-rw-r--r-- | tools/shared/qmlstreamwriter.h | 67 | ||||
-rw-r--r-- | tools/shared/resourcefilemapper.cpp | 170 | ||||
-rw-r--r-- | tools/shared/resourcefilemapper.h | 54 | ||||
-rw-r--r-- | tools/shared/scopetree.cpp | 181 | ||||
-rw-r--r-- | tools/shared/scopetree.h | 221 | ||||
-rw-r--r-- | tools/shared/shared.pri | 31 | ||||
-rw-r--r-- | tools/shared/typedescriptionreader.cpp | 689 | ||||
-rw-r--r-- | tools/shared/typedescriptionreader.h | 95 |
16 files changed, 0 insertions, 2739 deletions
diff --git a/tools/shared/importedmembersvisitor.cpp b/tools/shared/importedmembersvisitor.cpp deleted file mode 100644 index 559c0533f7..0000000000 --- a/tools/shared/importedmembersvisitor.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "importedmembersvisitor.h" -#include "scopetree.h" - -using namespace QQmlJS::AST; - -ScopeTree::Ptr ImportedMembersVisitor::result(const QString &scopeName) const -{ - ScopeTree::Ptr result = ScopeTree::create(); - result->setIsComposite(true); - result->setInternalName(scopeName); - result->setBaseTypeName(m_rootObject->baseTypeName()); - const auto properties = m_rootObject->properties(); - for (auto property : properties) { - if (property.isAlias()) { - const auto it = m_objects.find(property.typeName()); - if (it != m_objects.end()) - property.setType(*it); - result->addProperty(property); - } else { - result->addProperty(property); - } - } - - for (const auto &method : m_rootObject->methods()) - result->addMethod(method); - - for (const auto &enumerator : m_rootObject->enums()) - result->addEnum(enumerator); - - return result; -} - -bool ImportedMembersVisitor::visit(UiObjectDefinition *definition) -{ - ScopeTree::Ptr scope = ScopeTree::create(); - QString superType; - for (auto segment = definition->qualifiedTypeNameId; segment; segment = segment->next) { - if (!superType.isEmpty()) - superType.append(u'.'); - superType.append(segment->name.toString()); - } - scope->setBaseTypeName(superType); - if (!m_rootObject) - m_rootObject = scope; - m_currentObjects.append(scope); - return true; -} - -void ImportedMembersVisitor::endVisit(UiObjectDefinition *) -{ - m_currentObjects.pop_back(); -} - -bool ImportedMembersVisitor::visit(UiPublicMember *publicMember) -{ - switch (publicMember->type) { - case UiPublicMember::Signal: { - UiParameterList *param = publicMember->parameters; - MetaMethod method; - method.setMethodType(MetaMethod::Signal); - method.setMethodName(publicMember->name.toString()); - while (param) { - method.addParameter(param->name.toString(), param->type->name.toString()); - param = param->next; - } - currentObject()->addMethod(method); - break; - } - case UiPublicMember::Property: { - auto typeName = publicMember->memberType->name; - const bool isAlias = (typeName == QLatin1String("alias")); - if (isAlias) { - const auto expression = cast<ExpressionStatement *>(publicMember->statement); - if (const auto idExpression = cast<IdentifierExpression *>(expression->expression)) - typeName = idExpression->name; - } - MetaProperty prop { - publicMember->name.toString(), - typeName.toString(), - false, - false, - false, - isAlias, - 0 - }; - currentObject()->addProperty(prop); - break; - } - } - return true; -} - -bool ImportedMembersVisitor::visit(UiSourceElement *sourceElement) -{ - if (FunctionExpression *fexpr = sourceElement->sourceElement->asFunctionDefinition()) { - MetaMethod method; - method.setMethodName(fexpr->name.toString()); - method.setMethodType(MetaMethod::Method); - FormalParameterList *parameters = fexpr->formals; - while (parameters) { - method.addParameter(parameters->element->bindingIdentifier.toString(), QString()); - parameters = parameters->next; - } - currentObject()->addMethod(method); - } else if (ClassExpression *clexpr = sourceElement->sourceElement->asClassDefinition()) { - MetaProperty prop { clexpr->name.toString(), QString(), false, false, false, false, 1 }; - currentObject()->addProperty(prop); - } else if (cast<VariableStatement *>(sourceElement->sourceElement)) { - // nothing to do - } else { - const auto loc = sourceElement->firstSourceLocation(); - m_errors.append( - "unsupportedd sourceElement at " - + QString::fromLatin1("%1:%2: ").arg(loc.startLine).arg(loc.startColumn) - + QString::number(sourceElement->sourceElement->kind)); - } - return true; -} - -bool ImportedMembersVisitor::visit(UiScriptBinding *scriptBinding) -{ - if (scriptBinding->qualifiedId->name == QLatin1String("id")) { - const auto *statement = cast<ExpressionStatement *>(scriptBinding->statement); - const auto *idExprension = cast<IdentifierExpression *>(statement->expression); - m_objects.insert(idExprension->name.toString(), currentObject()); - } - return true; -} - -bool ImportedMembersVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied) -{ - MetaEnum qmlEnum(uied->name.toString()); - for (const auto *member = uied->members; member; member = member->next) - qmlEnum.addKey(member->member.toString()); - currentObject()->addEnum(qmlEnum); - return true; -} - -void ImportedMembersVisitor::throwRecursionDepthError() -{ - m_errors.append(QStringLiteral("Maximum statement or expression depth exceeded")); -} diff --git a/tools/shared/importedmembersvisitor.h b/tools/shared/importedmembersvisitor.h deleted file mode 100644 index ab44deda9b..0000000000 --- a/tools/shared/importedmembersvisitor.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef IMPORTEDMEMBERSVISITOR_H -#define IMPORTEDMEMBERSVISITOR_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include "scopetree.h" -#include "qcoloroutput.h" - -#include <private/qqmljsast_p.h> - -class ImportedMembersVisitor : public QQmlJS::AST::Visitor -{ -public: - ScopeTree::Ptr result(const QString &scopeName) const; - QStringList errors() const { return m_errors; } - -private: - bool visit(QQmlJS::AST::UiObjectDefinition *) override; - void endVisit(QQmlJS::AST::UiObjectDefinition *) override; - bool visit(QQmlJS::AST::UiPublicMember *) override; - bool visit(QQmlJS::AST::UiSourceElement *) override; - bool visit(QQmlJS::AST::UiScriptBinding *) override; - bool visit(QQmlJS::AST::UiEnumDeclaration *uied) override; - void throwRecursionDepthError() override; - - ScopeTree::Ptr currentObject() const { return m_currentObjects.back(); } - - QVector<ScopeTree::Ptr> m_currentObjects; - ScopeTree::ConstPtr m_rootObject; - QHash<QString, ScopeTree::Ptr> m_objects; - - QStringList m_errors; -}; - -#endif // IMPORTEDMEMBERSVISITOR_H diff --git a/tools/shared/metatypes.h b/tools/shared/metatypes.h deleted file mode 100644 index d462fb684f..0000000000 --- a/tools/shared/metatypes.h +++ /dev/null @@ -1,200 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef METATYPES_H -#define METATYPES_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qsharedpointer.h> - -// MetaMethod and MetaProperty have both type names and actual ScopeTree types. -// When parsing the information from the relevant QML or qmltypes files, we only -// see the names and don't have a complete picture of the types, yet. In a second -// pass we typically fill in the types. The types may have multiple exported names -// and the the name property of MetaProperty and MetaMethod still carries some -// significance regarding which name was chosen to refer to the type. In a third -// pass we may further specify the type if the context provides additional information. -// The parent of an Item, for example, is typically not just a QtObject, but rather -// some other Item with custom properties. - -class ScopeTree; -class MetaEnum -{ - QStringList m_keys; - QString m_name; - QString m_alias; - bool m_isFlag = false; - -public: - MetaEnum() = default; - explicit MetaEnum(QString name) : m_name(std::move(name)) {} - - bool isValid() const { return !m_name.isEmpty(); } - - QString name() const { return m_name; } - void setName(const QString &name) { m_name = name; } - - QString alias() const { return m_alias; } - void setAlias(const QString &alias) { m_alias = alias; } - - bool isFlag() const { return m_isFlag; } - void setIsFlag(bool isFlag) { m_isFlag = isFlag; } - - void addKey(const QString &key) { m_keys.append(key); } - QStringList keys() const { return m_keys; } -}; - -class MetaMethod -{ -public: - enum Type { - Signal, - Slot, - Method - }; - - enum Access { - Private, - Protected, - Public - }; - - MetaMethod() = default; - explicit MetaMethod(QString name, QString returnType = QString()) - : m_name(std::move(name)) - , m_returnTypeName(std::move(returnType)) - , m_methodType(Method) - , m_methodAccess(Public) - {} - - QString methodName() const { return m_name; } - void setMethodName(const QString &name) { m_name = name; } - - QString returnTypeName() const { return m_returnTypeName; } - QSharedPointer<const ScopeTree> returnType() const { return m_returnType.toStrongRef(); } - void setReturnTypeName(const QString &type) { m_returnTypeName = type; } - void setReturnType(const QSharedPointer<const ScopeTree> &type) - { - m_returnType = type; - } - - QStringList parameterNames() const { return m_paramNames; } - QStringList parameterTypeNames() const { return m_paramTypeNames; } - QList<QSharedPointer<const ScopeTree>> parameterTypes() const - { - QList<QSharedPointer<const ScopeTree>> result; - for (const auto &type : m_paramTypes) - result.append(type.toStrongRef()); - return result; - } - void setParameterTypes(const QList<QSharedPointer<const ScopeTree>> &types) - { - Q_ASSERT(types.length() == m_paramNames.length()); - m_paramTypes.clear(); - for (const auto &type : types) - m_paramTypes.append(type); - } - void addParameter(const QString &name, const QString &typeName, - const QSharedPointer<const ScopeTree> &type = {}) - { - m_paramNames.append(name); - m_paramTypeNames.append(typeName); - m_paramTypes.append(type); - } - - int methodType() const { return m_methodType; } - void setMethodType(Type methodType) { m_methodType = methodType; } - - Access access() const { return m_methodAccess; } - - int revision() const { return m_revision; } - void setRevision(int r) { m_revision = r; } - -private: - QString m_name; - QString m_returnTypeName; - QWeakPointer<const ScopeTree> m_returnType; - - QStringList m_paramNames; - QStringList m_paramTypeNames; - QList<QWeakPointer<const ScopeTree>> m_paramTypes; - - Type m_methodType = Signal; - Access m_methodAccess = Private; - int m_revision = 0; -}; - -class MetaProperty -{ - QString m_propertyName; - QString m_typeName; - QWeakPointer<const ScopeTree> m_type; - bool m_isList; - bool m_isWritable; - bool m_isPointer; - bool m_isAlias; - int m_revision; - -public: - MetaProperty(QString propertyName, QString typeName, - bool isList, bool isWritable, bool isPointer, bool isAlias, - int revision) - : m_propertyName(std::move(propertyName)) - , m_typeName(std::move(typeName)) - , m_isList(isList) - , m_isWritable(isWritable) - , m_isPointer(isPointer) - , m_isAlias(isAlias) - , m_revision(revision) - {} - - QString propertyName() const { return m_propertyName; } - QString typeName() const { return m_typeName; } - - void setType(const QSharedPointer<const ScopeTree> &type) { m_type = type; } - QSharedPointer<const ScopeTree> type() const { return m_type.toStrongRef(); } - - bool isList() const { return m_isList; } - bool isWritable() const { return m_isWritable; } - bool isPointer() const { return m_isPointer; } - bool isAlias() const { return m_isAlias; } - int revision() const { return m_revision; } -}; - -#endif // METATYPES_H diff --git a/tools/shared/qmljsimporter.cpp b/tools/shared/qmljsimporter.cpp deleted file mode 100644 index f2e8453c7c..0000000000 --- a/tools/shared/qmljsimporter.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmljsimporter.h" -#include "typedescriptionreader.h" -#include "qmljstypereader.h" - -#include <QtQml/private/qqmlimportresolver_p.h> - -#include <QtCore/qfileinfo.h> -#include <QtCore/qdiriterator.h> - -static const QLatin1String SlashQmldir = QLatin1String("/qmldir"); -static const QLatin1String SlashPluginsDotQmltypes = QLatin1String("/plugins.qmltypes"); - -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 QmlJSImporter::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()); -} - -QmlJSImporter::Import QmlJSImporter::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(), 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 QmlJSImporter::importDependencies( - const QmlJSImporter::Import &import, - 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. - 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 QmlJSImporter::processImport( - const QmlJSImporter::Import &import, - QmlJSImporter::AvailableTypes *types, - const QString &prefix) -{ - for (auto it = import.scripts.begin(); it != import.scripts.end(); ++it) - types->qmlNames.insert(prefixedName(prefix, 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->qmlNames.insert(prefixedName(prefix, 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); - } -} - -/*! - * Imports builtins.qmltypes found in any of the import paths. - */ -QmlJSImporter::ImportedTypes QmlJSImporter::importBuiltins() -{ - AvailableTypes 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); - } - - return types.qmlNames; -} - -/*! - * Imports types from the specified \a qmltypesFiles. - */ -QmlJSImporter::ImportedTypes QmlJSImporter::importQmltypes(const QStringList &qmltypesFiles) -{ - AvailableTypes types; - Import result; - - for (const auto &qmltypeFile : qmltypesFiles) - readQmltypes(qmltypeFile, &result.objects); - - importDependencies(result, &types); - processImport(result, &types); - - return types.qmlNames; -} - -QmlJSImporter::ImportedTypes QmlJSImporter::importModule( - const QString &module, const QString &prefix, QTypeRevision version) -{ - AvailableTypes result; - importHelper(module, &result, prefix, version); - return result.qmlNames; -} - -void QmlJSImporter::importHelper(const QString &module, AvailableTypes *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 QmlJSImporter::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); - - AvailableTypes 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.qmlNames.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.qmlNames); - return result; -} - -QmlJSImporter::ImportedTypes QmlJSImporter::importFileOrDirectory( - const QString &fileOrDirectory, const QString &prefix) -{ - AvailableTypes result; - - QString name = fileOrDirectory; - - QFileInfo fileInfo(name); - if (fileInfo.isFile()) { - ScopeTree::Ptr scope(localFile2ScopeTree(fileInfo.canonicalFilePath())); - result.qmlNames.insert(prefix.isEmpty() ? scope->internalName() : prefix, scope); - return result.qmlNames; - } - - QDirIterator it { - fileInfo.canonicalFilePath(), - QStringList() << QLatin1String("*.qml"), - QDir::NoFilter - }; - while (it.hasNext()) { - ScopeTree::Ptr scope(localFile2ScopeTree(it.next())); - if (!scope->internalName().isEmpty()) - result.qmlNames.insert(prefixedName(prefix, scope->internalName()), scope); - } - - return result.qmlNames; -} diff --git a/tools/shared/qmljsimporter.h b/tools/shared/qmljsimporter.h deleted file mode 100644 index 6dbd5cc527..0000000000 --- a/tools/shared/qmljsimporter.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLJSIMPORTER_H -#define QMLJSIMPORTER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include "scopetree.h" -#include <QtQml/private/qqmldirparser_p.h> - -class QmlJSImporter -{ -public: - using ImportedTypes = QHash<QString, ScopeTree::ConstPtr>; - - QmlJSImporter(const QStringList &importPaths) : m_importPaths(importPaths) {} - - ImportedTypes importBuiltins(); - ImportedTypes importQmltypes(const QStringList &qmltypesFiles); - ImportedTypes importFileOrDirectory( - const QString &fileOrDirectory, const QString &prefix = QString()); - ImportedTypes importModule( - const QString &module, const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); - - QStringList takeWarnings() - { - QStringList result = std::move(m_warnings); - m_warnings.clear(); - return result; - } - -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; - QList<QQmlDirParser::Import> imports; - QList<QQmlDirParser::Import> dependencies; - }; - - void importHelper(const QString &module, AvailableTypes *types, - const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); - void processImport(const Import &import, AvailableTypes *types, - const QString &prefix = QString()); - void importDependencies(const QmlJSImporter::Import &import, - AvailableTypes *types, - const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); - void readQmltypes(const QString &filename, QHash<QString, ScopeTree::Ptr> *objects); - Import readQmldir(const QString &dirname); - ScopeTree::Ptr localFile2ScopeTree(const QString &filePath); - - QStringList m_importPaths; - QHash<QPair<QString, QTypeRevision>, Import> m_seenImports; - QHash<QString, ScopeTree::Ptr> m_importedFiles; - QStringList m_warnings; -}; - -#endif // QMLJSIMPORTER_H diff --git a/tools/shared/qmljstypereader.cpp b/tools/shared/qmljstypereader.cpp deleted file mode 100644 index 4adacf96b4..0000000000 --- a/tools/shared/qmljstypereader.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmljstypereader.h" -#include "importedmembersvisitor.h" - -#include <QtQml/private/qqmljsast_p.h> -#include <QtQml/private/qqmljsengine_p.h> -#include <QtQml/private/qqmljslexer_p.h> -#include <QtQml/private/qqmljsparser_p.h> -#include <QtQml/private/qqmlimportresolver_p.h> - -#include <QtCore/qfileinfo.h> -#include <QtCore/qdebug.h> - -static QList<QmlJSTypeReader::Import> parseHeaders(QQmlJS::AST::UiHeaderItemList *header) -{ - using namespace QQmlJS::AST; - QList<QmlJSTypeReader::Import> imports; - - for (; header; header = header->next) { - auto import = cast<UiImport *>(header->headerItem); - if (!import) - continue; - - QString path; - auto uri = import->importUri; - while (uri) { - path.append(uri->name); - path.append(u'.'); - uri = uri->next; - } - path.chop(1); - imports.append({ - path, - import->version ? import->version->version : QTypeRevision(), - import->asToken.isValid() ? import->importId.toString() : QString() - }); - } - - return imports; -} - -static ScopeTree::Ptr parseProgram(QQmlJS::AST::Program *program, const QString &name) -{ - using namespace QQmlJS::AST; - ScopeTree::Ptr result = ScopeTree::create(ScopeType::JSLexicalScope); - result->setInternalName(name); - for (auto *statement = program->statements; statement; statement = statement->next) { - if (auto *function = cast<FunctionDeclaration *>(statement->statement)) { - MetaMethod method(function->name.toString()); - method.setMethodType(MetaMethod::Method); - for (auto *parameters = function->formals; parameters; parameters = parameters->next) - method.addParameter(parameters->element->bindingIdentifier.toString(), QString()); - result->addMethod(method); - } - } - return result; -} - -ScopeTree::Ptr QmlJSTypeReader::operator()() -{ - using namespace QQmlJS::AST; - const QFileInfo info { m_file }; - QString baseName = info.baseName(); - const QString scopeName = baseName.endsWith(QStringLiteral(".ui")) ? baseName.chopped(3) - : baseName; - - QQmlJS::Engine engine; - QQmlJS::Lexer lexer(&engine); - - const QString lowerSuffix = info.suffix().toLower(); - const bool isESModule = lowerSuffix == QLatin1String("mjs"); - const bool isJavaScript = isESModule || lowerSuffix == QLatin1String("js"); - - QFile file(m_file); - if (!file.open(QFile::ReadOnly)) { - ScopeTree::Ptr result = ScopeTree::create( - isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope); - result->setInternalName(scopeName); - return result; - } - - QString code = QString::fromUtf8(file.readAll()); - file.close(); - - lexer.setCode(code, /*line = */ 1, /*qmlMode=*/ !isJavaScript); - QQmlJS::Parser parser(&engine); - - const bool success = isJavaScript ? (isESModule ? parser.parseModule() - : parser.parseProgram()) - : parser.parse(); - if (!success) { - ScopeTree::Ptr result = ScopeTree::create( - isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope); - result->setInternalName(scopeName); - return result; - } - - if (!isJavaScript) { - QQmlJS::AST::UiProgram *program = parser.ast(); - m_imports = parseHeaders(program->headers); - ImportedMembersVisitor membersVisitor; - program->members->accept(&membersVisitor); - m_errors = membersVisitor.errors(); - return membersVisitor.result(scopeName); - } - - // TODO: Anything special to do with ES modules here? - return parseProgram(QQmlJS::AST::cast<QQmlJS::AST::Program *>(parser.rootNode()), scopeName); -} diff --git a/tools/shared/qmljstypereader.h b/tools/shared/qmljstypereader.h deleted file mode 100644 index 9afa5d46e6..0000000000 --- a/tools/shared/qmljstypereader.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLJSTYPERADER_H -#define QMLJSTYPERADER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include "scopetree.h" - -#include <QtQml/private/qqmljsastfwd_p.h> - -#include <QtCore/qpair.h> -#include <QtCore/qset.h> - -class QmlJSTypeReader -{ -public: - struct Import { - QString module; - QTypeRevision version; - QString prefix; - }; - - QmlJSTypeReader(const QString &file) : m_file(file) {} - - ScopeTree::Ptr operator()(); - QList<Import> imports() const { return m_imports; } - QStringList errors() const { return m_errors; } - -private: - QString m_file; - QList<Import> m_imports; - QStringList m_errors; -}; - -#endif // QMLJSTYPEREADER_H diff --git a/tools/shared/qmlstreamwriter.cpp b/tools/shared/qmlstreamwriter.cpp deleted file mode 100644 index b0fbc4e443..0000000000 --- a/tools/shared/qmlstreamwriter.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmlstreamwriter.h" - -#include <QtCore/QBuffer> -#include <QtCore/QStringList> - -QmlStreamWriter::QmlStreamWriter(QByteArray *array) - : m_indentDepth(0) - , m_pendingLineLength(0) - , m_maybeOneline(false) - , m_stream(new QBuffer(array)) -{ - m_stream->open(QIODevice::WriteOnly); -} - -void QmlStreamWriter::writeStartDocument() -{ -} - -void QmlStreamWriter::writeEndDocument() -{ -} - -void QmlStreamWriter::writeLibraryImport(const QString &uri, int majorVersion, int minorVersion, const QString &as) -{ - m_stream->write(QString::fromLatin1("import %1 %2.%3").arg(uri, QString::number(majorVersion), QString::number(minorVersion)).toUtf8()); - if (!as.isEmpty()) - m_stream->write(QString::fromLatin1(" as %1").arg(as).toUtf8()); - m_stream->write("\n"); -} - -void QmlStreamWriter::writeStartObject(const QString &component) -{ - flushPotentialLinesWithNewlines(); - writeIndent(); - m_stream->write(QString::fromLatin1("%1 {").arg(component).toUtf8()); - ++m_indentDepth; - m_maybeOneline = true; -} - -void QmlStreamWriter::writeEndObject() -{ - if (m_maybeOneline && !m_pendingLines.isEmpty()) { - --m_indentDepth; - for (int i = 0; i < m_pendingLines.size(); ++i) { - m_stream->write(" "); - m_stream->write(m_pendingLines.at(i).trimmed()); - if (i != m_pendingLines.size() - 1) - m_stream->write(";"); - } - m_stream->write(" }\n"); - m_pendingLines.clear(); - m_pendingLineLength = 0; - m_maybeOneline = false; - } else { - flushPotentialLinesWithNewlines(); - --m_indentDepth; - writeIndent(); - m_stream->write("}\n"); - } -} - -void QmlStreamWriter::writeScriptBinding(const QString &name, const QString &rhs) -{ - writePotentialLine(QString::fromLatin1("%1: %2").arg(name, rhs).toUtf8()); -} - -void QmlStreamWriter::writeBooleanBinding(const QString &name, bool value) -{ - writeScriptBinding(name, value ? QLatin1String("true") : QLatin1String("false")); -} - -void QmlStreamWriter::writeArrayBinding(const QString &name, const QStringList &elements) -{ - flushPotentialLinesWithNewlines(); - writeIndent(); - - // try to use a single line - QString singleLine; - singleLine += QString::fromLatin1("%1: [").arg(name); - for (int i = 0; i < elements.size(); ++i) { - singleLine += elements.at(i); - if (i != elements.size() - 1) - singleLine += QLatin1String(", "); - } - singleLine += QLatin1String("]\n"); - if (singleLine.size() + m_indentDepth * 4 < 80) { - m_stream->write(singleLine.toUtf8()); - return; - } - - // write multi-line - m_stream->write(QString::fromLatin1("%1: [\n").arg(name).toUtf8()); - ++m_indentDepth; - for (int i = 0; i < elements.size(); ++i) { - writeIndent(); - m_stream->write(elements.at(i).toUtf8()); - if (i != elements.size() - 1) { - m_stream->write(",\n"); - } else { - m_stream->write("\n"); - } - } - --m_indentDepth; - writeIndent(); - m_stream->write("]\n"); -} - -void QmlStreamWriter::write(const QString &data) -{ - flushPotentialLinesWithNewlines(); - m_stream->write(data.toUtf8()); -} - -void QmlStreamWriter::writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue) -{ - flushPotentialLinesWithNewlines(); - writeIndent(); - m_stream->write(QString::fromLatin1("%1: {\n").arg(name).toUtf8()); - ++m_indentDepth; - for (int i = 0; i < keyValue.size(); ++i) { - const QString key = keyValue.at(i).first; - const QString value = keyValue.at(i).second; - writeIndent(); - m_stream->write(QString::fromLatin1("%1: %2").arg(key, value).toUtf8()); - if (i != keyValue.size() - 1) { - m_stream->write(",\n"); - } else { - m_stream->write("\n"); - } - } - --m_indentDepth; - writeIndent(); - m_stream->write("}\n"); -} - -void QmlStreamWriter::writeIndent() -{ - m_stream->write(QByteArray(m_indentDepth * 4, ' ')); -} - -void QmlStreamWriter::writePotentialLine(const QByteArray &line) -{ - m_pendingLines.append(line); - m_pendingLineLength += line.size(); - if (m_pendingLineLength >= 80) { - flushPotentialLinesWithNewlines(); - } -} - -void QmlStreamWriter::flushPotentialLinesWithNewlines() -{ - if (m_maybeOneline) - m_stream->write("\n"); - for (const QByteArray &line : qAsConst(m_pendingLines)) { - writeIndent(); - m_stream->write(line); - m_stream->write("\n"); - } - m_pendingLines.clear(); - m_pendingLineLength = 0; - m_maybeOneline = false; -} diff --git a/tools/shared/qmlstreamwriter.h b/tools/shared/qmlstreamwriter.h deleted file mode 100644 index cb642159ea..0000000000 --- a/tools/shared/qmlstreamwriter.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLSTREAMWRITER_H -#define QMLSTREAMWRITER_H - -#include <QtCore/QIODevice> -#include <QtCore/QList> -#include <QtCore/QString> -#include <QtCore/QScopedPointer> -#include <QtCore/QPair> - -class QmlStreamWriter -{ -public: - QmlStreamWriter(QByteArray *array); - - void writeStartDocument(); - void writeEndDocument(); - void writeLibraryImport(const QString &uri, int majorVersion, int minorVersion, const QString &as = QString()); - //void writeFilesystemImport(const QString &file, const QString &as = QString()); - void writeStartObject(const QString &component); - void writeEndObject(); - void writeScriptBinding(const QString &name, const QString &rhs); - void writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue); - void writeArrayBinding(const QString &name, const QStringList &elements); - void write(const QString &data); - void writeBooleanBinding(const QString &name, bool value); - -private: - void writeIndent(); - void writePotentialLine(const QByteArray &line); - void flushPotentialLinesWithNewlines(); - - int m_indentDepth; - QList<QByteArray> m_pendingLines; - int m_pendingLineLength; - bool m_maybeOneline; - QScopedPointer<QIODevice> m_stream; -}; - -#endif // QMLSTREAMWRITER_H diff --git a/tools/shared/resourcefilemapper.cpp b/tools/shared/resourcefilemapper.cpp deleted file mode 100644 index b9cf463575..0000000000 --- a/tools/shared/resourcefilemapper.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "resourcefilemapper.h" - -#include <QFileInfo> -#include <QDir> -#include <QXmlStreamReader> - -ResourceFileMapper::ResourceFileMapper(const QStringList &resourceFiles) -{ - for (const QString &fileName: resourceFiles) { - QFile f(fileName); - if (!f.open(QIODevice::ReadOnly)) - continue; - populateFromQrcFile(f); - } -} - -bool ResourceFileMapper::isEmpty() const -{ - return qrcPathToFileSystemPath.isEmpty(); -} - -QStringList ResourceFileMapper::resourcePaths(const QString &fileName) -{ - const QString absPath = QDir::cleanPath(QDir::current().absoluteFilePath(fileName)); - QStringList resourcePaths; - for (auto it = qrcPathToFileSystemPath.cbegin(), end = qrcPathToFileSystemPath.cend(); it != end; ++it) { - if (QFileInfo(it.value()) == QFileInfo(absPath)) - resourcePaths.append(it.key()); - } - return resourcePaths; -} - -QStringList ResourceFileMapper::qmlCompilerFiles(FileOutput fo) const -{ - QStringList files; - for (auto it = qrcPathToFileSystemPath.constBegin(), end = qrcPathToFileSystemPath.constEnd(); - it != end; ++it) { - const QString &qrcPath = it.key(); - const QString suffix = QFileInfo(qrcPath).suffix(); - if (suffix != QStringLiteral("qml") && suffix != QStringLiteral("js") && suffix != QStringLiteral("mjs")) - continue; - if (fo == FileOutput::AbsoluteFilePath) - files << it.value(); - else - files << qrcPath; - } - return files; -} - -void ResourceFileMapper::populateFromQrcFile(QFile &file) -{ - enum State { - InitialState, - InRCC, - InResource, - InFile - }; - State state = InitialState; - - QDir qrcDir = QFileInfo(file).absoluteDir(); - - QString prefix; - QString currentFileName; - QXmlStreamAttributes currentFileAttributes; - - QXmlStreamReader reader(&file); - while (!reader.atEnd()) { - switch (reader.readNext()) { - case QXmlStreamReader::StartElement: - if (reader.name() == QStringLiteral("RCC")) { - if (state != InitialState) - return; - state = InRCC; - continue; - } else if (reader.name() == QStringLiteral("qresource")) { - if (state != InRCC) - return; - state = InResource; - QXmlStreamAttributes attributes = reader.attributes(); - if (attributes.hasAttribute(QStringLiteral("prefix"))) - prefix = attributes.value(QStringLiteral("prefix")).toString(); - if (!prefix.startsWith(QLatin1Char('/'))) - prefix.prepend(QLatin1Char('/')); - if (!prefix.endsWith(QLatin1Char('/'))) - prefix.append(QLatin1Char('/')); - continue; - } else if (reader.name() == QStringLiteral("file")) { - if (state != InResource) - return; - state = InFile; - currentFileAttributes = reader.attributes(); - continue; - } - return; - - case QXmlStreamReader::EndElement: - if (reader.name() == QStringLiteral("file")) { - if (state != InFile) - return; - state = InResource; - continue; - } else if (reader.name() == QStringLiteral("qresource")) { - if (state != InResource) - return; - state = InRCC; - continue; - } else if (reader.name() == QStringLiteral("RCC")) { - if (state != InRCC) - return; - state = InitialState; - continue; - } - return; - - case QXmlStreamReader::Characters: { - if (reader.isWhitespace()) - break; - if (state != InFile) - return; - currentFileName = reader.text().toString(); - if (currentFileName.isEmpty()) - continue; - - const QString fsPath = QDir::cleanPath(qrcDir.absoluteFilePath(currentFileName)); - - if (currentFileAttributes.hasAttribute(QStringLiteral("alias"))) - currentFileName = currentFileAttributes.value(QStringLiteral("alias")).toString(); - - currentFileName = QDir::cleanPath(currentFileName); - while (currentFileName.startsWith(QLatin1String("../"))) - currentFileName.remove(0, 3); - - const QString qrcPath = prefix + currentFileName; - if (QFile::exists(fsPath)) - qrcPathToFileSystemPath.insert(qrcPath, fsPath); - continue; - } - - default: break; - } - } -} diff --git a/tools/shared/resourcefilemapper.h b/tools/shared/resourcefilemapper.h deleted file mode 100644 index ed3e486149..0000000000 --- a/tools/shared/resourcefilemapper.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef RESOURCEFILEMAPPER_H -#define RESOURCEFILEMAPPER_H - -#include <QStringList> -#include <QHash> -#include <QFile> - -struct ResourceFileMapper -{ - enum class FileOutput { - RelativeFilePath, - AbsoluteFilePath - }; - ResourceFileMapper(const QStringList &resourceFiles); - - bool isEmpty() const; - - QStringList resourcePaths(const QString &fileName); - QStringList qmlCompilerFiles(FileOutput fo = FileOutput::RelativeFilePath) const; - -private: - void populateFromQrcFile(QFile &file); - - QHash<QString, QString> qrcPathToFileSystemPath; -}; - -#endif // RESOURCEFILEMAPPER_H diff --git a/tools/shared/scopetree.cpp b/tools/shared/scopetree.cpp deleted file mode 100644 index 7ebf636b2a..0000000000 --- a/tools/shared/scopetree.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "scopetree.h" - -#include <QtCore/qqueue.h> -#include <QtCore/qsharedpointer.h> - -#include <algorithm> - -ScopeTree::ScopeTree(ScopeType type, const ScopeTree::Ptr &parentScope) - : m_parentScope(parentScope), m_scopeType(type) {} - -ScopeTree::Ptr ScopeTree::create(ScopeType type, const ScopeTree::Ptr &parentScope) -{ - ScopeTree::Ptr childScope(new ScopeTree{type, parentScope}); - if (parentScope) { - Q_ASSERT(type != ScopeType::QMLScope - || !parentScope->m_parentScope - || parentScope->parentScope()->m_scopeType == ScopeType::QMLScope - || parentScope->parentScope()->m_internalName == QLatin1String("global")); - parentScope->m_childScopes.push_back(childScope); - } - return childScope; -} - -void ScopeTree::insertJSIdentifier(const QString &name, const JavaScriptIdentifier &identifier) -{ - Q_ASSERT(m_scopeType != ScopeType::QMLScope); - if (identifier.kind == JavaScriptIdentifier::LexicalScoped - || identifier.kind == JavaScriptIdentifier::Injected - || m_scopeType == ScopeType::JSFunctionScope) { - m_jsIdentifiers.insert(name, identifier); - } else { - auto targetScope = parentScope(); - while (targetScope->m_scopeType != ScopeType::JSFunctionScope) - targetScope = targetScope->parentScope(); - targetScope->m_jsIdentifiers.insert(name, identifier); - } -} - -void ScopeTree::insertPropertyIdentifier(const MetaProperty &property) -{ - addProperty(property); - MetaMethod method(property.propertyName() + QLatin1String("Changed"), QLatin1String("void")); - addMethod(method); -} - -bool ScopeTree::isIdInCurrentScope(const QString &id) const -{ - return isIdInCurrentQMlScopes(id) || isIdInCurrentJSScopes(id); -} - -bool ScopeTree::isIdInCurrentQMlScopes(const QString &id) const -{ - if (m_scopeType == ScopeType::QMLScope) - return m_properties.contains(id) || m_methods.contains(id) || m_enums.contains(id); - - const auto qmlScope = findCurrentQMLScope(parentScope()); - return qmlScope->m_properties.contains(id) - || qmlScope->m_methods.contains(id) - || qmlScope->m_enums.contains(id); -} - -bool ScopeTree::isIdInCurrentJSScopes(const QString &id) const -{ - if (m_scopeType != ScopeType::QMLScope && m_jsIdentifiers.contains(id)) - return true; - - for (auto jsScope = parentScope(); jsScope; jsScope = jsScope->parentScope()) { - if (jsScope->m_scopeType != ScopeType::QMLScope && jsScope->m_jsIdentifiers.contains(id)) - return true; - } - - return false; -} - -bool ScopeTree::isIdInjectedFromSignal(const QString &id) const -{ - const auto found = findJSIdentifier(id); - return found.has_value() && found->kind == JavaScriptIdentifier::Injected; -} - -std::optional<JavaScriptIdentifier> ScopeTree::findJSIdentifier(const QString &id) const -{ - for (const auto *scope = this; scope; scope = scope->parentScope().data()) { - if (scope->m_scopeType == ScopeType::JSFunctionScope - || scope->m_scopeType == ScopeType::JSLexicalScope) { - auto it = scope->m_jsIdentifiers.find(id); - if (it != scope->m_jsIdentifiers.end()) - return *it; - } - } - - return std::optional<JavaScriptIdentifier>{}; -} - -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::ConstPtr(); - }; - - m_baseType = findType(m_baseTypeName); - m_attachedType = findType(m_attachedTypeName); - - for (auto it = m_properties.begin(), end = m_properties.end(); it != end; ++it) - it->setType(findType(it->typeName())); - - for (auto it = m_methods.begin(), end = m_methods.end(); it != end; ++it) { - it->setReturnType(findType(it->returnTypeName())); - const auto paramNames = it->parameterTypeNames(); - QList<ScopeTree::ConstPtr> paramTypes; - - for (const QString ¶mName: paramNames) - paramTypes.append(findType(paramName)); - - it->setParameterTypes(paramTypes); - } -} - -ScopeTree::ConstPtr ScopeTree::findCurrentQMLScope(const ScopeTree::ConstPtr &scope) -{ - auto qmlScope = scope; - while (qmlScope && qmlScope->m_scopeType != ScopeType::QMLScope) - qmlScope = qmlScope->parentScope(); - return qmlScope; -} - -void ScopeTree::addExport(const QString &name, const QString &package, const QTypeRevision &version) -{ - m_exports.append(Export(package, name, version, 0)); -} - -void ScopeTree::setExportMetaObjectRevision(int exportIndex, int metaObjectRevision) -{ - m_exports[exportIndex].setMetaObjectRevision(metaObjectRevision); -} - -ScopeTree::Export::Export(QString package, QString type, const QTypeRevision &version, - int metaObjectRevision) : - m_package(std::move(package)), - m_type(std::move(type)), - m_version(version), - m_metaObjectRevision(metaObjectRevision) -{ -} - -bool ScopeTree::Export::isValid() const -{ - return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty(); -} diff --git a/tools/shared/scopetree.h b/tools/shared/scopetree.h deleted file mode 100644 index 1794b45373..0000000000 --- a/tools/shared/scopetree.h +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SCOPETREE_H -#define SCOPETREE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include "metatypes.h" - -#include <QtQml/private/qqmljssourcelocation_p.h> - -#include <QtCore/qset.h> -#include <QtCore/qhash.h> -#include <QtCore/qstring.h> -#include <QtCore/qversionnumber.h> - -#include <optional> - -enum class ScopeType -{ - JSFunctionScope, - JSLexicalScope, - QMLScope -}; - -struct JavaScriptIdentifier -{ - enum Kind { - Parameter, - FunctionScoped, - LexicalScoped, - Injected - }; - - Kind kind = FunctionScoped; - QQmlJS::SourceLocation location; -}; - -class ScopeTree -{ - Q_DISABLE_COPY_MOVE(ScopeTree) -public: - using Ptr = QSharedPointer<ScopeTree>; - using WeakPtr = QWeakPointer<ScopeTree>; - using ConstPtr = QSharedPointer<const ScopeTree>; - using WeakConstPtr = QWeakPointer<const ScopeTree>; - - enum class AccessSemantics { - Reference, - Value, - None - }; - - enum Flag { - Creatable = 0x1, - Composite = 0x2, - Singleton = 0x4 - }; - Q_DECLARE_FLAGS(Flags, Flag) - Q_FLAGS(Flags); - - class Export { - public: - Export() = default; - Export(QString package, QString type, const QTypeRevision &version, - int metaObjectRevision); - - bool isValid() const; - - int metaObjectRevision() const { return m_metaObjectRevision; } - void setMetaObjectRevision(int metaObjectRevision) - { - m_metaObjectRevision = metaObjectRevision; - } - - QString package() const { return m_package; } - QString type() const { return m_type; } - - private: - QString m_package; - QString m_type; - QTypeRevision m_version; - int m_metaObjectRevision = 0; - }; - - static ScopeTree::Ptr create(ScopeType type = ScopeType::QMLScope, - const ScopeTree::Ptr &parentScope = ScopeTree::Ptr()); - static ScopeTree::ConstPtr findCurrentQMLScope(const ScopeTree::ConstPtr &scope); - - ScopeTree::Ptr parentScope() const { return m_parentScope.toStrongRef(); } - - void insertJSIdentifier(const QString &name, const JavaScriptIdentifier &identifier); - - // inserts property as qml identifier as well as the corresponding - void insertPropertyIdentifier(const MetaProperty &prop); - - bool isIdInCurrentScope(const QString &id) const; - - ScopeType scopeType() const { return m_scopeType; } - - void addMethods(const QMultiHash<QString, MetaMethod> &methods) { m_methods.unite(methods); } - void addMethod(const MetaMethod &method) { m_methods.insert(method.methodName(), method); } - QMultiHash<QString, MetaMethod> methods() const { return m_methods; } - - void addEnum(const MetaEnum &fakeEnum) { m_enums.insert(fakeEnum.name(), fakeEnum); } - QHash<QString, MetaEnum> enums() const { return m_enums; } - - QString fileName() const { return m_fileName; } - void setFileName(const QString &file) { m_fileName = file; } - - // The name the type uses to refer to itself. Either C++ class name or base name of - // QML file. isComposite tells us if this is a C++ or a QML name. - QString internalName() const { return m_internalName; } - void setInternalName(const QString &internalName) { m_internalName = internalName; } - - void addExport(const QString &name, const QString &package, const QTypeRevision &version); - void setExportMetaObjectRevision(int exportIndex, int metaObjectRevision); - QList<Export> exports() const { return m_exports; } - - // If isComposite(), this is the QML/JS name of the prototype. Otherwise it's the - // relevant base class (in the hierarchy starting from QObject) of a C++ type. - void setBaseTypeName(const QString &baseTypeName) { m_baseTypeName = baseTypeName; } - QString baseTypeName() const { return m_baseTypeName; } - ScopeTree::ConstPtr baseType() const { return m_baseType; } - - void addProperty(const MetaProperty &prop) { m_properties.insert(prop.propertyName(), prop); } - QHash<QString, MetaProperty> properties() const { return m_properties; } - - QString defaultPropertyName() const { return m_defaultPropertyName; } - void setDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } - - QString attachedTypeName() const { return m_attachedTypeName; } - void setAttachedTypeName(const QString &name) { m_attachedTypeName = name; } - ScopeTree::ConstPtr attachedType() const { return m_attachedType; } - - bool isSingleton() const { return m_flags & Singleton; } - bool isCreatable() const { return m_flags & Creatable; } - bool isComposite() const { return m_flags & Composite; } - void setIsSingleton(bool v) { m_flags = v ? (m_flags | Singleton) : (m_flags & ~Singleton); } - void setIsCreatable(bool v) { m_flags = v ? (m_flags | Creatable) : (m_flags & ~Creatable); } - void setIsComposite(bool v) { m_flags = v ? (m_flags | Composite) : (m_flags & ~Composite); } - - void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; } - AccessSemantics accessSemantics() const { return m_semantics; } - - bool isIdInCurrentQMlScopes(const QString &id) const; - bool isIdInCurrentJSScopes(const QString &id) const; - bool isIdInjectedFromSignal(const QString &id) const; - - std::optional<JavaScriptIdentifier> findJSIdentifier(const QString &id) const; - - QVector<ScopeTree::Ptr> childScopes() const - { - return m_childScopes; - } - - void resolveTypes(const QHash<QString, ConstPtr> &contextualTypes); - -private: - ScopeTree(ScopeType type, const ScopeTree::Ptr &parentScope = ScopeTree::Ptr()); - - QHash<QString, JavaScriptIdentifier> m_jsIdentifiers; - - QMultiHash<QString, MetaMethod> m_methods; - QHash<QString, MetaProperty> m_properties; - QHash<QString, MetaEnum> m_enums; - - QVector<ScopeTree::Ptr> m_childScopes; - ScopeTree::WeakPtr m_parentScope; - - QString m_fileName; - QString m_internalName; - QString m_baseTypeName; - ScopeTree::WeakConstPtr m_baseType; - - ScopeType m_scopeType = ScopeType::QMLScope; - QList<Export> m_exports; - - QString m_defaultPropertyName; - QString m_attachedTypeName; - ScopeTree::WeakConstPtr m_attachedType; - - Flags m_flags; - AccessSemantics m_semantics = AccessSemantics::Reference; -}; - -#endif // SCOPETREE_H diff --git a/tools/shared/shared.pri b/tools/shared/shared.pri deleted file mode 100644 index 181cda3e8b..0000000000 --- a/tools/shared/shared.pri +++ /dev/null @@ -1,31 +0,0 @@ -INCLUDEPATH += $$PWD - -# The relevant tools need different bits and pieces. -# Furthermore, some of the classes require devtools, some not. - -RESOURCEFILEMAPPER_SOURCES = \ - $$PWD/resourcefilemapper.cpp - -RESOURCEFILEMAPPER_HEADERS = \ - $$PWD/resourcefilemapper.h - -METATYPEREADER_SOURCES = \ - $$PWD/importedmembersvisitor.cpp \ - $$PWD/qmljsimporter.cpp \ - $$PWD/qmljstypereader.cpp \ - $$PWD/scopetree.cpp \ - $$PWD/typedescriptionreader.cpp - -METATYPEREADER_HEADERS = \ - $$PWD/importedmembersvisitor.h \ - $$PWD/qmljsimporter.h \ - $$PWD/qmljstypereader.h \ - $$PWD/metatypes.h \ - $$PWD/scopetree.h \ - $$PWD/typedescriptionreader.h - -QMLSTREAMWRITER_SOURCES = \ - $$PWD/qmlstreamwriter.cpp - -QMLSTREAMWRITER_HEADERS = \ - $$PWD/qmlstreamwriter.h diff --git a/tools/shared/typedescriptionreader.cpp b/tools/shared/typedescriptionreader.cpp deleted file mode 100644 index f95e4453b3..0000000000 --- a/tools/shared/typedescriptionreader.cpp +++ /dev/null @@ -1,689 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typedescriptionreader.h" - -#include <QtQml/private/qqmljsparser_p.h> -#include <QtQml/private/qqmljslexer_p.h> -#include <QtQml/private/qqmljsengine_p.h> - -#include <QtCore/qdir.h> - -using namespace QQmlJS; -using namespace QQmlJS::AST; - -QString toString(const UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char('.')) -{ - QString result; - - for (const UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) { - if (iter != qualifiedId) - result += delimiter; - - result += iter->name; - } - - return result; -} - -bool TypeDescriptionReader::operator()( - QHash<QString, ScopeTree::Ptr> *objects, - QStringList *dependencies) -{ - Engine engine; - - Lexer lexer(&engine); - Parser parser(&engine); - - lexer.setCode(m_source, /*lineno = */ 1, /*qmlMode = */true); - - if (!parser.parse()) { - m_errorMessage = QString::fromLatin1("%1:%2: %3").arg( - QString::number(parser.errorLineNumber()), - QString::number(parser.errorColumnNumber()), - parser.errorMessage()); - return false; - } - - m_objects = objects; - m_dependencies = dependencies; - readDocument(parser.ast()); - - return m_errorMessage.isEmpty(); -} - -void TypeDescriptionReader::readDocument(UiProgram *ast) -{ - if (!ast) { - addError(SourceLocation(), tr("Could not parse document.")); - return; - } - - if (!ast->headers || ast->headers->next || !cast<UiImport *>(ast->headers->headerItem)) { - addError(SourceLocation(), tr("Expected a single import.")); - return; - } - - auto *import = cast<UiImport *>(ast->headers->headerItem); - if (toString(import->importUri) != QLatin1String("QtQuick.tooling")) { - addError(import->importToken, tr("Expected import of QtQuick.tooling.")); - return; - } - - if (!import->version) { - addError(import->firstSourceLocation(), tr("Import statement without version.")); - return; - } - - if (import->version->version.majorVersion() != 1) { - addError(import->version->firstSourceLocation(), - tr("Major version different from 1 not supported.")); - return; - } - - if (!ast->members || !ast->members->member || ast->members->next) { - addError(SourceLocation(), tr("Expected document to contain a single object definition.")); - return; - } - - auto *module = cast<UiObjectDefinition *>(ast->members->member); - if (!module) { - addError(SourceLocation(), tr("Expected document to contain a single object definition.")); - return; - } - - if (toString(module->qualifiedTypeNameId) != QLatin1String("Module")) { - addError(SourceLocation(), tr("Expected document to contain a Module {} member.")); - return; - } - - readModule(module); -} - -void TypeDescriptionReader::readModule(UiObjectDefinition *ast) -{ - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *component = cast<UiObjectDefinition *>(member); - - auto *script = cast<UiScriptBinding *>(member); - if (script && (toString(script->qualifiedId) == QStringLiteral("dependencies"))) { - readDependencies(script); - continue; - } - - QString typeName; - if (component) - typeName = toString(component->qualifiedTypeNameId); - - if (!component || typeName != QLatin1String("Component")) { - continue; - } - - if (typeName == QLatin1String("Component")) - readComponent(component); - } -} - -void TypeDescriptionReader::addError(const SourceLocation &loc, const QString &message) -{ - m_errorMessage += QString::fromLatin1("%1:%2:%3: %4\n").arg( - QDir::toNativeSeparators(m_fileName), - QString::number(loc.startLine), - QString::number(loc.startColumn), - message); -} - -void TypeDescriptionReader::addWarning(const SourceLocation &loc, const QString &message) -{ - m_warningMessage += QString::fromLatin1("%1:%2:%3: %4\n").arg( - QDir::toNativeSeparators(m_fileName), - QString::number(loc.startLine), - QString::number(loc.startColumn), - message); -} - -void TypeDescriptionReader::readDependencies(UiScriptBinding *ast) -{ - auto *stmt = cast<ExpressionStatement*>(ast->statement); - if (!stmt) { - addError(ast->statement->firstSourceLocation(), tr("Expected dependency definitions")); - return; - } - auto *exp = cast<ArrayPattern *>(stmt->expression); - if (!exp) { - addError(stmt->expression->firstSourceLocation(), tr("Expected dependency definitions")); - return; - } - for (PatternElementList *l = exp->elements; l; l = l->next) { - auto *str = cast<StringLiteral *>(l->element->initializer); - *m_dependencies << str->value.toString(); - } -} - -void TypeDescriptionReader::readComponent(UiObjectDefinition *ast) -{ - ScopeTree::Ptr scope = ScopeTree::create(); - - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *component = cast<UiObjectDefinition *>(member); - auto *script = cast<UiScriptBinding *>(member); - if (component) { - QString name = toString(component->qualifiedTypeNameId); - if (name == QLatin1String("Property")) - readProperty(component, scope); - else if (name == QLatin1String("Method") || name == QLatin1String("Signal")) - readSignalOrMethod(component, name == QLatin1String("Method"), scope); - else if (name == QLatin1String("Enum")) - readEnum(component, scope); - else - addWarning(component->firstSourceLocation(), - tr("Expected only Property, Method, Signal and Enum object definitions, " - "not \"%1\".").arg(name)); - } else if (script) { - QString name = toString(script->qualifiedId); - if (name == QLatin1String("file")) { - scope->setFileName(readStringBinding(script)); - } else if (name == QLatin1String("name")) { - scope->setInternalName(readStringBinding(script)); - } else if (name == QLatin1String("prototype")) { - scope->setBaseTypeName(readStringBinding(script)); - } else if (name == QLatin1String("defaultProperty")) { - scope->setDefaultPropertyName(readStringBinding(script)); - } else if (name == QLatin1String("exports")) { - readExports(script, scope); - } else if (name == QLatin1String("exportMetaObjectRevisions")) { - readMetaObjectRevisions(script, scope); - } else if (name == QLatin1String("attachedType")) { - scope->setAttachedTypeName(readStringBinding(script)); - } else if (name == QLatin1String("isSingleton")) { - scope->setIsSingleton(readBoolBinding(script)); - } else if (name == QLatin1String("isCreatable")) { - scope->setIsCreatable(readBoolBinding(script)); - } else if (name == QLatin1String("isComposite")) { - scope->setIsComposite(readBoolBinding(script)); - } else if (name == QLatin1String("accessSemantics")) { - const QString semantics = readStringBinding(script); - if (semantics == QLatin1String("reference")) { - scope->setAccessSemantics(ScopeTree::AccessSemantics::Reference); - } else if (semantics == QLatin1String("value")) { - scope->setAccessSemantics(ScopeTree::AccessSemantics::Value); - } else if (semantics == QLatin1String("none")) { - scope->setAccessSemantics(ScopeTree::AccessSemantics::None); - } else { - addWarning(script->firstSourceLocation(), - tr("Unknown access semantics \"%1\".").arg(semantics)); - } - } else { - addWarning(script->firstSourceLocation(), - tr("Expected only name, prototype, defaultProperty, attachedType, " - "exports, isSingleton, isCreatable, isComposite and " - "exportMetaObjectRevisions script bindings, not \"%1\".").arg(name)); - } - } else { - addWarning(member->firstSourceLocation(), - tr("Expected only script bindings and object definitions.")); - } - } - - if (scope->internalName().isEmpty()) { - addError(ast->firstSourceLocation(), tr("Component definition is missing a name binding.")); - return; - } - - m_objects->insert(scope->internalName(), scope); -} - -void TypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isMethod, - const ScopeTree::Ptr &scope) -{ - MetaMethod metaMethod; - // ### confusion between Method and Slot. Method should be removed. - if (isMethod) - metaMethod.setMethodType(MetaMethod::Slot); - else - metaMethod.setMethodType(MetaMethod::Signal); - - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *component = cast<UiObjectDefinition *>(member); - auto *script = cast<UiScriptBinding *>(member); - if (component) { - QString name = toString(component->qualifiedTypeNameId); - if (name == QLatin1String("Parameter")) { - readParameter(component, &metaMethod); - } else { - addWarning(component->firstSourceLocation(), - tr("Expected only Parameter object definitions.")); - } - } else if (script) { - QString name = toString(script->qualifiedId); - if (name == QLatin1String("name")) { - metaMethod.setMethodName(readStringBinding(script)); - } else if (name == QLatin1String("type")) { - metaMethod.setReturnTypeName(readStringBinding(script)); - } else if (name == QLatin1String("revision")) { - metaMethod.setRevision(readIntBinding(script)); - } else { - addWarning(script->firstSourceLocation(), - tr("Expected only name and type script bindings.")); - } - } else { - addWarning(member->firstSourceLocation(), - tr("Expected only script bindings and object definitions.")); - } - } - - if (metaMethod.methodName().isEmpty()) { - addError(ast->firstSourceLocation(), - tr("Method or signal is missing a name script binding.")); - return; - } - - scope->addMethod(metaMethod); -} - -void TypeDescriptionReader::readProperty(UiObjectDefinition *ast, const ScopeTree::Ptr &scope) -{ - QString name; - QString type; - bool isPointer = false; - bool isReadonly = false; - bool isList = false; - int revision = 0; - - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *script = cast<UiScriptBinding *>(member); - if (!script) { - addWarning(member->firstSourceLocation(), tr("Expected script binding.")); - continue; - } - - QString id = toString(script->qualifiedId); - if (id == QLatin1String("name")) { - name = readStringBinding(script); - } else if (id == QLatin1String("type")) { - type = readStringBinding(script); - } else if (id == QLatin1String("isPointer")) { - isPointer = readBoolBinding(script); - } else if (id == QLatin1String("isReadonly")) { - isReadonly = readBoolBinding(script); - } else if (id == QLatin1String("isList")) { - isList = readBoolBinding(script); - } else if (id == QLatin1String("revision")) { - revision = readIntBinding(script); - } else { - addWarning(script->firstSourceLocation(), - tr("Expected only type, name, revision, isPointer, isReadonly and" - " isList script bindings.")); - } - } - - if (name.isEmpty() || type.isEmpty()) { - addError(ast->firstSourceLocation(), - tr("Property object is missing a name or type script binding.")); - return; - } - - scope->addProperty(MetaProperty(name, type, isList, !isReadonly, isPointer, false, revision)); -} - -void TypeDescriptionReader::readEnum(UiObjectDefinition *ast, const ScopeTree::Ptr &scope) -{ - MetaEnum metaEnum; - - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *script = cast<UiScriptBinding *>(member); - if (!script) { - addWarning(member->firstSourceLocation(), tr("Expected script binding.")); - continue; - } - - QString name = toString(script->qualifiedId); - if (name == QLatin1String("name")) { - metaEnum.setName(readStringBinding(script)); - } else if (name == QLatin1String("alias")) { - metaEnum.setAlias(readStringBinding(script)); - } else if (name == QLatin1String("isFlag")) { - metaEnum.setIsFlag(readBoolBinding(script)); - } else if (name == QLatin1String("values")) { - readEnumValues(script, &metaEnum); - } else { - addWarning(script->firstSourceLocation(), - tr("Expected only name and values script bindings.")); - } - } - - scope->addEnum(metaEnum); -} - -void TypeDescriptionReader::readParameter(UiObjectDefinition *ast, MetaMethod *metaMethod) -{ - QString name; - QString type; - - for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { - UiObjectMember *member = it->member; - auto *script = cast<UiScriptBinding *>(member); - if (!script) { - addWarning(member->firstSourceLocation(), tr("Expected script binding.")); - continue; - } - - const QString id = toString(script->qualifiedId); - if (id == QLatin1String("name")) { - name = readStringBinding(script); - } else if (id == QLatin1String("type")) { - type = readStringBinding(script); - } else if (id == QLatin1String("isPointer")) { - // ### unhandled - } else if (id == QLatin1String("isReadonly")) { - // ### unhandled - } else if (id == QLatin1String("isList")) { - // ### unhandled - } else { - addWarning(script->firstSourceLocation(), - tr("Expected only name and type script bindings.")); - } - } - - metaMethod->addParameter(name, type); -} - -QString TypeDescriptionReader::readStringBinding(UiScriptBinding *ast) -{ - Q_ASSERT(ast); - - if (!ast->statement) { - addError(ast->colonToken, tr("Expected string after colon.")); - return QString(); - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), tr("Expected string after colon.")); - return QString(); - } - - auto *stringLit = cast<StringLiteral *>(expStmt->expression); - if (!stringLit) { - addError(expStmt->firstSourceLocation(), tr("Expected string after colon.")); - return QString(); - } - - return stringLit->value.toString(); -} - -bool TypeDescriptionReader::readBoolBinding(UiScriptBinding *ast) -{ - Q_ASSERT(ast); - - if (!ast->statement) { - addError(ast->colonToken, tr("Expected boolean after colon.")); - return false; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), tr("Expected boolean after colon.")); - return false; - } - - auto *trueLit = cast<TrueLiteral *>(expStmt->expression); - auto *falseLit = cast<FalseLiteral *>(expStmt->expression); - if (!trueLit && !falseLit) { - addError(expStmt->firstSourceLocation(), tr("Expected true or false after colon.")); - return false; - } - - return trueLit; -} - -double TypeDescriptionReader::readNumericBinding(UiScriptBinding *ast) -{ - Q_ASSERT(ast); - - if (!ast->statement) { - addError(ast->colonToken, tr("Expected numeric literal after colon.")); - return 0; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), - tr("Expected numeric literal after colon.")); - return 0; - } - - auto *numericLit = cast<NumericLiteral *>(expStmt->expression); - if (!numericLit) { - addError(expStmt->firstSourceLocation(), tr("Expected numeric literal after colon.")); - return 0; - } - - return numericLit->value; -} - -static QTypeRevision parseVersion(const QString &versionString) -{ - const int dotIdx = versionString.indexOf(QLatin1Char('.')); - if (dotIdx == -1) - return QTypeRevision(); - bool ok = false; - const int maybeMajor = QStringView{versionString}.left(dotIdx).toInt(&ok); - if (!ok) - return QTypeRevision(); - const int maybeMinor = QStringView{versionString}.mid(dotIdx + 1).toInt(&ok); - if (!ok) - return QTypeRevision(); - return QTypeRevision::fromVersion(maybeMajor, maybeMinor); -} - -QTypeRevision TypeDescriptionReader::readNumericVersionBinding(UiScriptBinding *ast) -{ - QTypeRevision invalidVersion; - - if (!ast || !ast->statement) { - addError((ast ? ast->colonToken : SourceLocation()), - tr("Expected numeric literal after colon.")); - return invalidVersion; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), - tr("Expected numeric literal after colon.")); - return invalidVersion; - } - - auto *numericLit = cast<NumericLiteral *>(expStmt->expression); - if (!numericLit) { - addError(expStmt->firstSourceLocation(), tr("Expected numeric literal after colon.")); - return invalidVersion; - } - - return parseVersion(m_source.mid(numericLit->literalToken.begin(), - numericLit->literalToken.length)); -} - -int TypeDescriptionReader::readIntBinding(UiScriptBinding *ast) -{ - double v = readNumericBinding(ast); - int i = static_cast<int>(v); - - if (i != v) { - addError(ast->firstSourceLocation(), tr("Expected integer after colon.")); - return 0; - } - - return i; -} - -void TypeDescriptionReader::readExports(UiScriptBinding *ast, const ScopeTree::Ptr &scope) -{ - Q_ASSERT(ast); - - if (!ast->statement) { - addError(ast->colonToken, tr("Expected array of strings after colon.")); - return; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), - tr("Expected array of strings after colon.")); - return; - } - - auto *arrayLit = cast<ArrayPattern *>(expStmt->expression); - if (!arrayLit) { - addError(expStmt->firstSourceLocation(), tr("Expected array of strings after colon.")); - return; - } - - for (PatternElementList *it = arrayLit->elements; it; it = it->next) { - auto *stringLit = cast<StringLiteral *>(it->element->initializer); - if (!stringLit) { - addError(arrayLit->firstSourceLocation(), - tr("Expected array literal with only string literal members.")); - return; - } - QString exp = stringLit->value.toString(); - int slashIdx = exp.indexOf(QLatin1Char('/')); - int spaceIdx = exp.indexOf(QLatin1Char(' ')); - const QTypeRevision version = parseVersion(exp.mid(spaceIdx + 1)); - - if (spaceIdx == -1 || !version.isValid()) { - addError(stringLit->firstSourceLocation(), - tr("Expected string literal to contain 'Package/Name major.minor' " - "or 'Name major.minor'.")); - continue; - } - QString package; - if (slashIdx != -1) - package = exp.left(slashIdx); - QString name = exp.mid(slashIdx + 1, spaceIdx - (slashIdx+1)); - - // ### relocatable exports where package is empty? - scope->addExport(name, package, version); - } -} - -void TypeDescriptionReader::readMetaObjectRevisions(UiScriptBinding *ast, - const ScopeTree::Ptr &scope) -{ - Q_ASSERT(ast); - - if (!ast->statement) { - addError(ast->colonToken, tr("Expected array of numbers after colon.")); - return; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), - tr("Expected array of numbers after colon.")); - return; - } - - auto *arrayLit = cast<ArrayPattern *>(expStmt->expression); - if (!arrayLit) { - addError(expStmt->firstSourceLocation(), tr("Expected array of numbers after colon.")); - return; - } - - int exportIndex = 0; - const int exportCount = scope->exports().size(); - for (PatternElementList *it = arrayLit->elements; it; it = it->next, ++exportIndex) { - auto *numberLit = cast<NumericLiteral *>(it->element->initializer); - if (!numberLit) { - addError(arrayLit->firstSourceLocation(), - tr("Expected array literal with only number literal members.")); - return; - } - - if (exportIndex >= exportCount) { - addError(numberLit->firstSourceLocation(), - tr("Meta object revision without matching export.")); - return; - } - - const double v = numberLit->value; - const int metaObjectRevision = static_cast<int>(v); - if (metaObjectRevision != v) { - addError(numberLit->firstSourceLocation(), tr("Expected integer.")); - return; - } - - scope->setExportMetaObjectRevision(exportIndex, metaObjectRevision); - } -} - -void TypeDescriptionReader::readEnumValues(UiScriptBinding *ast, MetaEnum *metaEnum) -{ - if (!ast) - return; - if (!ast->statement) { - addError(ast->colonToken, tr("Expected object literal after colon.")); - return; - } - - auto *expStmt = cast<ExpressionStatement *>(ast->statement); - if (!expStmt) { - addError(ast->statement->firstSourceLocation(), tr("Expected expression after colon.")); - return; - } - - if (auto *objectLit = cast<ObjectPattern *>(expStmt->expression)) { - for (PatternPropertyList *it = objectLit->properties; it; it = it->next) { - if (PatternProperty *assignement = it->property) { - if (auto *name = cast<StringLiteralPropertyName *>(assignement->name)) { - metaEnum->addKey(name->id.toString()); - continue; - } - } - addError(it->firstSourceLocation(), tr("Expected strings as enum keys.")); - } - } else if (auto *arrayLit = cast<ArrayPattern *>(expStmt->expression)) { - for (PatternElementList *it = arrayLit->elements; it; it = it->next) { - if (PatternElement *element = it->element) { - if (auto *name = cast<StringLiteral *>(element->initializer)) { - metaEnum->addKey(name->value.toString()); - continue; - } - } - addError(it->firstSourceLocation(), tr("Expected strings as enum keys.")); - } - } else { - addError(ast->statement->firstSourceLocation(), - tr("Expected either array or object literal as enum definition.")); - } -} diff --git a/tools/shared/typedescriptionreader.h b/tools/shared/typedescriptionreader.h deleted file mode 100644 index 8395f09bc4..0000000000 --- a/tools/shared/typedescriptionreader.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPEDESCRIPTIONREADER_H -#define TYPEDESCRIPTIONREADER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include "scopetree.h" - -#include <QtQml/private/qqmljsastfwd_p.h> - -// for Q_DECLARE_TR_FUNCTIONS -#include <QtCore/qcoreapplication.h> - -class TypeDescriptionReader -{ - Q_DECLARE_TR_FUNCTIONS(TypeDescriptionReader) -public: - TypeDescriptionReader() = default; - explicit TypeDescriptionReader(QString fileName, QString data) - : m_fileName(std::move(fileName)), m_source(std::move(data)) {} - - bool operator()( - QHash<QString, ScopeTree::Ptr> *objects, - QStringList *dependencies); - - QString errorMessage() const { return m_errorMessage; } - QString warningMessage() const { return m_warningMessage; } - -private: - void readDocument(QQmlJS::AST::UiProgram *ast); - void readModule(QQmlJS::AST::UiObjectDefinition *ast); - void readDependencies(QQmlJS::AST::UiScriptBinding *ast); - void readComponent(QQmlJS::AST::UiObjectDefinition *ast); - void readSignalOrMethod(QQmlJS::AST::UiObjectDefinition *ast, bool isMethod, - const ScopeTree::Ptr &scope); - void readProperty(QQmlJS::AST::UiObjectDefinition *ast, const ScopeTree::Ptr &scope); - void readEnum(QQmlJS::AST::UiObjectDefinition *ast, const ScopeTree::Ptr &scope); - void readParameter(QQmlJS::AST::UiObjectDefinition *ast, MetaMethod *metaMethod); - - QString readStringBinding(QQmlJS::AST::UiScriptBinding *ast); - bool readBoolBinding(QQmlJS::AST::UiScriptBinding *ast); - double readNumericBinding(QQmlJS::AST::UiScriptBinding *ast); - QTypeRevision readNumericVersionBinding(QQmlJS::AST::UiScriptBinding *ast); - int readIntBinding(QQmlJS::AST::UiScriptBinding *ast); - void readExports(QQmlJS::AST::UiScriptBinding *ast, const ScopeTree::Ptr &scope); - void readMetaObjectRevisions(QQmlJS::AST::UiScriptBinding *ast, const ScopeTree::Ptr &scope); - void readEnumValues(QQmlJS::AST::UiScriptBinding *ast, MetaEnum *metaEnum); - - void addError(const QQmlJS::SourceLocation &loc, const QString &message); - void addWarning(const QQmlJS::SourceLocation &loc, const QString &message); - - QString m_fileName; - QString m_source; - QString m_errorMessage; - QString m_warningMessage; - QHash<QString, ScopeTree::Ptr> *m_objects = nullptr; - QStringList *m_dependencies = nullptr; -}; - -#endif // TYPEDESCRIPTIONREADER_H |