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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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