1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "qqmljsregistercontent_p.h"
5
6#include <variant>
7
8QT_BEGIN_NAMESPACE
9
10using namespace Qt::StringLiterals;
11
12struct QQmlJSRegisterContentPrivate
13{
14public:
15
16 using ContentVariant = QQmlJSRegisterContent::ContentVariant;
17
18 enum class Kind : size_t {
19 Type, Property, Enum, Method, ImportNamespace, Conversion, MethodCall
20 };
21
22 struct ConvertedTypes
23 {
24 QList<QQmlJSRegisterContent> origins;
25 QQmlJSScope::ConstPtr result;
26 QQmlJSRegisterContent resultScope;
27
28 friend size_t qHash(const ConvertedTypes &types, size_t seed = 0)
29 {
30 return qHashMulti(seed, args: types.origins, args: types.result, args: types.resultScope);
31 }
32
33 friend bool operator==(const ConvertedTypes &a, const ConvertedTypes &b)
34 {
35 return a.origins == b.origins && a.result == b.result && a.resultScope == b.resultScope;
36 }
37
38 friend bool operator!=(const ConvertedTypes &a, const ConvertedTypes &b)
39 {
40 return !(a == b);
41 }
42 };
43
44 struct PropertyLookup
45 {
46 QQmlJSMetaProperty property;
47 int baseLookupIndex = QQmlJSRegisterContent::InvalidLookupIndex;
48 int resultLookupIndex = QQmlJSRegisterContent::InvalidLookupIndex;
49
50 friend size_t qHash(const PropertyLookup &property, size_t seed = 0)
51 {
52 return qHashMulti(
53 seed, args: property.property, args: property.baseLookupIndex, args: property.resultLookupIndex);
54 }
55
56 friend bool operator==(const PropertyLookup &a, const PropertyLookup &b)
57 {
58 return a.baseLookupIndex == b.baseLookupIndex
59 && a.resultLookupIndex == b.resultLookupIndex
60 && a.property == b.property;
61 }
62
63 friend bool operator!=(const PropertyLookup &a, const PropertyLookup &b)
64 {
65 return !(a == b);
66 }
67 };
68
69 using Content = std::variant<
70 std::pair<QQmlJSScope::ConstPtr, int>,
71 PropertyLookup,
72 std::pair<QQmlJSMetaEnum, QString>,
73 std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>,
74 std::pair<uint, QQmlJSScope::ConstPtr>,
75 ConvertedTypes,
76 QQmlJSMetaMethod
77 >;
78
79 friend size_t qHash(const QQmlJSRegisterContentPrivate &registerContent, size_t seed = 0)
80 {
81 seed = qHashMulti(
82 seed, args: registerContent.m_storage, args: registerContent.m_content.index(),
83 args: registerContent.m_variant, args: registerContent.m_scope);
84
85 switch (Kind(registerContent.m_content.index())) {
86 case Kind::Type:
87 return qHash(key: std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v: registerContent.m_content),
88 seed);
89 case Kind::Property:
90 return qHash(property: std::get<PropertyLookup>(v: registerContent.m_content), seed);
91 case Kind::Enum:
92 return qHash(key: std::get<std::pair<QQmlJSMetaEnum, QString>>(v: registerContent.m_content),
93 seed);
94 case Kind::Method:
95 return qHash(key: std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(
96 v: registerContent.m_content), seed);
97 case Kind::ImportNamespace:
98 return qHash(key: std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(
99 v: registerContent.m_content), seed);
100 case Kind::Conversion:
101 return qHash(types: std::get<ConvertedTypes>(v: registerContent.m_content), seed);
102 case Kind::MethodCall:
103 return qHash(method: std::get<QQmlJSMetaMethod>(v: registerContent.m_content), seed);
104 }
105
106 Q_UNREACHABLE_RETURN(seed);
107 }
108
109 friend bool operator==(
110 const QQmlJSRegisterContentPrivate &a, const QQmlJSRegisterContentPrivate &b)
111 {
112 return a.m_storage == b.m_storage && a.m_variant == b.m_variant
113 && a.m_scope == b.m_scope && a.m_content == b.m_content;
114 }
115
116 friend bool operator!=(
117 const QQmlJSRegisterContentPrivate &a, const QQmlJSRegisterContentPrivate &b)
118 {
119 return !(a == b);
120 }
121
122 QQmlJSRegisterContent m_storage;
123 QQmlJSRegisterContent m_scope;
124 Content m_content;
125 ContentVariant m_variant = ContentVariant::Unknown;
126
127 QQmlJSRegisterContent m_original;
128 QQmlJSRegisterContent m_shadowed;
129
130 int resultLookupIndex() const
131 {
132 switch (Kind(m_content.index())) {
133 case Kind::Type:
134 return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v: m_content).second;
135 case Kind::Property:
136 return std::get<PropertyLookup>(v: m_content).resultLookupIndex;
137 default:
138 return QQmlJSRegisterContent::InvalidLookupIndex;
139 }
140 }
141
142 void setType(const QQmlJSScope::ConstPtr &type)
143 {
144 switch (Kind(m_content.index())) {
145 case Kind::Type:
146 std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v&: m_content).first = type;
147 return;
148 case Kind::Property:
149 std::get<PropertyLookup>(v&: m_content).property.setType(type);
150 return;
151 case Kind::Enum:
152 std::get<std::pair<QQmlJSMetaEnum, QString>>(v&: m_content).first.setType(type);
153 return;
154 case Kind::Method:
155 std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(v&: m_content)
156 .second = type;
157 return;
158 case Kind::ImportNamespace:
159 std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(v&: m_content).second = type;
160 return;
161 case Kind::Conversion:
162 std::get<ConvertedTypes>(v&: m_content).result = type;
163 return;
164 case Kind::MethodCall:
165 std::get<QQmlJSMetaMethod>(v&: m_content).setReturnType({ type });
166 return;
167 }
168
169 Q_UNREACHABLE_RETURN();
170 }
171
172private:
173 friend class QQmlJSRegisterContentPool;
174
175 QQmlJSRegisterContentPrivate() = default;
176 ~QQmlJSRegisterContentPrivate() = default;
177 QQmlJSRegisterContentPrivate(const QQmlJSRegisterContentPrivate &) = default;
178 QQmlJSRegisterContentPrivate(QQmlJSRegisterContentPrivate &&) = default;
179 QQmlJSRegisterContentPrivate &operator=(const QQmlJSRegisterContentPrivate &) = default;
180 QQmlJSRegisterContentPrivate &operator=(QQmlJSRegisterContentPrivate &&) = default;
181};
182
183bool QQmlJSRegisterContent::isValid() const
184{
185 return !containedType().isNull();
186};
187
188QString QQmlJSRegisterContent::descriptiveName() const
189{
190 using Kind = QQmlJSRegisterContentPrivate::Kind;
191
192 if (!d || (!d->m_storage.isValid() && containedType().isNull()))
193 return u"(invalid type)"_s;
194
195 const auto scope = [this]() -> QString {
196 if (!d->m_scope.isValid())
197 return u"(invalid type)::"_s;
198
199 const QQmlJSScope::ConstPtr scopeContained = d->m_scope.containedType();
200 if (scopeContained.isNull())
201 return u"(invalid type)::"_s;
202
203 return (scopeContained->internalName().isEmpty()
204 ? (scopeContained->filePath().isEmpty()
205 ? u"??"_s
206 : (u"(component in "_s + scopeContained->filePath() + u")"_s))
207 : scopeContained->internalName())
208 + u"::"_s;
209 };
210
211 QString result;
212 switch (Kind(d->m_content.index())) {
213 case Kind::Type: {
214 const QQmlJSScope::ConstPtr contained = type();
215 result += contained->internalName();
216 const QQmlJSScope::ConstPtr stored = d->m_storage.containedType();
217 if (stored && stored->internalName() != contained->internalName())
218 result += u" stored as "_s + stored->internalName();
219 return result;
220 }
221 case Kind::Property: {
222 const QQmlJSMetaProperty prop = property();
223 result += scope() + prop.propertyName() + u" with type "_s + prop.typeName();
224
225 QStringList details;
226 if (original().isValid() && !prop.type()->internalName().isEmpty())
227 details.append(t: u"adjusted to " + prop.type()->internalName());
228 const QQmlJSScope::ConstPtr stored = d->m_storage.containedType();
229 if (stored && stored->internalName() != prop.typeName())
230 details.append(t: u"stored as "_s + stored->internalName());
231
232 if (!details.isEmpty())
233 result += u" (%1)"_s.arg(a: details.join(sep: u", "));
234
235 return result;
236 }
237 case Kind::Method: {
238 const auto methods = method();
239 if (methods.isEmpty())
240 result = scope() + u"(unknown method)"_s;
241 else
242 result = scope() + methods[0].methodName() + u"(...)"_s;
243 if (d->m_storage.isValid())
244 return result + u" (stored as "_s + d->m_storage.containedType()->internalName() + u")";
245 return result;
246 }
247 case Kind::Enum: {
248 const QString enumName = enumeration().name();
249 const QString memberName = enumMember();
250 if (memberName.isEmpty())
251 result = scope() + enumName;
252 else
253 result = scope() + enumName + u"::"_s + memberName;
254 if (d->m_storage.isValid())
255 return result + u" (stored as "_s + d->m_storage.containedType()->internalName() + u")";
256 return result;
257 }
258 case Kind::ImportNamespace: {
259 return u"import namespace %1"_s.arg(a: importNamespace());
260 }
261 case Kind::Conversion: {
262 return u"conversion to %1"_s.arg(a: conversionResultType()->internalName());
263 }
264 case Kind::MethodCall: {
265 const QQmlJSMetaMethod &method = std::get<QQmlJSMetaMethod>(v&: d->m_content);
266 return u"call to method %1, returning %2"_s.arg(
267 args: method.methodName(), args: method.returnTypeName());
268 }
269 }
270
271 Q_UNREACHABLE_RETURN(result + u"wat?"_s);
272}
273
274QString QQmlJSRegisterContent::containedTypeName() const
275{
276 QQmlJSScope::ConstPtr type;
277
278 switch (variant()) {
279 case QQmlJSRegisterContent::MetaType:
280 type = scopeType();
281 break;
282 default:
283 type = containedType();
284 break;
285 }
286
287 return QQmlJSScope::prettyName(
288 name: type->internalName().isEmpty() ? type->baseTypeName() : type->internalName());
289}
290
291bool QQmlJSRegisterContent::isType() const
292{
293 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Type);
294}
295
296bool QQmlJSRegisterContent::isProperty() const
297{
298 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Property);
299}
300
301bool QQmlJSRegisterContent::isEnumeration() const
302{
303 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Enum);
304}
305
306bool QQmlJSRegisterContent::isMethod() const
307{
308 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Method);
309}
310
311bool QQmlJSRegisterContent::isImportNamespace() const
312{
313 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::ImportNamespace);
314}
315
316bool QQmlJSRegisterContent::isConversion() const
317{
318 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Conversion);
319}
320
321bool QQmlJSRegisterContent::isMethodCall() const
322{
323 return d && d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::MethodCall);
324}
325
326bool QQmlJSRegisterContent::isList() const
327{
328 using Kind = QQmlJSRegisterContentPrivate::Kind;
329
330 if (!d)
331 return false;
332
333 switch (Kind(d->m_content.index())) {
334 case Kind::Type:
335 return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v&: d->m_content).first
336 ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
337 case Kind::Property:
338 return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(v&: d->m_content).property.type()
339 ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
340 case Kind::Conversion:
341 return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(v&: d->m_content).result
342 ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
343 case Kind::MethodCall:
344 return std::get<QQmlJSMetaMethod>(v&: d->m_content).returnType()
345 ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
346 default:
347 return false;
348 }
349}
350
351bool QQmlJSRegisterContent::isWritable() const
352{
353 using Kind = QQmlJSRegisterContentPrivate::Kind;
354
355 if (!d)
356 return false;
357
358 switch (Kind(d->m_content.index())) {
359 case Kind::Property:
360 return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(v&: d->m_content)
361 .property.isWritable();
362
363 // TODO: What can we actually write?
364 default:
365 break;
366 }
367
368 return true;
369}
370
371bool QQmlJSRegisterContent::isJavaScriptReturnValue() const
372{
373 return d && isMethodCall() && std::get<QQmlJSMetaMethod>(v&: d->m_content).isJavaScriptFunction();
374}
375
376/*!
377 * \internal
378 * Precondition: This is an attachment.
379 * Return the type that does the attaching.
380 */
381QQmlJSRegisterContent QQmlJSRegisterContent::attacher() const
382{
383 Q_ASSERT(d);
384 Q_ASSERT(d->m_variant == Attachment);
385 return scope();
386}
387
388/*!
389 * \internal
390 * Precondition: This is an attachment.
391 * Return the type of the object the attachment is attached to.
392 */
393QQmlJSRegisterContent QQmlJSRegisterContent::attachee() const
394{
395 Q_ASSERT(d);
396 Q_ASSERT(d->m_variant == Attachment);
397 QQmlJSRegisterContent attachee = attacher().scope();
398 while (attachee.variant() == ModulePrefix)
399 attachee = attachee.scope();
400 return attachee;
401}
402
403QQmlJSScope::ConstPtr QQmlJSRegisterContent::storedType() const
404{
405 return d ? d->m_storage.containedType() : QQmlJSScope::ConstPtr();
406}
407
408QQmlJSScope::ConstPtr QQmlJSRegisterContent::containedType() const
409{
410 if (!d)
411 return QQmlJSScope::ConstPtr();
412 if (isType())
413 return type();
414 if (isProperty())
415 return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(v&: d->m_content).property.type();
416 if (isEnumeration())
417 return std::get<std::pair<QQmlJSMetaEnum, QString>>(v&: d->m_content).first.type();
418 if (isMethod())
419 return methodType();
420 if (isImportNamespace())
421 return importNamespaceType();
422 if (isConversion())
423 return conversionResultType();
424 if (isMethodCall())
425 return std::get<QQmlJSMetaMethod>(v&: d->m_content).returnType();
426
427 Q_UNREACHABLE_RETURN({});
428}
429
430QQmlJSScope::ConstPtr QQmlJSRegisterContent::scopeType() const
431{
432 return d ? d->m_scope.containedType() : QQmlJSScope::ConstPtr();
433}
434
435QQmlJSScope::ConstPtr QQmlJSRegisterContent::type() const
436{
437 Q_ASSERT(isType());
438 return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v&: d->m_content).first;
439}
440
441QQmlJSMetaProperty QQmlJSRegisterContent::property() const
442{
443 Q_ASSERT(isProperty());
444 return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(v&: d->m_content).property;
445}
446
447int QQmlJSRegisterContent::baseLookupIndex() const
448{
449 Q_ASSERT(isProperty());
450 return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(v&: d->m_content).baseLookupIndex;
451}
452
453int QQmlJSRegisterContent::resultLookupIndex() const
454{
455 return d ? d->resultLookupIndex() : InvalidLookupIndex;
456}
457
458QQmlJSMetaEnum QQmlJSRegisterContent::enumeration() const
459{
460 Q_ASSERT(isEnumeration());
461 return std::get<std::pair<QQmlJSMetaEnum, QString>>(v&: d->m_content).first;
462}
463
464QString QQmlJSRegisterContent::enumMember() const
465{
466 Q_ASSERT(isEnumeration());
467 return std::get<std::pair<QQmlJSMetaEnum, QString>>(v&: d->m_content).second;
468}
469
470QList<QQmlJSMetaMethod> QQmlJSRegisterContent::method() const
471{
472 Q_ASSERT(isMethod());
473 return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(v&: d->m_content).first;
474}
475
476QQmlJSScope::ConstPtr QQmlJSRegisterContent::methodType() const
477{
478 Q_ASSERT(isMethod());
479 return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(v&: d->m_content).second;
480}
481
482uint QQmlJSRegisterContent::importNamespace() const
483{
484 Q_ASSERT(isImportNamespace());
485 return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(v&: d->m_content).first;
486}
487
488QQmlJSScope::ConstPtr QQmlJSRegisterContent::importNamespaceType() const
489{
490 Q_ASSERT(isImportNamespace());
491 return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(v&: d->m_content).second;
492}
493
494QQmlJSScope::ConstPtr QQmlJSRegisterContent::conversionResultType() const
495{
496 Q_ASSERT(isConversion());
497 return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(v&: d->m_content).result;
498}
499
500QQmlJSRegisterContent QQmlJSRegisterContent::conversionResultScope() const
501{
502 Q_ASSERT(isConversion());
503 return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(v&: d->m_content).resultScope;
504}
505
506QList<QQmlJSRegisterContent> QQmlJSRegisterContent::conversionOrigins() const
507{
508 Q_ASSERT(isConversion());
509 return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(v&: d->m_content).origins;
510}
511
512QQmlJSMetaMethod QQmlJSRegisterContent::methodCall() const
513{
514 Q_ASSERT(isMethodCall());
515 return std::get<QQmlJSMetaMethod>(v&: d->m_content);
516}
517
518QQmlJSRegisterContent::ContentVariant QQmlJSRegisterContent::variant() const
519{
520 return d ? d->m_variant : Unknown;
521}
522
523QQmlJSRegisterContent QQmlJSRegisterContent::scope() const
524{
525 return d ? d->m_scope : QQmlJSRegisterContent();
526}
527
528QQmlJSRegisterContent QQmlJSRegisterContent::storage() const
529{
530 return d ? d->m_storage : QQmlJSRegisterContent();
531}
532
533QQmlJSRegisterContent QQmlJSRegisterContent::original() const
534{
535 return d ? d->m_original : QQmlJSRegisterContent();
536}
537
538QQmlJSRegisterContent QQmlJSRegisterContent::shadowed() const
539{
540 return d ? d->m_shadowed : QQmlJSRegisterContent();
541}
542
543QQmlJSRegisterContentPool::QQmlJSRegisterContentPool() = default;
544QQmlJSRegisterContentPool::~QQmlJSRegisterContentPool() = default;
545
546QQmlJSRegisterContent QQmlJSRegisterContentPool::createType(
547 const QQmlJSScope::ConstPtr &type, int resultLookupIndex,
548 QQmlJSRegisterContent::ContentVariant variant, QQmlJSRegisterContent scope)
549{
550 QQmlJSRegisterContentPrivate *result = create(scope, variant);
551 result->m_content = std::make_pair(x: type, y&: resultLookupIndex);
552 return result;
553}
554
555QQmlJSRegisterContent QQmlJSRegisterContentPool::createProperty(
556 const QQmlJSMetaProperty &property, int baseLookupIndex, int resultLookupIndex,
557 QQmlJSRegisterContent::ContentVariant variant, QQmlJSRegisterContent scope)
558{
559 QQmlJSRegisterContentPrivate *result = create(scope, variant);
560 result->m_content = QQmlJSRegisterContentPrivate::PropertyLookup {
561 .property: property,
562 .baseLookupIndex: baseLookupIndex,
563 .resultLookupIndex: resultLookupIndex
564 };
565 return result;
566}
567
568QQmlJSRegisterContent QQmlJSRegisterContentPool::createEnumeration(
569 const QQmlJSMetaEnum &enumeration, const QString &enumMember,
570 QQmlJSRegisterContent::ContentVariant variant, QQmlJSRegisterContent scope)
571{
572 QQmlJSRegisterContentPrivate *result = create(scope, variant);
573 result->m_content = std::make_pair(x: enumeration, y: enumMember);
574 return result;
575}
576
577QQmlJSRegisterContent QQmlJSRegisterContentPool::createMethod(
578 const QList<QQmlJSMetaMethod> &methods, const QQmlJSScope::ConstPtr &methodType,
579 QQmlJSRegisterContent::ContentVariant variant, QQmlJSRegisterContent scope)
580{
581 // Methods can only be stored in QJSValue.
582 Q_ASSERT(methodType->internalName() == u"QJSValue"_s);
583 QQmlJSRegisterContentPrivate *result = create(scope, variant);
584 result->m_content = std::make_pair(x: methods, y: methodType);
585 return result;
586}
587
588QQmlJSRegisterContent QQmlJSRegisterContentPool::createMethodCall(
589 const QQmlJSMetaMethod &method, const QQmlJSScope::ConstPtr &returnType,
590 QQmlJSRegisterContent scope)
591{
592 QQmlJSRegisterContentPrivate *result = create(scope, variant: ContentVariant::MethodCall);
593
594 QQmlJSMetaMethod resultMethod = method;
595 resultMethod.setReturnType({ returnType });
596 resultMethod.setReturnTypeName(returnType->internalName());
597 result->m_content = std::move(resultMethod);
598
599 return result;
600}
601
602QQmlJSRegisterContent QQmlJSRegisterContentPool::createImportNamespace(
603 uint importNamespaceStringId, const QQmlJSScope::ConstPtr &importNamespaceType,
604 QQmlJSRegisterContent::ContentVariant variant, QQmlJSRegisterContent scope)
605{
606 QQmlJSRegisterContentPrivate *result = create(scope, variant);
607 result->m_content = std::make_pair(x&: importNamespaceStringId, y: importNamespaceType);
608 return result;
609}
610
611QQmlJSRegisterContent QQmlJSRegisterContentPool::createConversion(
612 const QList<QQmlJSRegisterContent> &origins, const QQmlJSScope::ConstPtr &conversion,
613 QQmlJSRegisterContent conversionScope, ContentVariant variant,
614 QQmlJSRegisterContent scope)
615{
616 QQmlJSRegisterContentPrivate *result = create(scope, variant);
617
618 result->m_content = QQmlJSRegisterContentPrivate::ConvertedTypes {
619 .origins: origins,
620 .result: conversion,
621 .resultScope: conversionScope
622 };
623
624 return result;
625}
626
627QQmlJSRegisterContent QQmlJSRegisterContentPool::storedIn(
628 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &newStoredType)
629{
630 Q_ASSERT(content.d);
631 QQmlJSRegisterContentPrivate *result = clone(from: content.d);
632 result->m_storage = createType(
633 type: newStoredType, resultLookupIndex: QQmlJSRegisterContent::InvalidLookupIndex, variant: ContentVariant::Storage);
634 return result;
635}
636
637QQmlJSRegisterContent QQmlJSRegisterContentPool::castTo(
638 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &newContainedType)
639{
640 // This is not a conversion but a run time cast. It may result in null or undefined.
641 QQmlJSRegisterContentPrivate *result = create(scope: content, variant: ContentVariant::Cast);
642 result->m_content = std::make_pair(x: newContainedType, y: result->resultLookupIndex());
643 return result;
644}
645
646void QQmlJSRegisterContentPool::storeType(
647 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &stored)
648{
649 QQmlJSRegisterContentPrivate *d = content.d;
650
651 Q_ASSERT(d);
652 Q_ASSERT(d->m_storage.isNull());
653 d->m_storage = createType(
654 type: stored, resultLookupIndex: QQmlJSRegisterContent::InvalidLookupIndex, variant: ContentVariant::Storage);
655}
656
657void QQmlJSRegisterContentPool::adjustType(
658 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &adjusted)
659{
660 QQmlJSRegisterContentPrivate *d = content.d;
661
662 Q_ASSERT(d);
663 Q_ASSERT(d->m_original.isNull());
664 d->m_original = clone(from: d);
665 d->setType(adjusted);
666}
667
668void QQmlJSRegisterContentPool::generalizeType(
669 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &generalized)
670{
671 QQmlJSRegisterContentPrivate *d = content.d;
672
673 Q_ASSERT(d);
674 Q_ASSERT(d->m_shadowed.isNull());
675 d->m_shadowed = clone(from: d);
676 d->setType(generalized);
677}
678
679void QQmlJSRegisterContentPool::setAllocationMode(AllocationMode mode)
680{
681 m_checkpoint = (mode == Temporary) ? m_pool.size() : -1;
682}
683
684void QQmlJSRegisterContentPool::clearTemporaries()
685{
686 if (m_checkpoint != -1)
687 m_pool.resize(new_size: m_checkpoint);
688}
689
690QQmlJSRegisterContentPrivate *QQmlJSRegisterContentPool::clone(
691 const QQmlJSRegisterContentPrivate *from)
692{
693 m_pool.push_back(x: std::unique_ptr<QQmlJSRegisterContentPrivate, Deleter>(from
694 ? new QQmlJSRegisterContentPrivate(*from)
695 : new QQmlJSRegisterContentPrivate));
696 return m_pool.back().get();
697}
698
699QQmlJSRegisterContentPrivate *QQmlJSRegisterContentPool::create(
700 QQmlJSRegisterContent scope, ContentVariant variant)
701{
702 QQmlJSRegisterContentPrivate *result = create();
703 result->m_scope = scope;
704 result->m_variant = variant;
705 return result;
706}
707
708QT_END_NAMESPACE
709

source code of qtdeclarative/src/qmlcompiler/qqmljsregistercontent.cpp