aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/qmllint/checkidentifiers.cpp37
-rw-r--r--tools/qmllint/checkidentifiers.h6
-rw-r--r--tools/qmllint/findunqualified.cpp43
-rw-r--r--tools/qmllint/findunqualified.h12
-rw-r--r--tools/qmllint/importedmembersvisitor.cpp8
-rw-r--r--tools/qmllint/importedmembersvisitor.h2
-rw-r--r--tools/shared/metatypes.h7
-rw-r--r--tools/shared/scopetree.cpp72
-rw-r--r--tools/shared/scopetree.h17
-rw-r--r--tools/shared/typedescriptionreader.cpp2
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<ScopeTree::FieldMember> &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<ScopeTree::FieldMember> &
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<ScopeTree::FieldMember> &
detectedRestrictiveName = access.m_name;
scope = nullptr;
} else {
- scope = it->get();
+ scope = *it;
}
continue;
}
@@ -189,10 +190,10 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<ScopeTree::FieldMember> &
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<ScopeTree::FieldMember> &
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<ScopeTree::FieldMember> &
return true;
}
-bool CheckIdentifiers::operator()(const QHash<QString, const ScopeTree *> &qmlIDs,
- const ScopeTree *root, const QString &rootId) const
+bool CheckIdentifiers::operator()(const QHash<QString, ScopeTree::ConstPtr> &qmlIDs,
+ const ScopeTree::ConstPtr &root, const QString &rootId) const
{
bool noUnqualifiedIdentifier = true;
// revisit all scopes
- QQueue<const ScopeTree *> workQueue;
+ QQueue<ScopeTree::ConstPtr> 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<QString, const ScopeTree *> &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<QString, const ScopeTree *> &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<QString, const ScopeTree *> &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<QString, const ScopeTree *> &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<QString, const ScopeTree *> &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<QString, const ScopeTree *> &qmlIDs,
- const ScopeTree *root, const QString &rootId) const;
+ bool operator ()(const QHash<QString, ScopeTree::ConstPtr> &qmlIDs,
+ const ScopeTree::ConstPtr &root, const QString &rootId) const;
private:
bool checkMemberAccess(const QVector<ScopeTree::FieldMember> &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<FunctionDeclaration *>(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<QString, ScopeTree *> qmlComponents;
+ 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;
@@ -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("<id>")),
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<ScopeTree*> rollback(m_currentScope, outstandingConnection.scope);
+ QScopedValueRollback<ScopeTree::Ptr> 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<ScopeTree> m_rootScope;
- ScopeTree *m_currentScope;
+ ScopeTree::Ptr m_rootScope;
+ ScopeTree::Ptr m_currentScope;
QQmlJS::AST::ExpressionNode *m_fieldMemberBase = nullptr;
QHash<QString, ScopeTree::ConstPtr> m_types;
QHash<QString, ScopeTree::ConstPtr> m_exportedName2Scope;
QStringList m_qmltypeDirs;
QString m_code;
- QHash<QString, const ScopeTree *> m_qmlid2scope;
+ QHash<QString, ScopeTree::ConstPtr> m_qmlid2scope;
QString m_rootId;
QString m_filePath;
QSet<QPair<QString, QString>> 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 <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qsharedpointer.h>
class MetaEnum
{
@@ -119,7 +120,7 @@ class MetaProperty
{
QString m_propertyName;
QString m_typeName;
- const ScopeTree *m_type = nullptr;
+ QWeakPointer<const ScopeTree> 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<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; }
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 <algorithm>
-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<ScopeTree>;
+ using WeakPtr = QWeakPointer<ScopeTree>;
using ConstPtr = QSharedPointer<const ScopeTree>;
+ using WeakConstPtr = QWeakPointer<const ScopeTree>;
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<QString, MetaProperty> 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<ScopeTree::Ptr> childScopes() const
{
@@ -187,6 +188,8 @@ public:
}
private:
+ ScopeTree(ScopeType type, const QString &name = QString(),
+ const ScopeTree::Ptr &parentScope = ScopeTree::Ptr());
QSet<QString> m_jsIdentifiers;
QMultiHash<QString, MethodUsage> m_injectedSignalIdentifiers;
@@ -199,7 +202,7 @@ private:
QVector<QPair<QString, QQmlJS::SourceLocation>> m_unmatchedSignalHandlers;
QVector<ScopeTree::Ptr> 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;