1 | // Copyright (C) 2019 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #ifndef QQMLJSSCOPE_P_H |
5 | #define QQMLJSSCOPE_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | |
17 | #include <qtqmlcompilerexports.h> |
18 | |
19 | #include "qqmljsmetatypes_p.h" |
20 | #include "qdeferredpointer_p.h" |
21 | #include "qqmljsannotation_p.h" |
22 | #include "qqmlsaconstants.h" |
23 | #include "qqmlsa_p.h" |
24 | |
25 | #include <QtQml/private/qqmljssourcelocation_p.h> |
26 | |
27 | #include <QtCore/qfileinfo.h> |
28 | #include <QtCore/qhash.h> |
29 | #include <QtCore/qset.h> |
30 | #include <QtCore/qstring.h> |
31 | #include <QtCore/qversionnumber.h> |
32 | #include "qqmlsaconstants.h" |
33 | |
34 | #include <optional> |
35 | |
36 | QT_BEGIN_NAMESPACE |
37 | |
38 | class QQmlJSImporter; |
39 | |
40 | namespace QQmlJS { |
41 | |
42 | class ConstPtrWrapperIterator |
43 | { |
44 | public: |
45 | using Ptr = QDeferredSharedPointer<QQmlJSScope>; |
46 | using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>; |
47 | using iterator_category = std::forward_iterator_tag; |
48 | using difference_type = std::ptrdiff_t; |
49 | using value_type = ConstPtr; |
50 | using pointer = value_type *; |
51 | using reference = value_type &; |
52 | |
53 | ConstPtrWrapperIterator(QList<Ptr>::const_iterator iterator) : m_iterator(iterator) { } |
54 | |
55 | friend bool operator==(const ConstPtrWrapperIterator &a, const ConstPtrWrapperIterator &b) |
56 | { |
57 | return a.m_iterator == b.m_iterator; |
58 | } |
59 | friend bool operator!=(const ConstPtrWrapperIterator &a, const ConstPtrWrapperIterator &b) |
60 | { |
61 | return a.m_iterator != b.m_iterator; |
62 | } |
63 | |
64 | reference operator*() |
65 | { |
66 | if (!m_pointer) |
67 | m_pointer = *m_iterator; |
68 | return m_pointer; |
69 | } |
70 | pointer operator->() |
71 | { |
72 | if (!m_pointer) |
73 | m_pointer = *m_iterator; |
74 | return &m_pointer; |
75 | } |
76 | |
77 | ConstPtrWrapperIterator &operator++() |
78 | { |
79 | m_iterator++; |
80 | m_pointer = {}; |
81 | return *this; |
82 | } |
83 | ConstPtrWrapperIterator operator++(int) |
84 | { |
85 | auto before = *this; |
86 | ++(*this); |
87 | return before; |
88 | } |
89 | |
90 | private: |
91 | QList<Ptr>::const_iterator m_iterator; |
92 | ConstPtr m_pointer; |
93 | }; |
94 | |
95 | class Export { |
96 | public: |
97 | Export() = default; |
98 | Export(QString package, QString type, QTypeRevision version, QTypeRevision revision); |
99 | |
100 | bool isValid() const; |
101 | |
102 | QString package() const { return m_package; } |
103 | QString type() const { return m_type; } |
104 | QTypeRevision version() const { return m_version; } |
105 | QTypeRevision revision() const { return m_revision; } |
106 | |
107 | private: |
108 | QString m_package; |
109 | QString m_type; |
110 | QTypeRevision m_version; |
111 | QTypeRevision m_revision; |
112 | }; |
113 | |
114 | template<typename Pointer> |
115 | struct ExportedScope { |
116 | Pointer scope; |
117 | QList<Export> exports; |
118 | }; |
119 | |
120 | template<typename Pointer> |
121 | struct ImportedScope { |
122 | Pointer scope; |
123 | QTypeRevision revision; |
124 | }; |
125 | |
126 | struct ContextualTypes; |
127 | |
128 | } // namespace QQmlJS |
129 | |
130 | class Q_QMLCOMPILER_EXPORT QQmlJSScope |
131 | { |
132 | friend QQmlSA::Element; |
133 | |
134 | public: |
135 | explicit QQmlJSScope(const QString &internalName); |
136 | QQmlJSScope(QQmlJSScope &&) = default; |
137 | QQmlJSScope &operator=(QQmlJSScope &&) = default; |
138 | |
139 | using Ptr = QDeferredSharedPointer<QQmlJSScope>; |
140 | using WeakPtr = QDeferredWeakPointer<QQmlJSScope>; |
141 | using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>; |
142 | using WeakConstPtr = QDeferredWeakPointer<const QQmlJSScope>; |
143 | |
144 | using AccessSemantics = QQmlSA::AccessSemantics; |
145 | using ScopeType = QQmlSA::ScopeType; |
146 | |
147 | using InlineComponentNameType = QString; |
148 | using RootDocumentNameType = std::monostate; // an empty type that has std::hash |
149 | /*! |
150 | * A Hashable type to differentiate document roots from different inline components. |
151 | */ |
152 | using InlineComponentOrDocumentRootName = |
153 | std::variant<InlineComponentNameType, RootDocumentNameType>; |
154 | |
155 | enum Flag { |
156 | Creatable = 0x1, |
157 | Composite = 0x2, |
158 | JavaScriptBuiltin = 0x4, |
159 | Singleton = 0x8, |
160 | Script = 0x10, |
161 | CustomParser = 0x20, |
162 | Array = 0x40, |
163 | InlineComponent = 0x80, |
164 | WrappedInImplicitComponent = 0x100, |
165 | HasBaseTypeError = 0x200, |
166 | ExtensionIsNamespace = 0x400, |
167 | IsListProperty = 0x800, |
168 | Structured = 0x1000, |
169 | ExtensionIsJavaScript = 0x2000, |
170 | EnforcesScopedEnums = 0x4000, |
171 | AssignedToUnknownProperty = 0x10000, |
172 | }; |
173 | Q_DECLARE_FLAGS(Flags, Flag) |
174 | Q_FLAGS(Flags); |
175 | |
176 | using Export = QQmlJS::Export; |
177 | template <typename Pointer> |
178 | using ImportedScope = QQmlJS::ImportedScope<Pointer>; |
179 | template <typename Pointer> |
180 | using ExportedScope = QQmlJS::ExportedScope<Pointer>; |
181 | |
182 | struct JavaScriptIdentifier |
183 | { |
184 | enum Kind { |
185 | Parameter, |
186 | FunctionScoped, |
187 | LexicalScoped, |
188 | Injected |
189 | }; |
190 | |
191 | Kind kind = FunctionScoped; |
192 | QQmlJS::SourceLocation location; |
193 | std::optional<QString> typeName; |
194 | bool isConst = false; |
195 | QQmlJSScope::WeakConstPtr scope = {}; |
196 | }; |
197 | |
198 | enum BindingTargetSpecifier { |
199 | SimplePropertyTarget, // e.g. `property int p: 42` |
200 | ListPropertyTarget, // e.g. `property list<Item> pList: [ Text {} ]` |
201 | UnnamedPropertyTarget // default property bindings, where property name is unspecified |
202 | }; |
203 | |
204 | template <typename Key, typename Value> |
205 | using QMultiHashRange = QPair<typename QMultiHash<Key, Value>::iterator, |
206 | typename QMultiHash<Key, Value>::iterator>; |
207 | |
208 | static QQmlJSScope::Ptr create() { return QSharedPointer<QQmlJSScope>(new QQmlJSScope); } |
209 | static QQmlJSScope::Ptr create(const QString &internalName); |
210 | static QQmlJSScope::Ptr clone(const QQmlJSScope::ConstPtr &origin); |
211 | |
212 | static QQmlJSScope::ConstPtr findCurrentQMLScope(const QQmlJSScope::ConstPtr &scope); |
213 | |
214 | QQmlJSScope::Ptr parentScope(); |
215 | QQmlJSScope::ConstPtr parentScope() const; |
216 | static void reparent(const QQmlJSScope::Ptr &parentScope, const QQmlJSScope::Ptr &childScope); |
217 | |
218 | void insertJSIdentifier(const QString &name, const JavaScriptIdentifier &identifier); |
219 | QHash<QString, JavaScriptIdentifier> ownJSIdentifiers() const; |
220 | void insertPropertyIdentifier(const QQmlJSMetaProperty &prop); |
221 | |
222 | ScopeType scopeType() const { return m_scopeType; } |
223 | void setScopeType(ScopeType type) { m_scopeType = type; } |
224 | |
225 | void addOwnMethod(const QQmlJSMetaMethod &method) { m_methods.insert(key: method.methodName(), value: method); } |
226 | QMultiHashRange<QString, QQmlJSMetaMethod> mutableOwnMethodsRange(const QString &name) |
227 | { |
228 | return m_methods.equal_range(key: name); |
229 | } |
230 | QMultiHash<QString, QQmlJSMetaMethod> ownMethods() const { return m_methods; } |
231 | QList<QQmlJSMetaMethod> ownMethods(const QString &name) const { return m_methods.values(key: name); } |
232 | bool hasOwnMethod(const QString &name) const { return m_methods.contains(key: name); } |
233 | |
234 | bool hasMethod(const QString &name) const; |
235 | QHash<QString, QQmlJSMetaMethod> methods() const; |
236 | QList<QQmlJSMetaMethod> methods(const QString &name) const; |
237 | QList<QQmlJSMetaMethod> methods(const QString &name, QQmlJSMetaMethodType type) const; |
238 | |
239 | void addOwnEnumeration(const QQmlJSMetaEnum &enumeration) { m_enumerations.insert(key: enumeration.name(), value: enumeration); } |
240 | QHash<QString, QQmlJSMetaEnum> ownEnumerations() const { return m_enumerations; } |
241 | QQmlJSMetaEnum ownEnumeration(const QString &name) const { return m_enumerations.value(key: name); } |
242 | bool hasOwnEnumeration(const QString &name) const { return m_enumerations.contains(key: name); } |
243 | |
244 | bool hasEnumeration(const QString &name) const; |
245 | bool hasEnumerationKey(const QString &name) const; |
246 | bool hasOwnEnumerationKey(const QString &name) const; |
247 | QQmlJSMetaEnum enumeration(const QString &name) const; |
248 | QHash<QString, QQmlJSMetaEnum> enumerations() const; |
249 | |
250 | void setAnnotations(const QList<QQmlJSAnnotation> &annotation) { m_annotations = std::move(annotation); } |
251 | const QList<QQmlJSAnnotation> &annotations() const { return m_annotations; } |
252 | |
253 | QString filePath() const { return m_filePath; } |
254 | void setFilePath(const QString &file) { m_filePath = file; } |
255 | |
256 | // The name the type uses to refer to itself. Either C++ class name or base name of |
257 | // QML file. isComposite tells us if this is a C++ or a QML name. |
258 | QString internalName() const { return m_internalName; } |
259 | void setInternalName(const QString &internalName) { m_internalName = internalName; } |
260 | QString augmentedInternalName() const; |
261 | |
262 | // This returns a more user readable version of internalName / baseTypeName |
263 | static QString prettyName(QAnyStringView name); |
264 | |
265 | enum class IsComponentRoot : quint8 { No = 0, Yes, Maybe }; |
266 | IsComponentRoot componentRootStatus() const; |
267 | |
268 | void setAliases(const QStringList &aliases) { m_aliases = aliases; } |
269 | QStringList aliases() const { return m_aliases; } |
270 | |
271 | void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; } |
272 | QStringList interfaceNames() const { return m_interfaceNames; } |
273 | |
274 | bool hasInterface(const QString &name) const; |
275 | bool hasOwnInterface(const QString &name) const { return m_interfaceNames.contains(str: name); } |
276 | |
277 | void setOwnDeferredNames(const QStringList &names) { m_ownDeferredNames = names; } |
278 | QStringList ownDeferredNames() const { return m_ownDeferredNames; } |
279 | void setOwnImmediateNames(const QStringList &names) { m_ownImmediateNames = names; } |
280 | QStringList ownImmediateNames() const { return m_ownImmediateNames; } |
281 | |
282 | bool isNameDeferred(const QString &name) const; |
283 | |
284 | // If isComposite(), this is the QML/JS name of the prototype. Otherwise it's the |
285 | // relevant base class (in the hierarchy starting from QObject) of a C++ type. |
286 | void setBaseTypeName(const QString &baseTypeName); |
287 | QString baseTypeName() const; |
288 | |
289 | QQmlJSScope::ConstPtr baseType() const { return m_baseType.scope; } |
290 | QTypeRevision baseTypeRevision() const { return m_baseType.revision; } |
291 | |
292 | QString moduleName() const; |
293 | QString ownModuleName() const { return m_moduleName; } |
294 | void setOwnModuleName(const QString &moduleName) { m_moduleName = moduleName; } |
295 | |
296 | void clearBaseType() { m_baseType = {}; } |
297 | void setBaseTypeError(const QString &baseTypeError); |
298 | QString baseTypeError() const; |
299 | |
300 | void addOwnProperty(const QQmlJSMetaProperty &prop) { m_properties.insert(key: prop.propertyName(), value: prop); } |
301 | QHash<QString, QQmlJSMetaProperty> ownProperties() const { return m_properties; } |
302 | QQmlJSMetaProperty ownProperty(const QString &name) const { return m_properties.value(key: name); } |
303 | bool hasOwnProperty(const QString &name) const { return m_properties.contains(key: name); } |
304 | |
305 | bool hasProperty(const QString &name) const; |
306 | QQmlJSMetaProperty property(const QString &name) const; |
307 | QHash<QString, QQmlJSMetaProperty> properties() const; |
308 | |
309 | void setPropertyLocallyRequired(const QString &name, bool isRequired); |
310 | bool isPropertyRequired(const QString &name) const; |
311 | bool isPropertyLocallyRequired(const QString &name) const; |
312 | |
313 | void addOwnPropertyBinding( |
314 | const QQmlJSMetaPropertyBinding &binding, |
315 | BindingTargetSpecifier specifier = BindingTargetSpecifier::SimplePropertyTarget); |
316 | QMultiHash<QString, QQmlJSMetaPropertyBinding> ownPropertyBindings() const; |
317 | QPair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, |
318 | QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> |
319 | ownPropertyBindings(const QString &name) const; |
320 | QList<QQmlJSMetaPropertyBinding> ownPropertyBindingsInQmlIROrder() const; |
321 | bool hasOwnPropertyBindings(const QString &name) const; |
322 | |
323 | bool hasPropertyBindings(const QString &name) const; |
324 | QList<QQmlJSMetaPropertyBinding> propertyBindings(const QString &name) const; |
325 | |
326 | struct AnnotatedScope; // defined later |
327 | static AnnotatedScope ownerOfProperty(const QQmlJSScope::ConstPtr &self, const QString &name); |
328 | |
329 | bool isResolved() const; |
330 | bool isFullyResolved() const; |
331 | |
332 | QString ownDefaultPropertyName() const { return m_defaultPropertyName; } |
333 | void setOwnDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } |
334 | QString defaultPropertyName() const; |
335 | |
336 | QString ownParentPropertyName() const { return m_parentPropertyName; } |
337 | void setOwnParentPropertyName(const QString &name) { m_parentPropertyName = name; } |
338 | QString parentPropertyName() const; |
339 | |
340 | QString ownAttachedTypeName() const { return m_attachedTypeName; } |
341 | void setOwnAttachedTypeName(const QString &name) { m_attachedTypeName = name; } |
342 | QQmlJSScope::ConstPtr ownAttachedType() const { return m_attachedType; } |
343 | |
344 | QString attachedTypeName() const; |
345 | QQmlJSScope::ConstPtr attachedType() const; |
346 | |
347 | QString extensionTypeName() const { return m_extensionTypeName; } |
348 | void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; } |
349 | enum ExtensionKind { |
350 | NotExtension, |
351 | ExtensionType, |
352 | ExtensionJavaScript, |
353 | ExtensionNamespace, |
354 | }; |
355 | struct AnnotatedScope |
356 | { |
357 | QQmlJSScope::ConstPtr scope; |
358 | ExtensionKind extensionSpecifier = NotExtension; |
359 | }; |
360 | AnnotatedScope extensionType() const; |
361 | |
362 | QString valueTypeName() const { return m_valueTypeName; } |
363 | void setValueTypeName(const QString &name) { m_valueTypeName = name; } |
364 | QQmlJSScope::ConstPtr valueType() const { return m_valueType; } |
365 | QQmlJSScope::ConstPtr listType() const { return m_listType; } |
366 | QQmlJSScope::Ptr listType() { return m_listType; } |
367 | |
368 | void addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index); |
369 | QQmlJSMetaMethod::AbsoluteFunctionIndex |
370 | ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const; |
371 | |
372 | |
373 | /*! |
374 | * \internal |
375 | * |
376 | * Returns true for objects defined from Qml, and false for objects declared from C++. |
377 | */ |
378 | bool isComposite() const { return m_flags.testFlag(flag: Composite); } |
379 | void setIsComposite(bool v) { m_flags.setFlag(flag: Composite, on: v); } |
380 | |
381 | /*! |
382 | * \internal |
383 | * |
384 | * Returns true for JavaScript types, false for QML and C++ types. |
385 | */ |
386 | bool isJavaScriptBuiltin() const { return m_flags.testFlag(flag: JavaScriptBuiltin); } |
387 | void setIsJavaScriptBuiltin(bool v) { m_flags.setFlag(flag: JavaScriptBuiltin, on: v); } |
388 | |
389 | bool isScript() const { return m_flags.testFlag(flag: Script); } |
390 | void setIsScript(bool v) { m_flags.setFlag(flag: Script, on: v); } |
391 | |
392 | bool hasCustomParser() const { return m_flags.testFlag(flag: CustomParser); } |
393 | void setHasCustomParser(bool v) { m_flags.setFlag(flag: CustomParser, on: v); } |
394 | |
395 | bool isArrayScope() const { return m_flags.testFlag(flag: Array); } |
396 | void setIsArrayScope(bool v) { m_flags.setFlag(flag: Array, on: v); } |
397 | |
398 | bool isInlineComponent() const { return m_flags.testFlag(flag: InlineComponent); } |
399 | void setIsInlineComponent(bool v) { m_flags.setFlag(flag: InlineComponent, on: v); } |
400 | |
401 | bool isWrappedInImplicitComponent() const { return m_flags.testFlag(flag: WrappedInImplicitComponent); } |
402 | void setIsWrappedInImplicitComponent(bool v) { m_flags.setFlag(flag: WrappedInImplicitComponent, on: v); } |
403 | |
404 | bool isAssignedToUnknownProperty() const { return m_flags.testFlag(flag: AssignedToUnknownProperty); } |
405 | void setAssignedToUnknownProperty(bool v) { m_flags.setFlag(flag: AssignedToUnknownProperty, on: v); } |
406 | |
407 | bool extensionIsJavaScript() const { return m_flags.testFlag(flag: ExtensionIsJavaScript); } |
408 | void setExtensionIsJavaScript(bool v) { m_flags.setFlag(flag: ExtensionIsJavaScript, on: v); } |
409 | |
410 | bool extensionIsNamespace() const { return m_flags.testFlag(flag: ExtensionIsNamespace); } |
411 | void setExtensionIsNamespace(bool v) { m_flags.setFlag(flag: ExtensionIsNamespace, on: v); } |
412 | |
413 | bool isListProperty() const { return m_flags.testFlag(flag: IsListProperty); } |
414 | void setIsListProperty(bool v) { m_flags.setFlag(flag: IsListProperty, on: v); } |
415 | |
416 | bool isSingleton() const { return m_flags.testFlag(flag: Singleton); } |
417 | void setIsSingleton(bool v) { m_flags.setFlag(flag: Singleton, on: v); } |
418 | |
419 | bool enforcesScopedEnums() const; |
420 | void setEnforcesScopedEnumsFlag(bool v) { m_flags.setFlag(flag: EnforcesScopedEnums, on: v); } |
421 | |
422 | bool isCreatable() const; |
423 | void setCreatableFlag(bool v) { m_flags.setFlag(flag: Creatable, on: v); } |
424 | |
425 | bool isStructured() const; |
426 | void setStructuredFlag(bool v) { m_flags.setFlag(flag: Structured, on: v); } |
427 | |
428 | void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; } |
429 | AccessSemantics accessSemantics() const { return m_semantics; } |
430 | bool isReferenceType() const { return m_semantics == QQmlJSScope::AccessSemantics::Reference; } |
431 | bool isValueType() const { return m_semantics == QQmlJSScope::AccessSemantics::Value; } |
432 | |
433 | std::optional<JavaScriptIdentifier> jsIdentifier(const QString &id) const; |
434 | std::optional<JavaScriptIdentifier> ownJSIdentifier(const QString &id) const; |
435 | |
436 | QQmlJS::ConstPtrWrapperIterator childScopesBegin() const { return m_childScopes.constBegin(); } |
437 | QQmlJS::ConstPtrWrapperIterator childScopesEnd() const { return m_childScopes.constEnd(); } |
438 | |
439 | void setInlineComponentName(const QString &inlineComponentName); |
440 | std::optional<QString> inlineComponentName() const; |
441 | InlineComponentOrDocumentRootName enclosingInlineComponentName() const; |
442 | |
443 | QVector<QQmlJSScope::Ptr> childScopes(); |
444 | |
445 | QVector<QQmlJSScope::ConstPtr> childScopes() const; |
446 | |
447 | static QTypeRevision resolveTypes( |
448 | const Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
449 | QSet<QString> *usedTypes = nullptr); |
450 | static void resolveNonEnumTypes( |
451 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
452 | QSet<QString> *usedTypes = nullptr); |
453 | static void resolveEnums( |
454 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
455 | QSet<QString> *usedTypes = nullptr); |
456 | static void resolveList( |
457 | const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &arrayType); |
458 | static void resolveGroup( |
459 | const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &baseType, |
460 | const QQmlJS::ContextualTypes &contextualTypes, |
461 | QSet<QString> *usedTypes = nullptr); |
462 | |
463 | void setSourceLocation(const QQmlJS::SourceLocation &sourceLocation); |
464 | QQmlJS::SourceLocation sourceLocation() const; |
465 | |
466 | static QQmlJSScope::ConstPtr nonCompositeBaseType(const QQmlJSScope::ConstPtr &type); |
467 | |
468 | static QTypeRevision |
469 | nonCompositeBaseRevision(const ImportedScope<QQmlJSScope::ConstPtr> &scope); |
470 | |
471 | bool isSameType(const QQmlJSScope::ConstPtr &otherScope) const; |
472 | bool inherits(const QQmlJSScope::ConstPtr &base) const; |
473 | bool canAssign(const QQmlJSScope::ConstPtr &derived) const; |
474 | |
475 | bool isInCustomParserParent() const; |
476 | |
477 | |
478 | static ImportedScope<QQmlJSScope::ConstPtr> findType(const QString &name, |
479 | const QQmlJS::ContextualTypes &contextualTypes, |
480 | QSet<QString> *usedTypes = nullptr); |
481 | |
482 | static QQmlSA::Element createQQmlSAElement(const ConstPtr &); |
483 | static QQmlSA::Element createQQmlSAElement(ConstPtr &&); |
484 | static const QQmlJSScope::ConstPtr &scope(const QQmlSA::Element &); |
485 | static constexpr qsizetype sizeofQQmlSAElement() { return QQmlSA::Element::sizeofElement; } |
486 | |
487 | private: |
488 | /*! \internal |
489 | |
490 | Minimal information about a QQmlJSMetaPropertyBinding that allows it to |
491 | be manipulated similarly to QmlIR::Binding. |
492 | */ |
493 | template <typename T> |
494 | friend class QTypeInfo; // so that we can Q_DECLARE_TYPEINFO QmlIRCompatibilityBindingData |
495 | struct QmlIRCompatibilityBindingData |
496 | { |
497 | QmlIRCompatibilityBindingData() = default; |
498 | QmlIRCompatibilityBindingData(const QString &name, quint32 offset) |
499 | : propertyName(name), sourceLocationOffset(offset) |
500 | { |
501 | } |
502 | QString propertyName; // bound property name |
503 | quint32 sourceLocationOffset = 0; // binding's source location offset |
504 | }; |
505 | |
506 | QQmlJSScope() = default; |
507 | QQmlJSScope(const QQmlJSScope &) = default; |
508 | QQmlJSScope &operator=(const QQmlJSScope &) = default; |
509 | static QTypeRevision resolveType( |
510 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
511 | QSet<QString> *usedTypes); |
512 | static void updateChildScope( |
513 | const QQmlJSScope::Ptr &childScope, const QQmlJSScope::Ptr &self, |
514 | const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes); |
515 | |
516 | void addOwnPropertyBindingInQmlIROrder(const QQmlJSMetaPropertyBinding &binding, |
517 | BindingTargetSpecifier specifier); |
518 | bool hasEnforcesScopedEnumsFlag() const { return m_flags & EnforcesScopedEnums; } |
519 | bool hasCreatableFlag() const { return m_flags & Creatable; } |
520 | bool hasStructuredFlag() const { return m_flags & Structured; } |
521 | |
522 | QHash<QString, JavaScriptIdentifier> m_jsIdentifiers; |
523 | |
524 | QMultiHash<QString, QQmlJSMetaMethod> m_methods; |
525 | QHash<QString, QQmlJSMetaProperty> m_properties; |
526 | QMultiHash<QString, QQmlJSMetaPropertyBinding> m_propertyBindings; |
527 | |
528 | // a special QmlIR compatibility bindings array, ordered the same way as |
529 | // bindings in QmlIR::Object |
530 | QList<QmlIRCompatibilityBindingData> m_propertyBindingsArray; |
531 | |
532 | // same as QmlIR::Object::runtimeFunctionIndices |
533 | QList<QQmlJSMetaMethod::AbsoluteFunctionIndex> m_runtimeFunctionIndices; |
534 | |
535 | QHash<QString, QQmlJSMetaEnum> m_enumerations; |
536 | |
537 | QVector<QQmlJSAnnotation> m_annotations; |
538 | QVector<QQmlJSScope::Ptr> m_childScopes; |
539 | QQmlJSScope::WeakPtr m_parentScope; |
540 | |
541 | QString m_filePath; |
542 | QString m_internalName; |
543 | QString m_baseTypeNameOrError; |
544 | |
545 | // We only need the revision for the base type as inheritance is |
546 | // the only relation between two types where the revisions matter. |
547 | ImportedScope<QQmlJSScope::WeakConstPtr> m_baseType; |
548 | |
549 | ScopeType m_scopeType = ScopeType::QMLScope; |
550 | QStringList m_aliases; |
551 | QStringList m_interfaceNames; |
552 | QStringList m_ownDeferredNames; |
553 | QStringList m_ownImmediateNames; |
554 | |
555 | QString m_defaultPropertyName; |
556 | QString m_parentPropertyName; |
557 | /*! \internal |
558 | * The attached type name. |
559 | * This is an internal name, from a c++ type or a synthetic jsrootgen. |
560 | */ |
561 | QString m_attachedTypeName; |
562 | QStringList m_requiredPropertyNames; |
563 | QQmlJSScope::WeakConstPtr m_attachedType; |
564 | |
565 | /*! \internal |
566 | * The Value type name. |
567 | * This is an internal name, from a c++ type or a synthetic jsrootgen. |
568 | */ |
569 | QString m_valueTypeName; |
570 | QQmlJSScope::WeakConstPtr m_valueType; |
571 | QQmlJSScope::Ptr m_listType; |
572 | |
573 | /*! |
574 | The extension is provided as either a type (QML_{NAMESPACE_}EXTENDED) or as a |
575 | namespace (QML_EXTENDED_NAMESPACE). |
576 | The bool HasExtensionNamespace helps differentiating both cases, as namespaces |
577 | have a more limited lookup capaility. |
578 | This is an internal name, from a c++ type or a synthetic jsrootgen. |
579 | */ |
580 | QString m_extensionTypeName; |
581 | QQmlJSScope::WeakConstPtr m_extensionType; |
582 | |
583 | Flags m_flags = Creatable; // all types are marked as creatable by default. |
584 | AccessSemantics m_semantics = AccessSemantics::Reference; |
585 | |
586 | QQmlJS::SourceLocation m_sourceLocation; |
587 | |
588 | QString m_moduleName; |
589 | |
590 | std::optional<QString> m_inlineComponentName; |
591 | }; |
592 | |
593 | inline QQmlJSScope::Ptr QQmlJSScope::parentScope() |
594 | { |
595 | return m_parentScope.toStrongRef(); |
596 | } |
597 | |
598 | inline QQmlJSScope::ConstPtr QQmlJSScope::parentScope() const |
599 | { |
600 | QT_WARNING_PUSH |
601 | #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU < 1400 && Q_CC_GNU >= 1200 |
602 | QT_WARNING_DISABLE_GCC("-Wuse-after-free") |
603 | #endif |
604 | return QQmlJSScope::WeakConstPtr(m_parentScope).toStrongRef(); |
605 | QT_WARNING_POP |
606 | } |
607 | |
608 | inline QMultiHash<QString, QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindings() const |
609 | { |
610 | return m_propertyBindings; |
611 | } |
612 | |
613 | inline QPair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> QQmlJSScope::ownPropertyBindings(const QString &name) const |
614 | { |
615 | return m_propertyBindings.equal_range(key: name); |
616 | } |
617 | |
618 | inline bool QQmlJSScope::hasOwnPropertyBindings(const QString &name) const |
619 | { |
620 | return m_propertyBindings.contains(key: name); |
621 | } |
622 | |
623 | inline QQmlJSMetaMethod::AbsoluteFunctionIndex QQmlJSScope::ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const |
624 | { |
625 | const int i = static_cast<int>(index); |
626 | Q_ASSERT(i >= 0); |
627 | Q_ASSERT(i < int(m_runtimeFunctionIndices.size())); |
628 | return m_runtimeFunctionIndices[i]; |
629 | } |
630 | |
631 | inline void QQmlJSScope::setInlineComponentName(const QString &inlineComponentName) |
632 | { |
633 | Q_ASSERT(isInlineComponent()); |
634 | m_inlineComponentName = inlineComponentName; |
635 | } |
636 | |
637 | inline QVector<QQmlJSScope::Ptr> QQmlJSScope::childScopes() |
638 | { |
639 | return m_childScopes; |
640 | } |
641 | |
642 | inline void QQmlJSScope::setSourceLocation(const QQmlJS::SourceLocation &sourceLocation) |
643 | { |
644 | m_sourceLocation = sourceLocation; |
645 | } |
646 | |
647 | inline QQmlJS::SourceLocation QQmlJSScope::sourceLocation() const |
648 | { |
649 | return m_sourceLocation; |
650 | } |
651 | |
652 | inline QQmlJSScope::ConstPtr QQmlJSScope::nonCompositeBaseType(const ConstPtr &type) |
653 | { |
654 | for (QQmlJSScope::ConstPtr base = type; base; base = base->baseType()) { |
655 | if (!base->isComposite()) |
656 | return base; |
657 | } |
658 | return {}; |
659 | } |
660 | |
661 | Q_DECLARE_TYPEINFO(QQmlJSScope::QmlIRCompatibilityBindingData, Q_RELOCATABLE_TYPE); |
662 | |
663 | template<> |
664 | class Q_QMLCOMPILER_EXPORT QDeferredFactory<QQmlJSScope> |
665 | { |
666 | public: |
667 | using TypeReader = std::function<QList<QQmlJS::DiagnosticMessage>( |
668 | QQmlJSImporter *importer, const QString &filePath, |
669 | const QSharedPointer<QQmlJSScope> &scopeToPopulate)>; |
670 | QDeferredFactory() = default; |
671 | |
672 | QDeferredFactory(QQmlJSImporter *importer, const QString &filePath, |
673 | const TypeReader &typeReader = {}); |
674 | |
675 | bool isValid() const |
676 | { |
677 | return !m_filePath.isEmpty() && m_importer != nullptr; |
678 | } |
679 | |
680 | QString internalName() const |
681 | { |
682 | return QFileInfo(m_filePath).baseName(); |
683 | } |
684 | |
685 | QString filePath() const { return m_filePath; } |
686 | |
687 | QQmlJSImporter* importer() const { return m_importer; } |
688 | |
689 | void setIsSingleton(bool isSingleton) |
690 | { |
691 | m_isSingleton = isSingleton; |
692 | } |
693 | |
694 | void setModuleName(const QString &moduleName) { m_moduleName = moduleName; } |
695 | |
696 | private: |
697 | friend class QDeferredSharedPointer<QQmlJSScope>; |
698 | friend class QDeferredSharedPointer<const QQmlJSScope>; |
699 | friend class QDeferredWeakPointer<QQmlJSScope>; |
700 | friend class QDeferredWeakPointer<const QQmlJSScope>; |
701 | |
702 | // Should only be called when lazy-loading the type in a deferred pointer. |
703 | void populate(const QSharedPointer<QQmlJSScope> &scope) const; |
704 | |
705 | QString m_filePath; |
706 | QQmlJSImporter *m_importer = nullptr; |
707 | bool m_isSingleton = false; |
708 | QString m_moduleName; |
709 | TypeReader m_typeReader; |
710 | }; |
711 | |
712 | using QQmlJSExportedScope = QQmlJSScope::ExportedScope<QQmlJSScope::Ptr>; |
713 | using QQmlJSImportedScope = QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr>; |
714 | |
715 | QT_END_NAMESPACE |
716 | |
717 | #endif // QQMLJSSCOPE_P_H |
718 |
Definitions
- ConstPtrWrapperIterator
- ConstPtrWrapperIterator
- operator==
- operator!=
- operator*
- operator->
- operator++
- operator++
- Export
- Export
- package
- type
- version
- revision
- ExportedScope
- ImportedScope
- QQmlJSScope
- QQmlJSScope
- operator=
- Flag
- JavaScriptIdentifier
- Kind
- BindingTargetSpecifier
- create
- scopeType
- setScopeType
- addOwnMethod
- mutableOwnMethodsRange
- ownMethods
- ownMethods
- hasOwnMethod
- addOwnEnumeration
- ownEnumerations
- ownEnumeration
- hasOwnEnumeration
- setAnnotations
- annotations
- filePath
- setFilePath
- internalName
- setInternalName
- IsComponentRoot
- setAliases
- aliases
- setInterfaceNames
- interfaceNames
- hasOwnInterface
- setOwnDeferredNames
- ownDeferredNames
- setOwnImmediateNames
- ownImmediateNames
- baseType
- baseTypeRevision
- ownModuleName
- setOwnModuleName
- clearBaseType
- addOwnProperty
- ownProperties
- ownProperty
- hasOwnProperty
- ownDefaultPropertyName
- setOwnDefaultPropertyName
- ownParentPropertyName
- setOwnParentPropertyName
- ownAttachedTypeName
- setOwnAttachedTypeName
- ownAttachedType
- extensionTypeName
- setExtensionTypeName
- ExtensionKind
- AnnotatedScope
- valueTypeName
- setValueTypeName
- valueType
- listType
- listType
- isComposite
- setIsComposite
- isJavaScriptBuiltin
- setIsJavaScriptBuiltin
- isScript
- setIsScript
- hasCustomParser
- setHasCustomParser
- isArrayScope
- setIsArrayScope
- isInlineComponent
- setIsInlineComponent
- isWrappedInImplicitComponent
- setIsWrappedInImplicitComponent
- isAssignedToUnknownProperty
- setAssignedToUnknownProperty
- extensionIsJavaScript
- setExtensionIsJavaScript
- extensionIsNamespace
- setExtensionIsNamespace
- isListProperty
- setIsListProperty
- isSingleton
- setIsSingleton
- setEnforcesScopedEnumsFlag
- setCreatableFlag
- setStructuredFlag
- setAccessSemantics
- accessSemantics
- isReferenceType
- isValueType
- childScopesBegin
- childScopesEnd
- sizeofQQmlSAElement
- QmlIRCompatibilityBindingData
- QmlIRCompatibilityBindingData
- QmlIRCompatibilityBindingData
- QQmlJSScope
- QQmlJSScope
- operator=
- hasEnforcesScopedEnumsFlag
- hasCreatableFlag
- hasStructuredFlag
- parentScope
- parentScope
- ownPropertyBindings
- ownPropertyBindings
- hasOwnPropertyBindings
- ownRuntimeFunctionIndex
- setInlineComponentName
- childScopes
- setSourceLocation
- sourceLocation
- nonCompositeBaseType
- QDeferredFactory
- QDeferredFactory
- isValid
- internalName
- filePath
- importer
- setIsSingleton
Learn Advanced QML with KDAB
Find out more