1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef QQMLJSSCOPESBYID_P_H
#define QQMLJSSCOPESBYID_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 "qqmljsscope_p.h"
#include <QtCore/qhash.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
enum QQmlJSScopesByIdOption: char {
Default = 0,
AssumeComponentsAreBound = 1,
};
Q_DECLARE_FLAGS(QQmlJSScopesByIdOptions, QQmlJSScopesByIdOption);
class QQmlJSScopesById
{
public:
bool componentsAreBound() const { return m_componentsAreBound; }
void setComponentsAreBound(bool bound) { m_componentsAreBound = bound; }
void setSignaturesAreEnforced(bool enforced) { m_signaturesAreEnforced = enforced; }
bool signaturesAreEnforced() const { return m_signaturesAreEnforced; }
void setValueTypesAreAddressable(bool addressable) { m_valueTypesAreAddressable = addressable; }
bool valueTypesAreAddressable() const { return m_valueTypesAreAddressable; }
QString id(const QQmlJSScope::ConstPtr &scope, const QQmlJSScope::ConstPtr &referrer,
QQmlJSScopesByIdOptions options = Default) const
{
const QQmlJSScope::ConstPtr referrerRoot = componentRoot(referrer);
for (auto it = m_scopesById.begin(), end = m_scopesById.end(); it != end; ++it) {
if (*it == scope && isComponentVisible(componentRoot(*it), referrerRoot, options))
return it.key();
}
return QString();
}
/*!
\internal
Returns the scope that has id \a id in the component to which \a referrer belongs to.
If no such scope exists, a null scope is returned.
*/
QQmlJSScope::ConstPtr scope(const QString &id, const QQmlJSScope::ConstPtr &referrer,
QQmlJSScopesByIdOptions options = Default) const
{
Q_ASSERT(!id.isEmpty());
const auto range = m_scopesById.equal_range(id);
if (range.first == range.second)
return QQmlJSScope::ConstPtr();
const QQmlJSScope::ConstPtr referrerRoot = componentRoot(referrer);
for (auto it = range.first; it != range.second; ++it) {
if (isComponentVisible(componentRoot(*it), referrerRoot, options))
return *it;
}
return QQmlJSScope::ConstPtr();
}
void insert(const QString &id, const QQmlJSScope::ConstPtr &scope)
{
Q_ASSERT(!id.isEmpty());
m_scopesById.insert(id, scope);
}
void clear() { m_scopesById.clear(); }
/*!
\internal
Returns \c true if \a id exists anywhere in the current document.
This is still allowed if the other occurrence is in a different (inline) component.
Check the return value of scope to know whether the id has already been assigned
in a givne scope.
*/
bool existsAnywhereInDocument(const QString &id) const { return m_scopesById.contains(id); }
private:
static QQmlJSScope::ConstPtr componentRoot(const QQmlJSScope::ConstPtr &inner)
{
QQmlJSScope::ConstPtr scope = inner;
while (scope
&& scope->componentRootStatus() == QQmlJSScope::IsComponentRoot::No
&& !scope->isInlineComponent()) {
if (QQmlJSScope::ConstPtr parent = scope->parentScope())
scope = parent;
else
break;
}
return scope;
}
bool isComponentVisible(const QQmlJSScope::ConstPtr &observed,
const QQmlJSScope::ConstPtr &observer,
QQmlJSScopesByIdOptions options) const
{
if (!m_componentsAreBound && !options.testAnyFlag(AssumeComponentsAreBound))
return observed == observer;
for (QQmlJSScope::ConstPtr scope = observer; scope; scope = scope->parentScope()) {
if (scope == observed)
return true;
}
return false;
}
QMultiHash<QString, QQmlJSScope::ConstPtr> m_scopesById;
bool m_componentsAreBound = false;
bool m_signaturesAreEnforced = true;
bool m_valueTypesAreAddressable = false;
};
QT_END_NAMESPACE
#endif // QQMLJSSCOPESBYID_P_H
|