From eb5aa8d9c18535ecd0aacc42fe3af954faf01c04 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 31 Mar 2020 15:46:20 +0200 Subject: qmllint: Consistently use shared pointers for ScopeTree ScopeTree keeps a weak pointer to its parent scope and strong shared pointers to its children. Avoid passing bare pointers around, so that we cannot create multiple shared pointers independently from the same bare pointer. Change-Id: Id0faece550b1878363004d843a8fa5c1164794ae Reviewed-by: Fabian Kosmale --- tools/qmllint/checkidentifiers.cpp | 37 ++++++++-------- tools/qmllint/checkidentifiers.h | 6 +-- tools/qmllint/findunqualified.cpp | 43 +++++++++---------- tools/qmllint/findunqualified.h | 12 +++--- tools/qmllint/importedmembersvisitor.cpp | 8 ++-- tools/qmllint/importedmembersvisitor.h | 2 +- tools/shared/metatypes.h | 7 ++-- tools/shared/scopetree.cpp | 72 +++++++++++++++++++------------- tools/shared/scopetree.h | 17 ++++---- tools/shared/typedescriptionreader.cpp | 2 +- 10 files changed, 114 insertions(+), 92 deletions(-) diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp index 6b9e48ed38..20b2ba6214 100644 --- a/tools/qmllint/checkidentifiers.cpp +++ b/tools/qmllint/checkidentifiers.cpp @@ -83,14 +83,15 @@ void CheckIdentifiers::printContext(const QQmlJS::SourceLocation &location) cons } bool CheckIdentifiers::checkMemberAccess(const QVector &members, - const ScopeTree *scope) const + const ScopeTree::ConstPtr &outerScope) const { QStringList expectedNext; QString detectedRestrictiveName; QString detectedRestrictiveKind; + ScopeTree::ConstPtr scope = outerScope; for (const ScopeTree::FieldMember &access : members) { - if (scope == nullptr) { + if (scope.isNull()) { writeWarning(m_colorOut); m_colorOut->write( QString::fromLatin1("Type \"%1\" of base \"%2\" not found when accessing member \"%3\" at %4:%5.\n") @@ -142,7 +143,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector & continue; } - if (const ScopeTree *type = scopeIt->type()) { + if (const ScopeTree::ConstPtr type = scopeIt->type()) { if (access.m_parentType.isEmpty()) { scope = type; continue; @@ -158,7 +159,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector & detectedRestrictiveName = access.m_name; scope = nullptr; } else { - scope = it->get(); + scope = *it; } continue; } @@ -189,10 +190,10 @@ bool CheckIdentifiers::checkMemberAccess(const QVector & const auto typeProperties = type->properties(); const auto typeIt = typeProperties.find(access.m_name); if (typeIt != typeProperties.end()) { - const ScopeTree *propType = access.m_parentType.isEmpty() + const ScopeTree::ConstPtr propType = access.m_parentType.isEmpty() ? typeIt->type() - : m_types.value(access.m_parentType).get(); - scope = propType ? propType : m_types.value(typeIt->typeName()).get(); + : m_types.value(access.m_parentType); + scope = propType ? propType : m_types.value(typeIt->typeName()); typeFound = true; break; } @@ -217,7 +218,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector & if (it != m_types.end() && !(*it)->attachedTypeName().isEmpty()) { const auto attached = m_types.find((*it)->attachedTypeName()); if (attached != m_types.end()) { - scope = attached->get(); + scope = *attached; continue; } } @@ -237,16 +238,16 @@ bool CheckIdentifiers::checkMemberAccess(const QVector & return true; } -bool CheckIdentifiers::operator()(const QHash &qmlIDs, - const ScopeTree *root, const QString &rootId) const +bool CheckIdentifiers::operator()(const QHash &qmlIDs, + const ScopeTree::ConstPtr &root, const QString &rootId) const { bool noUnqualifiedIdentifier = true; // revisit all scopes - QQueue workQueue; + QQueue workQueue; workQueue.enqueue(root); while (!workQueue.empty()) { - const ScopeTree *currentScope = workQueue.dequeue(); + const ScopeTree::ConstPtr currentScope = workQueue.dequeue(); const auto unmatchedSignalHandlers = currentScope->unmatchedSignalHandlers(); for (const auto &handler : unmatchedSignalHandlers) { writeWarning(m_colorOut); @@ -281,7 +282,7 @@ bool CheckIdentifiers::operator()(const QHash &qmlID const auto typeIt = m_types.find(qualified); if (typeIt != m_types.end()) { memberAccessChain.takeFirst(); - if (!checkMemberAccess(memberAccessChain, typeIt->get())) + if (!checkMemberAccess(memberAccessChain, *typeIt)) noUnqualifiedIdentifier = false; continue; } @@ -289,7 +290,7 @@ bool CheckIdentifiers::operator()(const QHash &qmlID } } - auto qmlScope = currentScope->currentQMLScope(); + auto qmlScope = ScopeTree::findCurrentQMLScope(currentScope); if (qmlScope->methods().contains(memberAccessBase.m_name)) { // a property of a JavaScript function continue; @@ -323,7 +324,7 @@ bool CheckIdentifiers::operator()(const QHash &qmlID const auto typeIt = m_types.find(memberAccessBase.m_name); if (typeIt != m_types.end()) { - if (!checkMemberAccess(memberAccessChain, typeIt->get())) + if (!checkMemberAccess(memberAccessChain, *typeIt)) noUnqualifiedIdentifier = false; continue; } @@ -355,8 +356,8 @@ bool CheckIdentifiers::operator()(const QHash &qmlID m_colorOut->write(issueLocationWithContext.issueText().toString(), Normal); m_colorOut->write(issueLocationWithContext.afterText() + QLatin1Char('\n'), Normal); } else if (currentScope->isIdInjectedFromSignal(memberAccessBase.m_name)) { - auto methodUsages = currentScope->currentQMLScope()->injectedSignalIdentifiers() - .values(memberAccessBase.m_name); + auto methodUsages = ScopeTree::findCurrentQMLScope(currentScope) + ->injectedSignalIdentifiers().values(memberAccessBase.m_name); auto location = memberAccessBase.m_location; // sort the list of signal handlers by their occurrence in the source code // then, we select the first one whose location is after the unqualified id @@ -402,7 +403,7 @@ bool CheckIdentifiers::operator()(const QHash &qmlID } const auto childScopes = currentScope->childScopes(); for (auto const &childScope : childScopes) - workQueue.enqueue(childScope.get()); + workQueue.enqueue(childScope); } return noUnqualifiedIdentifier; } diff --git a/tools/qmllint/checkidentifiers.h b/tools/qmllint/checkidentifiers.h index ae924c491c..5d2236b7f9 100644 --- a/tools/qmllint/checkidentifiers.h +++ b/tools/qmllint/checkidentifiers.h @@ -41,12 +41,12 @@ public: m_colorOut(colorOut), m_code(code), m_types(types) {} - bool operator ()(const QHash &qmlIDs, - const ScopeTree *root, const QString &rootId) const; + bool operator ()(const QHash &qmlIDs, + const ScopeTree::ConstPtr &root, const QString &rootId) const; private: bool checkMemberAccess(const QVector &members, - const ScopeTree *scope) const; + const ScopeTree::ConstPtr &outerScope) const; void printContext(const QQmlJS::SourceLocation &location) const; ColorOutput *m_colorOut = nullptr; diff --git a/tools/qmllint/findunqualified.cpp b/tools/qmllint/findunqualified.cpp index 24d133dd81..baae3a3ce7 100644 --- a/tools/qmllint/findunqualified.cpp +++ b/tools/qmllint/findunqualified.cpp @@ -67,7 +67,7 @@ static TypeDescriptionReader createQmltypesReaderForFile(const QString &filename void FindUnqualifiedIDVisitor::enterEnvironment(ScopeType type, const QString &name) { - m_currentScope = m_currentScope->createNewChildScope(type, name).get(); + m_currentScope = ScopeTree::create(type, name, m_currentScope); } void FindUnqualifiedIDVisitor::leaveEnvironment() @@ -99,11 +99,11 @@ void FindUnqualifiedIDVisitor::parseHeaders(QQmlJS::AST::UiHeaderItemList *heade } } -ScopeTree *FindUnqualifiedIDVisitor::parseProgram(QQmlJS::AST::Program *program, - const QString &name) +ScopeTree::Ptr FindUnqualifiedIDVisitor::parseProgram(QQmlJS::AST::Program *program, + const QString &name) { using namespace QQmlJS::AST; - ScopeTree *result = new ScopeTree(ScopeType::JSLexicalScope, name); + ScopeTree::Ptr result = ScopeTree::create(ScopeType::JSLexicalScope, name); for (auto *statement = program->statements; statement; statement = statement->next) { if (auto *function = cast(statement->statement)) { MetaMethod method(function->name.toString()); @@ -204,7 +204,7 @@ FindUnqualifiedIDVisitor::Import FindUnqualifiedIDVisitor::readQmldir(const QStr for (const QString &import : imports) result.dependencies.append(import); - QHash qmlComponents; + QHash qmlComponents; const auto components = reader.components(); for (auto it = components.begin(), end = components.end(); it != end; ++it) { const QString filePath = path + QLatin1Char('/') + it->fileName; @@ -299,7 +299,7 @@ void FindUnqualifiedIDVisitor::importHelper(const QString &module, const QString } } -ScopeTree *FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath) +ScopeTree::Ptr FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath) { using namespace QQmlJS::AST; const QFileInfo info { filePath }; @@ -315,8 +315,8 @@ ScopeTree *FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath QFile file(filePath); if (!file.open(QFile::ReadOnly)) { - return new ScopeTree(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, - scopeName); + return ScopeTree::create(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, + scopeName); } QString code = file.readAll(); @@ -329,8 +329,8 @@ ScopeTree *FindUnqualifiedIDVisitor::localFile2ScopeTree(const QString &filePath : parser.parseProgram()) : parser.parse(); if (!success) { - return new ScopeTree(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, - scopeName); + return ScopeTree::create(isJavaScript ? ScopeType::JSLexicalScope : ScopeType::QMLScope, + scopeName); } if (!isJavaScript) { @@ -392,7 +392,7 @@ void FindUnqualifiedIDVisitor::importExportedNames(const QStringRef &prefix, QSt scopes.append(scope); const auto properties = scope->properties(); for (auto property : properties) { - property.setType(m_exportedName2Scope.value(property.typeName()).get()); + property.setType(m_exportedName2Scope.value(property.typeName())); m_currentScope->insertPropertyIdentifier(property); } @@ -631,7 +631,7 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiPublicMember *uipm) false, uipm->memberType ? (uipm->memberType->name == QLatin1String("alias")) : false, 0); - property.setType(m_exportedName2Scope.value(property.typeName()).get()); + property.setType(m_exportedName2Scope.value(property.typeName())); m_currentScope->insertPropertyIdentifier(property); return true; } @@ -646,14 +646,15 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::IdentifierExpression *idexp) FindUnqualifiedIDVisitor::FindUnqualifiedIDVisitor(QStringList qmltypeDirs, QString code, QString fileName, bool silent) - : m_rootScope(new ScopeTree { ScopeType::JSFunctionScope, "global" }), - m_currentScope(m_rootScope.get()), + : m_rootScope(ScopeTree::create(ScopeType::JSFunctionScope, "global")), m_qmltypeDirs(std::move(qmltypeDirs)), m_code(std::move(code)), m_rootId(QLatin1String("")), m_filePath(std::move(fileName)), m_colorOut(silent) { + m_currentScope = m_rootScope; + // setup color output m_colorOut.insertMapping(Error, ColorOutput::RedForeground); m_colorOut.insertMapping(Warning, ColorOutput::PurpleForeground); @@ -692,12 +693,12 @@ bool FindUnqualifiedIDVisitor::check() auto targetScope = m_qmlid2scope[outstandingConnection.targetName]; if (outstandingConnection.scope) outstandingConnection.scope->addMethods(targetScope->methods()); - QScopedValueRollback rollback(m_currentScope, outstandingConnection.scope); + QScopedValueRollback rollback(m_currentScope, outstandingConnection.scope); outstandingConnection.uiod->initializer->accept(this); } CheckIdentifiers check(&m_colorOut, m_code, m_exportedName2Scope); - return check(m_qmlid2scope, m_rootScope.get(), m_rootId); + return check(m_qmlid2scope, m_rootScope, m_rootId); } bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::VariableDeclarationList *vdl) @@ -772,7 +773,7 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiImport *import) if (!import->importId.isEmpty()) { // TODO: do not put imported ids into the same space as qml IDs const QString importId = import->importId.toString(); - m_qmlid2scope.insert(importId, m_exportedName2Scope.value(importId).get()); + m_qmlid2scope.insert(importId, m_exportedName2Scope.value(importId)); } if (import->version) { auto uri = import->importUri; @@ -812,7 +813,7 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob) MetaProperty prop(uiob->qualifiedId->name.toString(), name, false, true, true, name == QLatin1String("alias"), 0); - prop.setType(m_exportedName2Scope.value(uiob->qualifiedTypeNameId->name.toString()).get()); + prop.setType(m_exportedName2Scope.value(uiob->qualifiedTypeNameId->name.toString())); m_currentScope->addProperty(prop); enterEnvironment(ScopeType::QMLScope, name); @@ -870,14 +871,14 @@ bool FindUnqualifiedIDVisitor::visit(QQmlJS::AST::UiObjectDefinition *uiod) } member = member->next; } - const ScopeTree *targetScope; + ScopeTree::ConstPtr targetScope; if (target.isEmpty()) { // no target set, connection comes from parentF - ScopeTree* scope = m_currentScope; + ScopeTree::Ptr scope = m_currentScope; do { scope = scope->parentScope(); // TODO: rename method } while (scope->scopeType() != ScopeType::QMLScope); - targetScope = m_exportedName2Scope.value(scope->name()).get(); + targetScope = m_exportedName2Scope.value(scope->name()); } else { // there was a target, check if we already can find it auto scopeIt = m_qmlid2scope.find(target); diff --git a/tools/qmllint/findunqualified.h b/tools/qmllint/findunqualified.h index d2ebc947bf..1c1751fafb 100644 --- a/tools/qmllint/findunqualified.h +++ b/tools/qmllint/findunqualified.h @@ -63,14 +63,14 @@ private: QStringList dependencies; }; - QScopedPointer m_rootScope; - ScopeTree *m_currentScope; + ScopeTree::Ptr m_rootScope; + ScopeTree::Ptr m_currentScope; QQmlJS::AST::ExpressionNode *m_fieldMemberBase = nullptr; QHash m_types; QHash m_exportedName2Scope; QStringList m_qmltypeDirs; QString m_code; - QHash m_qmlid2scope; + QHash m_qmlid2scope; QString m_rootId; QString m_filePath; QSet> m_alreadySeenImports; @@ -81,7 +81,7 @@ private: struct OutstandingConnection { QString targetName; - ScopeTree *scope; + ScopeTree::Ptr scope; QQmlJS::AST::UiObjectDefinition *uiod; }; @@ -96,13 +96,13 @@ private: Import readQmldir(const QString &dirname); void processImport(const QString &prefix, const Import &import); - ScopeTree *localFile2ScopeTree(const QString &filePath); + ScopeTree::Ptr localFile2ScopeTree(const QString &filePath); void importFileOrDirectory(const QString &directory, const QString &prefix); void importExportedNames(const QStringRef &prefix, QString name); void parseHeaders(QQmlJS::AST::UiHeaderItemList *headers); - ScopeTree *parseProgram(QQmlJS::AST::Program *program, const QString &name); + ScopeTree::Ptr parseProgram(QQmlJS::AST::Program *program, const QString &name); void throwRecursionDepthError() override; diff --git a/tools/qmllint/importedmembersvisitor.cpp b/tools/qmllint/importedmembersvisitor.cpp index c5214f2bb9..bf3787d489 100644 --- a/tools/qmllint/importedmembersvisitor.cpp +++ b/tools/qmllint/importedmembersvisitor.cpp @@ -31,9 +31,9 @@ using namespace QQmlJS::AST; -ScopeTree *ImportedMembersVisitor::result(const QString &scopeName) const +ScopeTree::Ptr ImportedMembersVisitor::result(const QString &scopeName) const { - ScopeTree *result = new ScopeTree(ScopeType::QMLScope); + ScopeTree::Ptr result = ScopeTree::create(); result->setClassName(scopeName); result->setSuperclassName(m_rootObject->superclassName()); const auto properties = m_rootObject->properties(); @@ -41,7 +41,7 @@ ScopeTree *ImportedMembersVisitor::result(const QString &scopeName) const if (property.isAlias()) { const auto it = m_objects.find(property.typeName()); if (it != m_objects.end()) - property.setType(it->get()); + property.setType(*it); result->addProperty(property); } else { result->addProperty(property); @@ -56,7 +56,7 @@ ScopeTree *ImportedMembersVisitor::result(const QString &scopeName) const bool ImportedMembersVisitor::visit(UiObjectDefinition *definition) { - ScopeTree::Ptr scope(new ScopeTree(ScopeType::QMLScope)); + ScopeTree::Ptr scope = ScopeTree::create(); QString superType; for (auto segment = definition->qualifiedTypeNameId; segment; segment = segment->next) { if (!superType.isEmpty()) diff --git a/tools/qmllint/importedmembersvisitor.h b/tools/qmllint/importedmembersvisitor.h index 793ff18dcc..045ba00420 100644 --- a/tools/qmllint/importedmembersvisitor.h +++ b/tools/qmllint/importedmembersvisitor.h @@ -51,7 +51,7 @@ public: m_colorOut(colorOut) {} - ScopeTree *result(const QString &scopeName) const; + ScopeTree::Ptr result(const QString &scopeName) const; private: bool visit(QQmlJS::AST::UiObjectDefinition *) override; diff --git a/tools/shared/metatypes.h b/tools/shared/metatypes.h index d67de2edcd..0ab37d72ca 100644 --- a/tools/shared/metatypes.h +++ b/tools/shared/metatypes.h @@ -41,6 +41,7 @@ #include #include +#include class MetaEnum { @@ -119,7 +120,7 @@ class MetaProperty { QString m_propertyName; QString m_typeName; - const ScopeTree *m_type = nullptr; + QWeakPointer m_type; bool m_isList; bool m_isWritable; bool m_isPointer; @@ -142,8 +143,8 @@ public: QString propertyName() const { return m_propertyName; } QString typeName() const { return m_typeName; } - void setType(const ScopeTree *type) { m_type = type; } - const ScopeTree *type() const { return m_type; } + void setType(const QSharedPointer &type) { m_type = type; } + QSharedPointer type() const { return m_type.toStrongRef(); } bool isList() const { return m_isList; } bool isWritable() const { return m_isWritable; } diff --git a/tools/shared/scopetree.cpp b/tools/shared/scopetree.cpp index 870ba13fc4..ea5175d2d6 100644 --- a/tools/shared/scopetree.cpp +++ b/tools/shared/scopetree.cpp @@ -33,17 +33,20 @@ #include -ScopeTree::ScopeTree(ScopeType type, QString name, ScopeTree *parentScope) - : m_parentScope(parentScope), m_name(std::move(name)), m_scopeType(type) {} - -ScopeTree::Ptr ScopeTree::createNewChildScope(ScopeType type, const QString &name) -{ - Q_ASSERT(type != ScopeType::QMLScope - || !m_parentScope - || m_parentScope->m_scopeType == ScopeType::QMLScope - || m_parentScope->m_name == QLatin1String("global")); - auto childScope = ScopeTree::Ptr(new ScopeTree{type, name, this}); - m_childScopes.push_back(childScope); +ScopeTree::ScopeTree(ScopeType type, const QString &name, const ScopeTree::Ptr &parentScope) + : m_parentScope(parentScope), m_name(name), m_scopeType(type) {} + +ScopeTree::Ptr ScopeTree::create(ScopeType type, const QString &name, + const ScopeTree::Ptr &parentScope) +{ + ScopeTree::Ptr childScope(new ScopeTree{type, name, parentScope}); + if (parentScope) { + Q_ASSERT(type != ScopeType::QMLScope + || !parentScope->m_parentScope + || parentScope->parentScope()->m_scopeType == ScopeType::QMLScope + || parentScope->parentScope()->m_name == QLatin1String("global")); + parentScope->m_childScopes.push_back(childScope); + } return childScope; } @@ -51,13 +54,13 @@ void ScopeTree::insertJSIdentifier(const QString &id, ScopeType scope) { Q_ASSERT(m_scopeType != ScopeType::QMLScope); Q_ASSERT(scope != ScopeType::QMLScope); - if (scope == ScopeType::JSFunctionScope) { - auto targetScope = this; - while (targetScope->scopeType() != ScopeType::JSFunctionScope) - targetScope = targetScope->m_parentScope; - targetScope->m_jsIdentifiers.insert(id); - } else { + if (scope != ScopeType::JSFunctionScope || m_scopeType == ScopeType::JSFunctionScope) { m_jsIdentifiers.insert(id); + } else { + auto targetScope = parentScope(); + while (targetScope->m_scopeType != ScopeType::JSFunctionScope) + targetScope = targetScope->parentScope(); + targetScope->m_jsIdentifiers.insert(id); } } @@ -101,13 +104,22 @@ void ScopeTree::accessMember(const QString &name, const QString &parentType, bool ScopeTree::isVisualRootScope() const { - return m_parentScope && m_parentScope->m_parentScope - && m_parentScope->m_parentScope->m_parentScope == nullptr; + if (!m_parentScope) + return false; + + const auto grandParent = parentScope()->m_parentScope.toStrongRef(); + if (!grandParent) + return false; + + return grandParent->m_parentScope == nullptr; } bool ScopeTree::isIdInCurrentQMlScopes(const QString &id) const { - const auto *qmlScope = currentQMLScope(); + 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); @@ -115,25 +127,29 @@ bool ScopeTree::isIdInCurrentQMlScopes(const QString &id) const bool ScopeTree::isIdInCurrentJSScopes(const QString &id) const { - auto jsScope = this; - while (jsScope) { + 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; - jsScope = jsScope->m_parentScope; } + return false; } bool ScopeTree::isIdInjectedFromSignal(const QString &id) const { - return currentQMLScope()->m_injectedSignalIdentifiers.contains(id); + if (m_scopeType == ScopeType::QMLScope) + return m_injectedSignalIdentifiers.contains(id); + return findCurrentQMLScope(parentScope())->m_injectedSignalIdentifiers.contains(id); } -const ScopeTree *ScopeTree::currentQMLScope() const +ScopeTree::ConstPtr ScopeTree::findCurrentQMLScope(const ScopeTree::ConstPtr &scope) { - auto qmlScope = this; + auto qmlScope = scope; while (qmlScope && qmlScope->m_scopeType != ScopeType::QMLScope) - qmlScope = qmlScope->m_parentScope; + qmlScope = qmlScope->parentScope(); return qmlScope; } @@ -148,7 +164,7 @@ void ScopeTree::setExportMetaObjectRevision(int exportIndex, int metaObjectRevis m_exports[exportIndex].setMetaObjectRevision(metaObjectRevision); } -void ScopeTree::updateParentProperty(const ScopeTree *scope) +void ScopeTree::updateParentProperty(const ScopeTree::ConstPtr &scope) { auto it = m_properties.find(QLatin1String("parent")); if (it != m_properties.end() diff --git a/tools/shared/scopetree.h b/tools/shared/scopetree.h index f28f2fa841..90f772ab98 100644 --- a/tools/shared/scopetree.h +++ b/tools/shared/scopetree.h @@ -67,7 +67,9 @@ class ScopeTree Q_DISABLE_COPY_MOVE(ScopeTree) public: using Ptr = QSharedPointer; + using WeakPtr = QWeakPointer; using ConstPtr = QSharedPointer; + using WeakConstPtr = QWeakPointer; class Export { public: @@ -93,11 +95,11 @@ public: int m_metaObjectRevision = 0; }; - ScopeTree(ScopeType type, QString name = QString(), - ScopeTree *parentScope = nullptr); + static ScopeTree::Ptr create(ScopeType type = ScopeType::QMLScope, const QString &name = QString(), + const ScopeTree::Ptr &parentScope = ScopeTree::Ptr()); + static ScopeTree::ConstPtr findCurrentQMLScope(const ScopeTree::ConstPtr &scope); - ScopeTree::Ptr createNewChildScope(ScopeType type, const QString &name); - ScopeTree *parentScope() const { return m_parentScope; } + ScopeTree::Ptr parentScope() const { return m_parentScope.toStrongRef(); } void insertJSIdentifier(const QString &id, ScopeType scope); void insertSignalIdentifier(const QString &id, const MetaMethod &method, @@ -139,7 +141,7 @@ public: void addProperty(const MetaProperty &prop) { m_properties.insert(prop.propertyName(), prop); } QHash properties() const { return m_properties; } - void updateParentProperty(const ScopeTree *scope); + void updateParentProperty(const ScopeTree::ConstPtr &scope); QString defaultPropertyName() const { return m_defaultPropertyName; } void setDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } @@ -174,7 +176,6 @@ public: bool isIdInCurrentQMlScopes(const QString &id) const; bool isIdInCurrentJSScopes(const QString &id) const; bool isIdInjectedFromSignal(const QString &id) const; - const ScopeTree *currentQMLScope() const; QVector childScopes() const { @@ -187,6 +188,8 @@ public: } private: + ScopeTree(ScopeType type, const QString &name = QString(), + const ScopeTree::Ptr &parentScope = ScopeTree::Ptr()); QSet m_jsIdentifiers; QMultiHash m_injectedSignalIdentifiers; @@ -199,7 +202,7 @@ private: QVector> m_unmatchedSignalHandlers; QVector m_childScopes; - ScopeTree *m_parentScope; + ScopeTree::WeakPtr m_parentScope; QString m_fileName; QString m_name; diff --git a/tools/shared/typedescriptionreader.cpp b/tools/shared/typedescriptionreader.cpp index 495ee57f32..3ca8e7e44a 100644 --- a/tools/shared/typedescriptionreader.cpp +++ b/tools/shared/typedescriptionreader.cpp @@ -188,7 +188,7 @@ void TypeDescriptionReader::readDependencies(UiScriptBinding *ast) void TypeDescriptionReader::readComponent(UiObjectDefinition *ast) { - ScopeTree::Ptr scope(new ScopeTree(ScopeType::QMLScope)); + ScopeTree::Ptr scope = ScopeTree::create(); for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { UiObjectMember *member = it->member; -- cgit v1.2.3