aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/CMakeLists.txt1
-rw-r--r--src/qmlcompiler/qdeferredpointer_p.h181
-rw-r--r--src/qmlcompiler/qmlcompiler.pro1
-rw-r--r--src/qmlcompiler/qqmljsimporter.cpp26
-rw-r--r--src/qmlcompiler/qqmljsimporter_p.h2
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp2
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp25
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h41
-rw-r--r--tools/qmllint/checkidentifiers.cpp6
-rw-r--r--tools/qmllint/findwarnings.cpp6
10 files changed, 259 insertions, 32 deletions
diff --git a/src/qmlcompiler/CMakeLists.txt b/src/qmlcompiler/CMakeLists.txt
index 0eab79259f..d0e9be9418 100644
--- a/src/qmlcompiler/CMakeLists.txt
+++ b/src/qmlcompiler/CMakeLists.txt
@@ -8,6 +8,7 @@ qt_internal_add_module(QmlCompiler
STATIC
INTERNAL_MODULE
SOURCES
+ qdeferredpointer_p.h
qqmljsimporter.cpp qqmljsimporter_p.h
qqmljsimportvisitor.cpp qqmljsimportvisitor_p.h
qqmljsmetatypes_p.h
diff --git a/src/qmlcompiler/qdeferredpointer_p.h b/src/qmlcompiler/qdeferredpointer_p.h
new file mode 100644
index 0000000000..07875013fa
--- /dev/null
+++ b/src/qmlcompiler/qdeferredpointer_p.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** 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 QDEFERREDPOINTER_P_H
+#define QDEFERREDPOINTER_P_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/qglobal.h>
+#include <QtCore/qsharedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+template<typename T>
+class QDeferredFactory
+{
+public:
+ T create() const;
+ bool isValid() const;
+ void clear();
+};
+
+template<typename T>
+class QDeferredWeakPointer;
+
+template<typename T>
+class QDeferredSharedPointer
+{
+public:
+ using Factory = QDeferredFactory<std::remove_const_t<T>>;
+
+ QDeferredSharedPointer() = default;
+
+ QDeferredSharedPointer(QSharedPointer<T> data)
+ : m_data(data)
+ {}
+
+ QDeferredSharedPointer(QWeakPointer<T> data)
+ : m_data(data)
+ {}
+
+ QDeferredSharedPointer(QSharedPointer<T> data, QSharedPointer<Factory> factory)
+ : m_data(data), m_factory(factory)
+ {}
+
+ operator QSharedPointer<T>() const
+ {
+ if (m_factory && m_factory->isValid()) {
+ const_cast<std::remove_const_t<T> &>(*m_data) = m_factory->create();
+ m_factory->clear();
+ }
+ return m_data;
+ }
+
+ operator QDeferredSharedPointer<const T>() const { return { m_data, m_factory }; }
+
+ T &operator*() const { return QSharedPointer<T>(*this).operator*(); }
+ T *operator->() const { return QSharedPointer<T>(*this).operator->(); }
+
+ bool isNull() const { return m_data.isNull(); }
+ explicit operator bool() const noexcept { return !isNull(); }
+ bool operator !() const noexcept { return isNull(); }
+
+ T *data() const { return QSharedPointer<T>(*this).data(); }
+
+ friend qsizetype qHash(const QDeferredSharedPointer &ptr, qsizetype seed = 0)
+ {
+ return qHashMulti(seed, ptr.m_factory, ptr.m_data);
+ }
+
+ friend bool operator==(const QDeferredSharedPointer &a, const QDeferredSharedPointer &b)
+ {
+ return a.m_factory == b.m_factory && a.m_data == b.m_data;
+ }
+
+private:
+ friend class QDeferredWeakPointer<T>;
+
+ QSharedPointer<T> m_data;
+ QSharedPointer<Factory> m_factory;
+};
+
+template<typename T>
+class QDeferredWeakPointer
+{
+public:
+ using Factory = QDeferredFactory<std::remove_const_t<T>>;
+
+ QDeferredWeakPointer() = default;
+
+ QDeferredWeakPointer(const QDeferredSharedPointer<T> &strong)
+ : m_data(strong.m_data), m_factory(strong.m_factory)
+ {
+ }
+
+ QDeferredWeakPointer(QWeakPointer<T> data, QWeakPointer<Factory> factory)
+ : m_data(data), m_factory(factory)
+ {}
+
+ operator QWeakPointer<T>() const
+ {
+ if (m_factory) {
+ auto factory = m_factory.toStrongRef();
+ if (factory->isValid()) {
+ const_cast<std::remove_const_t<T> &>(*(m_data.toStrongRef())) = factory->create();
+ factory->clear();
+ }
+ }
+ return m_data;
+ }
+
+ operator QDeferredSharedPointer<T>() const
+ {
+ return QDeferredSharedPointer<T>(m_data.toStrongRef(), m_factory.toStrongRef());
+ }
+
+ operator QDeferredWeakPointer<const T>() const { return {m_data, m_factory}; }
+
+ QSharedPointer<T> toStrongRef() const
+ {
+ return QWeakPointer<T>(*this).toStrongRef();
+ }
+
+ bool isNull() const { return m_data.isNull(); }
+ explicit operator bool() const noexcept { return !isNull(); }
+ bool operator !() const noexcept { return isNull(); }
+
+ T *data() const { return QWeakPointer<T>(*this).data(); }
+
+ friend qsizetype qHash(const QDeferredWeakPointer &ptr, qsizetype seed = 0)
+ {
+ return qHashMulti(seed, ptr.m_factory, ptr.m_data);
+ }
+
+ friend bool operator==(const QDeferredWeakPointer &a, const QDeferredWeakPointer &b)
+ {
+ return a.m_factory == b.m_factory && a.m_data == b.m_data;
+ }
+
+private:
+ QWeakPointer<T> m_data;
+ QWeakPointer<Factory> m_factory;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QDEFERREDPOINTER_P_H
diff --git a/src/qmlcompiler/qmlcompiler.pro b/src/qmlcompiler/qmlcompiler.pro
index 111d27932a..37a1b44b9c 100644
--- a/src/qmlcompiler/qmlcompiler.pro
+++ b/src/qmlcompiler/qmlcompiler.pro
@@ -13,6 +13,7 @@ SOURCES = \
qqmljsstreamwriter.cpp
HEADERS = \
+ qdeferredpointer_p.h \
qqmljsresourcefilemapper_p.h \
qqmljsimportvisitor_p.h \
qqmljsimporter_p.h \
diff --git a/src/qmlcompiler/qqmljsimporter.cpp b/src/qmlcompiler/qqmljsimporter.cpp
index 717b559c44..0f334eabd3 100644
--- a/src/qmlcompiler/qqmljsimporter.cpp
+++ b/src/qmlcompiler/qqmljsimporter.cpp
@@ -303,21 +303,11 @@ QQmlJSScope::Ptr QQmlJSImporter::localFile2ScopeTree(const QString &filePath)
if (seen != m_importedFiles.end())
return *seen;
- QQmlJSTypeReader typeReader(filePath);
- QQmlJSScope::Ptr result = typeReader();
- m_importedFiles.insert(filePath, result);
-
- m_warnings.append(typeReader.errors());
-
- AvailableTypes types;
- types.qmlNames.insert(importDirectory(QFileInfo(filePath).canonicalPath()));
-
- const auto imports = typeReader.imports();
- for (const auto &import : imports)
- importHelper(import.module, &types, import.prefix, import.version);
-
- result->resolveTypes(types.qmlNames);
- return result;
+ return *m_importedFiles.insert(filePath, {
+ QQmlJSScope::create(),
+ QSharedPointer<QDeferredFactory<QQmlJSScope>>(
+ new QDeferredFactory<QQmlJSScope>(this, filePath))
+ });
}
QQmlJSScope::Ptr QQmlJSImporter::importFile(const QString &file)
@@ -339,9 +329,9 @@ QQmlJSImporter::ImportedTypes QQmlJSImporter::importDirectory(
it.next();
if (!it.fileName().front().isUpper())
continue; // Non-uppercase names cannot be imported anyway.
- QQmlJSScope::Ptr scope(localFile2ScopeTree(it.filePath()));
- if (!scope->internalName().isEmpty())
- qmlNames.insert(prefixedName(prefix, scope->internalName()), scope);
+
+ qmlNames.insert(prefixedName(prefix, QFileInfo(it.filePath()).baseName()),
+ localFile2ScopeTree(it.filePath()));
}
return qmlNames;
diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h
index 1acd2a5ed1..3356997fd3 100644
--- a/src/qmlcompiler/qqmljsimporter_p.h
+++ b/src/qmlcompiler/qqmljsimporter_p.h
@@ -69,6 +69,8 @@ public:
}
private:
+ friend class QDeferredFactory<QQmlJSScope>;
+
struct AvailableTypes
{
// C++ names used in qmltypes files for non-composite types
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 0b79339b62..0cb5632d40 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -43,7 +43,7 @@ QQmlJSScope::Ptr QQmlJSImportVisitor::result(const QString &scopeName) const
if (property.isAlias()) {
const auto it = m_objects.find(property.typeName());
if (it != m_objects.end())
- property.setType(*it);
+ property.setType(QQmlJSScope::ConstPtr(*it));
result->addProperty(property);
} else {
result->addProperty(property);
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp
index b2b9443fc6..e515431758 100644
--- a/src/qmlcompiler/qqmljsscope.cpp
+++ b/src/qmlcompiler/qqmljsscope.cpp
@@ -27,9 +27,12 @@
****************************************************************************/
#include "qqmljsscope_p.h"
+#include "qqmljstypereader_p.h"
+#include "qqmljsimporter_p.h"
#include <QtCore/qqueue.h>
#include <QtCore/qsharedpointer.h>
+#include <QtCore/qfileinfo.h>
#include <algorithm>
@@ -40,7 +43,7 @@ QQmlJSScope::QQmlJSScope(ScopeType type, const QQmlJSScope::Ptr &parentScope)
QQmlJSScope::Ptr QQmlJSScope::create(ScopeType type, const QQmlJSScope::Ptr &parentScope)
{
- QQmlJSScope::Ptr childScope(new QQmlJSScope{type, parentScope});
+ QSharedPointer<QQmlJSScope> childScope(new QQmlJSScope{type, parentScope});
if (parentScope) {
Q_ASSERT(type != QQmlJSScope::QMLScope
|| !parentScope->m_parentScope
@@ -142,7 +145,7 @@ void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &cont
for (auto it = m_methods.begin(), end = m_methods.end(); it != end; ++it) {
it->setReturnType(findType(it->returnTypeName()));
const auto paramNames = it->parameterTypeNames();
- QList<QQmlJSScope::ConstPtr> paramTypes;
+ QList<QSharedPointer<const QQmlJSScope>> paramTypes;
for (const QString &paramName: paramNames)
paramTypes.append(findType(paramName));
@@ -183,4 +186,22 @@ bool QQmlJSScope::Export::isValid() const
return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty();
}
+QQmlJSScope QDeferredFactory<QQmlJSScope>::create() const
+{
+ QQmlJSTypeReader typeReader(m_filePath);
+ QQmlJSScope::Ptr result = typeReader();
+
+ m_importer->m_warnings.append(typeReader.errors());
+
+ QQmlJSImporter::AvailableTypes types;
+ types.qmlNames.insert(m_importer->importDirectory(QFileInfo(m_filePath).canonicalPath()));
+
+ const auto imports = typeReader.imports();
+ for (const auto &import : imports)
+ m_importer->importHelper(import.module, &types, import.prefix, import.version);
+
+ result->resolveTypes(types.qmlNames);
+ return std::move(*result);
+}
+
QT_END_NAMESPACE
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index 4cf1d4cd6c..df7aad840d 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -40,6 +40,7 @@
// We mean it.
#include "qqmljsmetatypes_p.h"
+#include "qdeferredpointer_p.h"
#include <QtQml/private/qqmljssourcelocation_p.h>
@@ -52,15 +53,45 @@
QT_BEGIN_NAMESPACE
+class QQmlJSImporter;
+class QQmlJSScope;
+
+template<>
+class QDeferredFactory<QQmlJSScope>
+{
+public:
+ QDeferredFactory(QQmlJSImporter *importer, const QString &filePath) :
+ m_filePath(filePath), m_importer(importer)
+ {}
+
+ QQmlJSScope create() const;
+
+ bool isValid() const
+ {
+ return !m_filePath.isEmpty() && m_importer != nullptr;
+ }
+
+ void clear() {
+ m_filePath.clear();
+ m_importer = nullptr;
+ }
+
+private:
+ QString m_filePath;
+ QQmlJSImporter *m_importer = nullptr;
+};
class QQmlJSScope
{
- Q_DISABLE_COPY_MOVE(QQmlJSScope)
+ Q_DISABLE_COPY(QQmlJSScope)
public:
- using Ptr = QSharedPointer<QQmlJSScope>;
- using WeakPtr = QWeakPointer<QQmlJSScope>;
- using ConstPtr = QSharedPointer<const QQmlJSScope>;
- using WeakConstPtr = QWeakPointer<const QQmlJSScope>;
+ QQmlJSScope(QQmlJSScope &&) = default;
+ QQmlJSScope &operator=(QQmlJSScope &&) = default;
+
+ using Ptr = QDeferredSharedPointer<QQmlJSScope>;
+ using WeakPtr = QDeferredWeakPointer<QQmlJSScope>;
+ using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>;
+ using WeakConstPtr = QDeferredWeakPointer<const QQmlJSScope>;
enum ScopeType
{
diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp
index 6fa26b86ba..b7d331521c 100644
--- a/tools/qmllint/checkidentifiers.cpp
+++ b/tools/qmllint/checkidentifiers.cpp
@@ -82,7 +82,7 @@ void CheckIdentifiers::printContext(
static bool walkViaParentAndAttachedScopes(QQmlJSScope::ConstPtr rootType,
std::function<bool(QQmlJSScope::ConstPtr)> visit)
{
- if (rootType == nullptr)
+ if (rootType.isNull())
return false;
std::stack<QQmlJSScope::ConstPtr> stack;
stack.push(rootType);
@@ -186,7 +186,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<FieldMember> &members,
if (it == m_types.end()) {
detectedRestrictiveKind = typeName;
detectedRestrictiveName = access.m_name;
- scope = nullptr;
+ scope = QQmlJSScope::ConstPtr();
} else {
scope = *it;
}
@@ -304,7 +304,7 @@ bool CheckIdentifiers::operator()(
auto it = qmlIDs.find(memberAccessBase.m_name);
if (it != qmlIDs.end()) {
- if (*it != nullptr) {
+ if (!it->isNull()) {
if (!checkMemberAccess(memberAccessChain, *it))
noUnqualifiedIdentifier = false;
continue;
diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp
index 62dce68bb7..962ccaa1c6 100644
--- a/tools/qmllint/findwarnings.cpp
+++ b/tools/qmllint/findwarnings.cpp
@@ -473,7 +473,7 @@ bool FindWarningVisitor::check()
// now that all ids are known, revisit any Connections whose target were perviously unknown
for (auto const &outstandingConnection: m_outstandingConnections) {
auto targetScope = m_qmlid2scope[outstandingConnection.targetName];
- if (outstandingConnection.scope && targetScope != nullptr)
+ if (outstandingConnection.scope && !targetScope.isNull())
outstandingConnection.scope->addMethods(targetScope->methods());
QScopedValueRollback<QQmlJSScope::Ptr> rollback(m_currentScope, outstandingConnection.scope);
outstandingConnection.uiod->initializer->accept(this);
@@ -632,7 +632,7 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob)
void FindWarningVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob)
{
- const auto childScope = m_currentScope;
+ const QQmlJSScope::ConstPtr childScope = m_currentScope;
leaveEnvironment();
QQmlJSMetaProperty property(uiob->qualifiedId->name.toString(),
uiob->qualifiedTypeNameId->name.toString(),
@@ -736,7 +736,7 @@ void FindWarningVisitor::endVisit(QQmlJS::AST::UiObjectDefinition *)
const auto it = properties.find(QStringLiteral("parent"));
if (it != properties.end()) {
auto property = *it;
- property.setType(m_currentScope);
+ property.setType(QQmlJSScope::ConstPtr(m_currentScope));
childScope->addProperty(property);
}
}