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

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