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 QQMLJSMETATYPES_P_H
5#define QQMLJSMETATYPES_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 <private/qtqmlcompilerexports_p.h>
18
19#include <QtCore/qstring.h>
20#include <QtCore/qstringlist.h>
21#include <QtCore/qsharedpointer.h>
22#include <QtCore/qvariant.h>
23#include <QtCore/qhash.h>
24
25#include <QtQml/private/qqmljssourcelocation_p.h>
26#include <QtQml/private/qqmltranslation_p.h>
27
28#include "qqmlsaconstants.h"
29#include "qqmlsa.h"
30#include "qqmljsannotation_p.h"
31
32// MetaMethod and MetaProperty have both type names and actual QQmlJSScope types.
33// When parsing the information from the relevant QML or qmltypes files, we only
34// see the names and don't have a complete picture of the types, yet. In a second
35// pass we typically fill in the types. The types may have multiple exported names
36// and the the name property of MetaProperty and MetaMethod still carries some
37// significance regarding which name was chosen to refer to the type. In a third
38// pass we may further specify the type if the context provides additional information.
39// The parent of an Item, for example, is typically not just a QtObject, but rather
40// some other Item with custom properties.
41
42QT_BEGIN_NAMESPACE
43
44enum ScriptBindingValueType : unsigned int {
45 ScriptValue_Unknown,
46 ScriptValue_Undefined // property int p: undefined
47};
48
49using QQmlJSMetaMethodType = QQmlSA::MethodType;
50
51class QQmlJSTypeResolver;
52class QQmlJSScope;
53class QQmlJSMetaEnum
54{
55 QStringList m_keys;
56 QList<int> m_values; // empty if values unknown.
57 QString m_name;
58 QString m_alias;
59 QString m_typeName;
60 QSharedPointer<const QQmlJSScope> m_type;
61 bool m_isFlag = false;
62 bool m_scoped = true;
63
64public:
65 QQmlJSMetaEnum() = default;
66 explicit QQmlJSMetaEnum(QString name) : m_name(std::move(name)) {}
67
68 bool isValid() const { return !m_name.isEmpty(); }
69
70 QString name() const { return m_name; }
71 void setName(const QString &name) { m_name = name; }
72
73 QString alias() const { return m_alias; }
74 void setAlias(const QString &alias) { m_alias = alias; }
75
76 bool isFlag() const { return m_isFlag; }
77 void setIsFlag(bool isFlag) { m_isFlag = isFlag; }
78
79 bool isScoped() const { return m_scoped; }
80 void setScoped(bool v) { m_scoped = v; }
81
82 void addKey(const QString &key) { m_keys.append(t: key); }
83 QStringList keys() const { return m_keys; }
84
85 void addValue(int value) { m_values.append(t: value); }
86 QList<int> values() const { return m_values; }
87
88 bool hasValues() const { return !m_values.isEmpty(); }
89 int value(const QString &key) const { return m_values.value(i: m_keys.indexOf(str: key)); }
90 bool hasKey(const QString &key) const { return m_keys.indexOf(str: key) != -1; }
91
92 QString typeName() const { return m_typeName; }
93 void setTypeName(const QString &typeName) { m_typeName = typeName; }
94
95 QSharedPointer<const QQmlJSScope> type() const { return m_type; }
96 void setType(const QSharedPointer<const QQmlJSScope> &type) { m_type = type; }
97
98 friend bool operator==(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b)
99 {
100 return a.m_keys == b.m_keys
101 && a.m_values == b.m_values
102 && a.m_name == b.m_name
103 && a.m_alias == b.m_alias
104 && a.m_isFlag == b.m_isFlag
105 && a.m_type == b.m_type;
106 }
107
108 friend bool operator!=(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b)
109 {
110 return !(a == b);
111 }
112
113 friend size_t qHash(const QQmlJSMetaEnum &e, size_t seed = 0)
114 {
115 return qHashMulti(seed, args: e.m_keys, args: e.m_values, args: e.m_name, args: e.m_alias, args: e.m_isFlag, args: e.m_type);
116 }
117};
118
119class QQmlJSMetaParameter
120{
121public:
122 /*!
123 \internal
124 A non-const parameter is passed either by pointer or by value, depending on its access
125 semantics. For types with reference access semantics, they can be const and will be passed
126 then as const pointer. Const references are treated like values (i.e. non-const).
127 */
128 enum Constness {
129 NonConst = 0,
130 Const,
131 };
132
133 QQmlJSMetaParameter(const QString &name, const QString &typeName,
134 Constness typeQualifier = NonConst,
135 QWeakPointer<const QQmlJSScope> type = {})
136 : m_name(name), m_typeName(typeName), m_type(type), m_typeQualifier(typeQualifier)
137 {
138 }
139
140 QString name() const { return m_name; }
141 void setName(const QString &name) { m_name = name; }
142 QString typeName() const { return m_typeName; }
143 void setTypeName(const QString &typeName) { m_typeName = typeName; }
144 QSharedPointer<const QQmlJSScope> type() const { return m_type.toStrongRef(); }
145 void setType(QWeakPointer<const QQmlJSScope> type) { m_type = type; }
146 Constness typeQualifier() const { return m_typeQualifier; }
147 void setTypeQualifier(Constness typeQualifier) { m_typeQualifier = typeQualifier; }
148 bool isPointer() const { return m_isPointer; }
149 void setIsPointer(bool isPointer) { m_isPointer = isPointer; }
150 bool isList() const { return m_isList; }
151 void setIsList(bool isList) { m_isList = isList; }
152
153 friend bool operator==(const QQmlJSMetaParameter &a, const QQmlJSMetaParameter &b)
154 {
155 return a.m_name == b.m_name && a.m_typeName == b.m_typeName
156 && a.m_type.toStrongRef().data() == b.m_type.toStrongRef().data()
157 && a.m_typeQualifier == b.m_typeQualifier;
158 }
159
160 friend bool operator!=(const QQmlJSMetaParameter &a, const QQmlJSMetaParameter &b)
161 {
162 return !(a == b);
163 }
164
165 friend size_t qHash(const QQmlJSMetaParameter &e, size_t seed = 0)
166 {
167 return qHashMulti(seed, args: e.m_name, args: e.m_typeName, args: e.m_type.toStrongRef().data(),
168 args: e.m_typeQualifier);
169 }
170
171private:
172 QString m_name;
173 QString m_typeName;
174 QWeakPointer<const QQmlJSScope> m_type;
175 Constness m_typeQualifier = NonConst;
176 bool m_isPointer = false;
177 bool m_isList = false;
178};
179
180class QQmlJSMetaMethod
181{
182public:
183 enum Access { Private, Protected, Public };
184 using MethodType = QQmlJSMetaMethodType;
185
186public:
187 /*! \internal
188
189 Represents a relative JavaScript function/expression index within a type
190 in a QML document. Used as a typed alternative to int with an explicit
191 invalid state.
192 */
193 enum class RelativeFunctionIndex : int { Invalid = -1 };
194
195 /*! \internal
196
197 Represents an absolute JavaScript function/expression index pointing
198 into the QV4::ExecutableCompilationUnit::runtimeFunctions array. Used as
199 a typed alternative to int with an explicit invalid state.
200 */
201 enum class AbsoluteFunctionIndex : int { Invalid = -1 };
202
203 QQmlJSMetaMethod() = default;
204 explicit QQmlJSMetaMethod(QString name, QString returnType = QString())
205 : m_name(std::move(name)),
206 m_returnTypeName(std::move(returnType)),
207 m_methodType(MethodType::Method)
208 {}
209
210 QString methodName() const { return m_name; }
211 void setMethodName(const QString &name) { m_name = name; }
212
213 QString returnTypeName() const { return m_returnTypeName; }
214 QSharedPointer<const QQmlJSScope> returnType() const { return m_returnType.toStrongRef(); }
215 void setReturnTypeName(const QString &type) { m_returnTypeName = type; }
216 void setReturnType(const QSharedPointer<const QQmlJSScope> &type)
217 {
218 m_returnType = type;
219 }
220
221 QList<QQmlJSMetaParameter> parameters() const { return m_parameters; }
222
223 QStringList parameterNames() const
224 {
225 QStringList names;
226 for (const auto &p : m_parameters)
227 names.append(t: p.name());
228
229 return names;
230 }
231
232 void setParameters(const QList<QQmlJSMetaParameter> &parameters) { m_parameters = parameters; }
233
234 void addParameter(const QQmlJSMetaParameter &p) { m_parameters.append(t: p); }
235
236 QQmlJSMetaMethodType methodType() const { return m_methodType; }
237 void setMethodType(MethodType methodType) { m_methodType = methodType; }
238
239 Access access() const { return m_methodAccess; }
240
241 int revision() const { return m_revision; }
242 void setRevision(int r) { m_revision = r; }
243
244 bool isCloned() const { return m_isCloned; }
245 void setIsCloned(bool isCloned) { m_isCloned= isCloned; }
246
247 bool isConstructor() const { return m_isConstructor; }
248 void setIsConstructor(bool isConstructor) { m_isConstructor = isConstructor; }
249
250 bool isJavaScriptFunction() const { return m_isJavaScriptFunction; }
251 void setIsJavaScriptFunction(bool isJavaScriptFunction)
252 {
253 m_isJavaScriptFunction = isJavaScriptFunction;
254 }
255
256 bool isImplicitQmlPropertyChangeSignal() const { return m_isImplicitQmlPropertyChangeSignal; }
257 void setIsImplicitQmlPropertyChangeSignal(bool isPropertyChangeSignal)
258 {
259 m_isImplicitQmlPropertyChangeSignal = isPropertyChangeSignal;
260 }
261
262 bool isValid() const { return !m_name.isEmpty(); }
263
264 const QVector<QQmlJSAnnotation>& annotations() const { return m_annotations; }
265 void setAnnotations(QVector<QQmlJSAnnotation> annotations) { m_annotations = annotations; }
266
267 void setJsFunctionIndex(RelativeFunctionIndex index)
268 {
269 Q_ASSERT(!m_isConstructor);
270 m_relativeFunctionIndex = index;
271 }
272
273 RelativeFunctionIndex jsFunctionIndex() const
274 {
275 Q_ASSERT(!m_isConstructor);
276 return m_relativeFunctionIndex;
277 }
278
279 void setConstructorIndex(RelativeFunctionIndex index)
280 {
281 Q_ASSERT(m_isConstructor);
282 m_relativeFunctionIndex = index;
283 }
284
285 RelativeFunctionIndex constructorIndex() const
286 {
287 Q_ASSERT(m_isConstructor);
288 return m_relativeFunctionIndex;
289 }
290
291 friend bool operator==(const QQmlJSMetaMethod &a, const QQmlJSMetaMethod &b)
292 {
293 return a.m_name == b.m_name && a.m_returnTypeName == b.m_returnTypeName
294 && a.m_returnType == b.m_returnType && a.m_parameters == b.m_parameters
295 && a.m_annotations == b.m_annotations && a.m_methodType == b.m_methodType
296 && a.m_methodAccess == b.m_methodAccess && a.m_revision == b.m_revision
297 && a.m_isConstructor == b.m_isConstructor;
298 }
299
300 friend bool operator!=(const QQmlJSMetaMethod &a, const QQmlJSMetaMethod &b)
301 {
302 return !(a == b);
303 }
304
305 friend size_t qHash(const QQmlJSMetaMethod &method, size_t seed = 0)
306 {
307 QtPrivate::QHashCombine combine;
308
309 seed = combine(seed, method.m_name);
310 seed = combine(seed, method.m_returnTypeName);
311 seed = combine(seed, method.m_returnType.toStrongRef().data());
312 seed = combine(seed, method.m_annotations);
313 seed = combine(seed, method.m_methodType);
314 seed = combine(seed, method.m_methodAccess);
315 seed = combine(seed, method.m_revision);
316 seed = combine(seed, method.m_isConstructor);
317
318 for (const auto &type : method.m_parameters) {
319 seed = combine(seed, type);
320 }
321
322 return seed;
323 }
324
325private:
326 QString m_name;
327 QString m_returnTypeName;
328 QWeakPointer<const QQmlJSScope> m_returnType;
329
330 QList<QQmlJSMetaParameter> m_parameters;
331 QList<QQmlJSAnnotation> m_annotations;
332
333 MethodType m_methodType = MethodType::Signal;
334 Access m_methodAccess = Public;
335 int m_revision = 0;
336 RelativeFunctionIndex m_relativeFunctionIndex = RelativeFunctionIndex::Invalid;
337 bool m_isCloned = false;
338 bool m_isConstructor = false;
339 bool m_isJavaScriptFunction = false;
340 bool m_isImplicitQmlPropertyChangeSignal = false;
341};
342
343class QQmlJSMetaProperty
344{
345 QString m_propertyName;
346 QString m_typeName;
347 QString m_read;
348 QString m_write;
349 QString m_reset;
350 QString m_bindable;
351 QString m_notify;
352 QString m_privateClass;
353 QString m_aliasExpr;
354 QWeakPointer<const QQmlJSScope> m_type;
355 QVector<QQmlJSAnnotation> m_annotations;
356 bool m_isList = false;
357 bool m_isWritable = false;
358 bool m_isPointer = false;
359 bool m_isFinal = false;
360 bool m_isConstant = false;
361 int m_revision = 0;
362 int m_index = -1; // relative property index within owning QQmlJSScope
363
364public:
365 QQmlJSMetaProperty() = default;
366
367 void setPropertyName(const QString &propertyName) { m_propertyName = propertyName; }
368 QString propertyName() const { return m_propertyName; }
369
370 void setTypeName(const QString &typeName) { m_typeName = typeName; }
371 QString typeName() const { return m_typeName; }
372
373 void setRead(const QString &read) { m_read = read; }
374 QString read() const { return m_read; }
375
376 void setWrite(const QString &write) { m_write = write; }
377 QString write() const { return m_write; }
378
379 void setReset(const QString &reset) { m_reset = reset; }
380 QString reset() const { return m_reset; }
381
382 void setBindable(const QString &bindable) { m_bindable = bindable; }
383 QString bindable() const { return m_bindable; }
384
385 void setNotify(const QString &notify) { m_notify = notify; }
386 QString notify() const { return m_notify; }
387
388 void setPrivateClass(const QString &privateClass) { m_privateClass = privateClass; }
389 QString privateClass() const { return m_privateClass; }
390 bool isPrivate() const { return !m_privateClass.isEmpty(); } // exists for convenience
391
392 void setType(const QSharedPointer<const QQmlJSScope> &type) { m_type = type; }
393 QSharedPointer<const QQmlJSScope> type() const { return m_type.toStrongRef(); }
394
395 void setAnnotations(const QList<QQmlJSAnnotation> &annotation) { m_annotations = annotation; }
396 const QList<QQmlJSAnnotation> &annotations() const { return m_annotations; }
397
398 void setIsList(bool isList) { m_isList = isList; }
399 bool isList() const { return m_isList; }
400
401 void setIsWritable(bool isWritable) { m_isWritable = isWritable; }
402 bool isWritable() const { return m_isWritable; }
403
404 void setIsPointer(bool isPointer) { m_isPointer = isPointer; }
405 bool isPointer() const { return m_isPointer; }
406
407 void setAliasExpression(const QString &aliasString) { m_aliasExpr = aliasString; }
408 QString aliasExpression() const { return m_aliasExpr; }
409 bool isAlias() const { return !m_aliasExpr.isEmpty(); } // exists for convenience
410
411 void setIsFinal(bool isFinal) { m_isFinal = isFinal; }
412 bool isFinal() const { return m_isFinal; }
413
414 void setIsConstant(bool isConstant) { m_isConstant = isConstant; }
415 bool isConstant() const { return m_isConstant; }
416
417 void setRevision(int revision) { m_revision = revision; }
418 int revision() const { return m_revision; }
419
420 void setIndex(int index) { m_index = index; }
421 int index() const { return m_index; }
422
423 bool isValid() const { return !m_propertyName.isEmpty(); }
424
425 friend bool operator==(const QQmlJSMetaProperty &a, const QQmlJSMetaProperty &b)
426 {
427 return a.m_index == b.m_index && a.m_propertyName == b.m_propertyName
428 && a.m_typeName == b.m_typeName && a.m_bindable == b.m_bindable
429 && a.m_type == b.m_type && a.m_isList == b.m_isList
430 && a.m_isWritable == b.m_isWritable && a.m_isPointer == b.m_isPointer
431 && a.m_aliasExpr == b.m_aliasExpr && a.m_revision == b.m_revision
432 && a.m_isFinal == b.m_isFinal;
433 }
434
435 friend bool operator!=(const QQmlJSMetaProperty &a, const QQmlJSMetaProperty &b)
436 {
437 return !(a == b);
438 }
439
440 friend size_t qHash(const QQmlJSMetaProperty &prop, size_t seed = 0)
441 {
442 return qHashMulti(seed, args: prop.m_propertyName, args: prop.m_typeName, args: prop.m_bindable,
443 args: prop.m_type.toStrongRef().data(), args: prop.m_isList, args: prop.m_isWritable,
444 args: prop.m_isPointer, args: prop.m_aliasExpr, args: prop.m_revision, args: prop.m_isFinal,
445 args: prop.m_index);
446 }
447};
448
449/*!
450 \class QQmlJSMetaPropertyBinding
451
452 \internal
453
454 Represents a single QML binding of a specific type. Typically, when you
455 create a new binding, you know all the details of it already, so you should
456 just set all the data at once.
457*/
458class Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSMetaPropertyBinding
459{
460 using BindingType = QQmlSA::BindingType;
461 using ScriptBindingKind = QQmlSA::ScriptBindingKind;
462
463 // needs to be kept in sync with the BindingType enum
464 struct Content {
465 using Invalid = std::monostate;
466 struct BoolLiteral {
467 bool value;
468 friend bool operator==(BoolLiteral a, BoolLiteral b) { return a.value == b.value; }
469 friend bool operator!=(BoolLiteral a, BoolLiteral b) { return !(a == b); }
470 };
471 struct NumberLiteral {
472 QT_WARNING_PUSH
473 QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
474 QT_WARNING_DISABLE_GCC("-Wfloat-equal")
475 friend bool operator==(NumberLiteral a, NumberLiteral b) { return a.value == b.value; }
476 friend bool operator!=(NumberLiteral a, NumberLiteral b) { return !(a == b); }
477 QT_WARNING_POP
478
479 double value; // ### TODO: int?
480 };
481 struct StringLiteral {
482 friend bool operator==(StringLiteral a, StringLiteral b) { return a.value == b.value; }
483 friend bool operator!=(StringLiteral a, StringLiteral b) { return !(a == b); }
484 QString value;
485 };
486 struct RegexpLiteral {
487 friend bool operator==(RegexpLiteral a, RegexpLiteral b) { return a.value == b.value; }
488 friend bool operator!=(RegexpLiteral a, RegexpLiteral b) { return !(a == b); }
489 QString value;
490 };
491 struct Null {
492 friend bool operator==(Null , Null ) { return true; }
493 friend bool operator!=(Null a, Null b) { return !(a == b); }
494 };
495 struct TranslationString {
496 friend bool operator==(TranslationString a, TranslationString b)
497 {
498 return a.text == b.text && a.comment == b.comment && a.number == b.number && a.context == b.context;
499 }
500 friend bool operator!=(TranslationString a, TranslationString b) { return !(a == b); }
501 QString text;
502 QString comment;
503 QString context;
504 int number;
505 };
506 struct TranslationById {
507 friend bool operator==(TranslationById a, TranslationById b)
508 {
509 return a.id == b.id && a.number == b.number;
510 }
511 friend bool operator!=(TranslationById a, TranslationById b) { return !(a == b); }
512 QString id;
513 int number;
514 };
515 struct Script {
516 friend bool operator==(Script a, Script b)
517 {
518 return a.index == b.index && a.kind == b.kind;
519 }
520 friend bool operator!=(Script a, Script b) { return !(a == b); }
521 QQmlJSMetaMethod::RelativeFunctionIndex index =
522 QQmlJSMetaMethod::RelativeFunctionIndex::Invalid;
523 ScriptBindingKind kind = ScriptBindingKind::Invalid;
524 ScriptBindingValueType valueType = ScriptBindingValueType::ScriptValue_Unknown;
525 };
526 struct Object {
527 friend bool operator==(Object a, Object b) { return a.value == b.value && a.typeName == b.typeName; }
528 friend bool operator!=(Object a, Object b) { return !(a == b); }
529 QString typeName;
530 QWeakPointer<const QQmlJSScope> value;
531 };
532 struct Interceptor {
533 friend bool operator==(Interceptor a, Interceptor b)
534 {
535 return a.value == b.value && a.typeName == b.typeName;
536 }
537 friend bool operator!=(Interceptor a, Interceptor b) { return !(a == b); }
538 QString typeName;
539 QWeakPointer<const QQmlJSScope> value;
540 };
541 struct ValueSource {
542 friend bool operator==(ValueSource a, ValueSource b)
543 {
544 return a.value == b.value && a.typeName == b.typeName;
545 }
546 friend bool operator!=(ValueSource a, ValueSource b) { return !(a == b); }
547 QString typeName;
548 QWeakPointer<const QQmlJSScope> value;
549 };
550 struct AttachedProperty {
551 /*
552 AttachedProperty binding is a grouping for a series of bindings
553 belonging to the same scope(QQmlJSScope::AttachedPropertyScope).
554 Thus, the attached property binding itself only exposes the
555 attaching type object. Such object is unique per the enclosing
556 scope, so attaching types attached to different QML scopes are
557 different (think of them as objects in C++ terms).
558
559 An attaching type object, being a QQmlJSScope, has bindings
560 itself. For instance:
561 ```
562 Type {
563 Keys.enabled: true
564 }
565 ```
566 tells us that "Type" has an AttachedProperty binding with
567 property name "Keys". The attaching object of that binding
568 (binding.attachingType()) has type "Keys" and a BoolLiteral
569 binding with property name "enabled".
570 */
571 friend bool operator==(AttachedProperty a, AttachedProperty b)
572 {
573 return a.value == b.value;
574 }
575 friend bool operator!=(AttachedProperty a, AttachedProperty b) { return !(a == b); }
576 QWeakPointer<const QQmlJSScope> value;
577 };
578 struct GroupProperty {
579 /* Given a group property declaration like
580 anchors.left: root.left
581 the QQmlJSMetaPropertyBinding will have name "anchors", and a m_bindingContent
582 of type GroupProperty, with groupScope pointing to the scope introudced by anchors
583 In that scope, there will be another QQmlJSMetaPropertyBinding, with name "left" and
584 m_bindingContent Script (for root.left).
585 There should never be more than one GroupProperty for the same name in the same
586 scope, though: If the scope also contains anchors.top: root.top that should reuse the
587 GroupProperty content (and add a top: root.top binding in it). There might however
588 still be an additional object or script binding ( anchors: {left: foo, right: bar };
589 anchors: root.someFunction() ) or another binding to the property in a "derived"
590 type.
591
592 ### TODO: Obtaining the effective binding result requires some resolving function
593 */
594 QWeakPointer<const QQmlJSScope> groupScope;
595 friend bool operator==(GroupProperty a, GroupProperty b) { return a.groupScope == b.groupScope; }
596 friend bool operator!=(GroupProperty a, GroupProperty b) { return !(a == b); }
597 };
598 using type = std::variant<Invalid, BoolLiteral, NumberLiteral, StringLiteral,
599 RegexpLiteral, Null, TranslationString,
600 TranslationById, Script, Object, Interceptor,
601 ValueSource, AttachedProperty, GroupProperty
602 >;
603 };
604 using BindingContent = Content::type;
605
606 QQmlJS::SourceLocation m_sourceLocation;
607 QString m_propertyName; // TODO: this is a debug-only information
608 BindingContent m_bindingContent;
609
610 void ensureSetBindingTypeOnce()
611 {
612 Q_ASSERT(bindingType() == BindingType::Invalid);
613 }
614
615 bool isLiteralBinding() const { return isLiteralBinding(type: bindingType()); }
616
617
618public:
619 static bool isLiteralBinding(BindingType type)
620 {
621 return type == BindingType::BoolLiteral || type == BindingType::NumberLiteral
622 || type == BindingType::StringLiteral || type == BindingType::RegExpLiteral
623 || type == BindingType::Null; // special. we record it as literal
624 }
625
626 QQmlJSMetaPropertyBinding();
627 QQmlJSMetaPropertyBinding(QQmlJS::SourceLocation location) : m_sourceLocation(location) { }
628 explicit QQmlJSMetaPropertyBinding(QQmlJS::SourceLocation location, const QString &propName)
629 : m_sourceLocation(location), m_propertyName(propName)
630 {
631 }
632 explicit QQmlJSMetaPropertyBinding(QQmlJS::SourceLocation location,
633 const QQmlJSMetaProperty &prop)
634 : QQmlJSMetaPropertyBinding(location, prop.propertyName())
635 {
636 }
637
638 void setPropertyName(const QString &propertyName) { m_propertyName = propertyName; }
639 QString propertyName() const { return m_propertyName; }
640
641 const QQmlJS::SourceLocation &sourceLocation() const { return m_sourceLocation; }
642
643 BindingType bindingType() const { return BindingType(m_bindingContent.index()); }
644
645 bool isValid() const;
646
647 void setStringLiteral(QAnyStringView value)
648 {
649 ensureSetBindingTypeOnce();
650 m_bindingContent = Content::StringLiteral { .value: value.toString() };
651 }
652
653 void
654 setScriptBinding(QQmlJSMetaMethod::RelativeFunctionIndex value, ScriptBindingKind kind,
655 ScriptBindingValueType valueType = ScriptBindingValueType::ScriptValue_Unknown)
656 {
657 ensureSetBindingTypeOnce();
658 m_bindingContent = Content::Script { .index: value, .kind: kind, .valueType: valueType };
659 }
660
661 void setGroupBinding(const QSharedPointer<const QQmlJSScope> &groupScope)
662 {
663 ensureSetBindingTypeOnce();
664 m_bindingContent = Content::GroupProperty { .groupScope: groupScope };
665 }
666
667 void setAttachedBinding(const QSharedPointer<const QQmlJSScope> &attachingScope)
668 {
669 ensureSetBindingTypeOnce();
670 m_bindingContent = Content::AttachedProperty { .value: attachingScope };
671 }
672
673 void setBoolLiteral(bool value)
674 {
675 ensureSetBindingTypeOnce();
676 m_bindingContent = Content::BoolLiteral { .value: value };
677 }
678
679 void setNullLiteral()
680 {
681 ensureSetBindingTypeOnce();
682 m_bindingContent = Content::Null {};
683 }
684
685 void setNumberLiteral(double value)
686 {
687 ensureSetBindingTypeOnce();
688 m_bindingContent = Content::NumberLiteral { .value: value };
689 }
690
691 void setRegexpLiteral(QAnyStringView value)
692 {
693 ensureSetBindingTypeOnce();
694 m_bindingContent = Content::RegexpLiteral { .value: value.toString() };
695 }
696
697 void setTranslation(QStringView text, QStringView comment, QStringView context, int number)
698 {
699 ensureSetBindingTypeOnce();
700 m_bindingContent =
701 Content::TranslationString{ .text: text.toString(), .comment: comment.toString(), .context: context.toString(), .number: number };
702 }
703
704 void setTranslationId(QStringView id, int number)
705 {
706 ensureSetBindingTypeOnce();
707 m_bindingContent = Content::TranslationById{ .id: id.toString(), .number: number };
708 }
709
710 void setObject(const QString &typeName, const QSharedPointer<const QQmlJSScope> &type)
711 {
712 ensureSetBindingTypeOnce();
713 m_bindingContent = Content::Object { .typeName: typeName, .value: type };
714 }
715
716 void setInterceptor(const QString &typeName, const QSharedPointer<const QQmlJSScope> &type)
717 {
718 ensureSetBindingTypeOnce();
719 m_bindingContent = Content::Interceptor { .typeName: typeName, .value: type };
720 }
721
722 void setValueSource(const QString &typeName, const QSharedPointer<const QQmlJSScope> &type)
723 {
724 ensureSetBindingTypeOnce();
725 m_bindingContent = Content::ValueSource { .typeName: typeName, .value: type };
726 }
727
728 QString literalTypeName() const;
729
730 // ### TODO: here and below: Introduce an allowConversion parameter, if yes, enable conversions e.g. bool -> number?
731 bool boolValue() const;
732
733 double numberValue() const;
734
735 QString stringValue() const;
736
737 QString regExpValue() const;
738
739 QQmlTranslation translationDataValue(QString qmlFileNameForContext = QStringLiteral("")) const;
740
741 QSharedPointer<const QQmlJSScope> literalType(const QQmlJSTypeResolver *resolver) const;
742
743 QQmlJSMetaMethod::RelativeFunctionIndex scriptIndex() const
744 {
745 if (auto *script = std::get_if<Content::Script>(ptr: &m_bindingContent))
746 return script->index;
747 // warn
748 return QQmlJSMetaMethod::RelativeFunctionIndex::Invalid;
749 }
750
751 ScriptBindingKind scriptKind() const
752 {
753 if (auto *script = std::get_if<Content::Script>(ptr: &m_bindingContent))
754 return script->kind;
755 // warn
756 return ScriptBindingKind::Invalid;
757 }
758
759 ScriptBindingValueType scriptValueType() const
760 {
761 if (auto *script = std::get_if<Content::Script>(ptr: &m_bindingContent))
762 return script->valueType;
763 // warn
764 return ScriptBindingValueType::ScriptValue_Unknown;
765 }
766
767 QString objectTypeName() const
768 {
769 if (auto *object = std::get_if<Content::Object>(ptr: &m_bindingContent))
770 return object->typeName;
771 // warn
772 return {};
773 }
774 QSharedPointer<const QQmlJSScope> objectType() const
775 {
776 if (auto *object = std::get_if<Content::Object>(ptr: &m_bindingContent))
777 return object->value.lock();
778 // warn
779 return {};
780 }
781
782 QString interceptorTypeName() const
783 {
784 if (auto *interceptor = std::get_if<Content::Interceptor>(ptr: &m_bindingContent))
785 return interceptor->typeName;
786 // warn
787 return {};
788 }
789 QSharedPointer<const QQmlJSScope> interceptorType() const
790 {
791 if (auto *interceptor = std::get_if<Content::Interceptor>(ptr: &m_bindingContent))
792 return interceptor->value.lock();
793 // warn
794 return {};
795 }
796
797 QString valueSourceTypeName() const
798 {
799 if (auto *valueSource = std::get_if<Content::ValueSource>(ptr: &m_bindingContent))
800 return valueSource->typeName;
801 // warn
802 return {};
803 }
804 QSharedPointer<const QQmlJSScope> valueSourceType() const
805 {
806 if (auto *valueSource = std::get_if<Content::ValueSource>(ptr: &m_bindingContent))
807 return valueSource->value.lock();
808 // warn
809 return {};
810 }
811
812 QSharedPointer<const QQmlJSScope> groupType() const
813 {
814 if (auto *group = std::get_if<Content::GroupProperty>(ptr: &m_bindingContent))
815 return group->groupScope.lock();
816 // warn
817 return {};
818 }
819
820 QSharedPointer<const QQmlJSScope> attachingType() const
821 {
822 if (auto *attached = std::get_if<Content::AttachedProperty>(ptr: &m_bindingContent))
823 return attached->value.lock();
824 // warn
825 return {};
826 }
827
828 bool hasLiteral() const
829 {
830 // TODO: Assumption: if the type is literal, we must have one
831 return isLiteralBinding();
832 }
833 bool hasObject() const { return bindingType() == BindingType::Object; }
834 bool hasInterceptor() const
835 {
836 return bindingType() == BindingType::Interceptor;
837 }
838 bool hasValueSource() const
839 {
840 return bindingType() == BindingType::ValueSource;
841 }
842
843 friend bool operator==(const QQmlJSMetaPropertyBinding &a, const QQmlJSMetaPropertyBinding &b)
844 {
845 return a.m_propertyName == b.m_propertyName
846 && a.m_bindingContent == b.m_bindingContent
847 && a.m_sourceLocation == b.m_sourceLocation;
848 }
849
850 friend bool operator!=(const QQmlJSMetaPropertyBinding &a, const QQmlJSMetaPropertyBinding &b)
851 {
852 return !(a == b);
853 }
854
855 friend size_t qHash(const QQmlJSMetaPropertyBinding &binding, size_t seed = 0)
856 {
857 // we don't need to care about the actual binding content when hashing
858 return qHashMulti(seed, args: binding.m_propertyName, args: binding.m_sourceLocation,
859 args: binding.bindingType());
860 }
861};
862
863struct Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSMetaSignalHandler
864{
865 QStringList signalParameters;
866 bool isMultiline;
867};
868
869QT_END_NAMESPACE
870
871#endif // QQMLJSMETATYPES_P_H
872

source code of qtdeclarative/src/qmlcompiler/qqmljsmetatypes_p.h