Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlsa.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
5#include "qqmlsa.h"
6#include "qqmlsa_p.h"
8
10#include "qqmljslogger_p.h"
13#include "qqmljsutils_p.h"
15
16#include <QtQmlCompiler/private/qqmlsasourcelocation_p.h>
17
18#include <memory>
19
21
22using namespace Qt::StringLiterals;
23
24namespace QQmlSA {
25
26static_assert(QQmlJSScope::sizeofQQmlSAElement() == sizeof(Element));
27
28/*!
29 \namespace QQmlSA
30 \inmodule QtQmlCompiler
31
32 \brief Provides tools for static analysis on QML programs.
33 */
34
35/*!
36 \enum QQmlSA::MethodType
37 \inmodule QtQmlCompiler
38
39 \brief Describes the type of a \l{QQmlSA::Method}.
40 \value Signal The method is a signal
41 \value Slot The method is a slot
42 \value Method The method is a \l{Q_INVOKABLE} method
43 \value StaticMethod The method is a \l{Q_INVOKABLE} static method
44*/
45
46/*!
47 \enum QQmlSA::AccessSemantics
48 \inmodule QtQmlCompiler
49
50 \brief Describes how a type is accessed and shared.
51 \value Reference The type behaves like an \l{QML Object Types}{Object type}
52 \value Value The type behaves like a \l{QML Value Types}{Value type}
53 \value None The type is a \l{QML Namespaces}{namespace}, or is invalid
54 \value Sequence The type behaves like a \l{QML Sequence Types}{Sequence type}
55
56 \sa {The QML Type System}
57*/
58
59/*!
60 \enum QQmlSA::BindingType
61 \inmodule QtQmlCompiler
62
63 \brief Describes the type of a \l{QQmlSA::Binding}.
64 \value Invalid There is no binding
65 \value BoolLiteral The binding is a bool literal
66 \value NumberLiteral The binding is a number literal
67 \value StringLiteral The binding is a string literal
68 \value RegExpLiteral The binding is a regular expression literal
69 \value Null The binding is a null literal
70 \value Translation The binding is a \l{Text ID based translations}{translation}
71 \value TranslationById The binding is a \l{Text ID based translations}{translation} by id
72 \value Script The binding is a regular script
73 \value Object The binging is an \l{QML Object Types}{Object}
74 \value Interceptor The binding is an interceptor that can intercept writes to properties such as \l[Quick]{Behavior}
75 \value ValueSource The binging is a \l{Defining QML Types from C++#Property Value Sources}{property value source}
76 \value AttachedProperty The binding is an \l{QML Object Attributes#Attached Properties and Attached Signal Handlers}{attached object}
77 \value GroupProperty The binding is a \l{QML Object Attributes#Grouped Properties}{grouped property}
78*/
79
80/*!
81 \enum QQmlSA::ScriptBindingKind
82 \inmodule QtQmlCompiler
83
84 \brief Describes the script type of a \l{QQmlSA::Binding} of type \l{Script}.
85 \value Invalid The binding has an invalid script
86 \value PropertyBinding The binding is bound to a property
87 \value SignalHandler The binding is a \l{Signal and Handler Event System#Receiving signals with signal handlers}{signal handler}
88 \value ChangeHandler The binding is a \l{Signal and Handler Event System#Property change signal handlers}{change handler}
89*/
90
91/*!
92 \enum QQmlSA::ScopeType
93 \brief Describes the type of QML scope.
94 \value JSFunctionScope The scope is a JavaScript function:
95 \badcode
96 Item {
97 function f() : int { <- begin
98 return 1
99 } <- end
100 }
101 \endcode
102 \value JSLexicalScope The scope is a JavaScript lexical scope:
103 \badcode
104 property int i: { <- begin
105 let a = 1
106 { <- begin
107 console.log("hello")
108 } <- end
109 return a
110 } <- end
111 \endcode
112 \value QMLScope The scope is a QML Object:
113 \badcode
114 Item { <- begin
115 x: 50
116 } <- end
117 \endcode
118 \value GroupedPropertyScope The scope is a \l{QML Object Attributes#Grouped Properties}{grouped property}:
119 \badcode
120 Text {
121 font { <- begin
122 pixelSize: 12
123 bold: true
124 } <- end
125 }
126 \endcode
127 \value AttachedPropertyScope The scope is an \l{QML Object Attributes#Attached Properties and Attached Signal Handlers}{attached property}:
128 \badcode
129 Item {
130 Component.onCompleted: console.log("Hello")
131 ^^^^^^^^^
132 \ Scope of attached property Component
133 }
134 \endcode
135 \value EnumScope The scope is a QML \l{QML Enumerations}{enum}:
136 \badcode
137 enum E { <- begin
138 A,
139 B,
140 C
141 } <- end
142 \endcode
143 \value [since 6.11] BindingFunctionScope The scope represents the expression of a binding:
144 \badcode
145 Item {
146 width: <- begin 10 +
147 2 *parent.width <- end
148 }
149 \endcode
150 Before Qt 6.11, this was reported as a JSFunctionScope
151 \value [since 6.11] SignalHandlerFunctionScope The scope represents a function used as a signal handler:
152 \badcode
153 Timer {
154 onTriggered: <- begin console.log("hi") <- end
155 }
156 \endcode
157 Before Qt 6.11, this was reported as a JSFunctionScope
158
159 Each entry is shown with an example scope of the matching type in QML code.
160*/
161
162/*!
163 \class QQmlSA::Binding::Bindings
164 \inmodule QtQmlCompiler
165
166 \brief Holds multiple property name to property binding associations.
167 */
168
169/*!
170 Constructs a new Bindings object.
171 */
173
174BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface) : q_ptr{ iface } { }
175
176/*!
177 Creates a copy of \a other.
178 */
180 : d_ptr{ new BindingsPrivate{ this, *other.d_func() } }
181{
182}
183
184/*!
185 Destroys the Bindings object.
186 */
187Binding::Bindings::~Bindings() = default;
188
189BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface, const BindingsPrivate &other)
190 : m_bindings{ other.m_bindings.begin(), other.m_bindings.end() }, q_ptr{ iface }
191{
192}
193
194BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface, BindingsPrivate &&other)
195 : m_bindings{ std::move(other.m_bindings) }, q_ptr{ iface }
196{
197}
198
199/*!
200 Returns an iterator to the beginning of the bindings.
201 */
203{
204 Q_D(const Bindings);
205 return d->constBegin();
206}
207
208/*!
209 \fn QMultiHash<QString, Binding>::const_iterator Binding::Bindings::begin() const
210 Same as constBegin().
211 */
212
214{
215 return m_bindings.constBegin();
216}
217
218/*!
219 Returns an iterator to the end of the bindings.
220 */
222{
223 Q_D(const Bindings);
224 return d->constEnd();
225}
226
227/*!
228 \fn QMultiHash<QString, Binding>::const_iterator Binding::Bindings::end() const
229 Same as constEnd().
230 */
231
233{
234 return m_bindings.constEnd();
235}
236
237/*!
238 \class QQmlSA::Binding
239 \inmodule QtQmlCompiler
240
241 \brief Represents a single QML property binding for a specific type.
242 */
243
244/*!
245 Constructs a new Binding object.
246 */
247Binding::Binding() : d_ptr{ new BindingPrivate{ this } } { }
248
249BindingPrivate::BindingPrivate(Binding *iface) : q_ptr{ iface } { }
250
251/*!
252 Creates a copy of \a other.
253*/
254Binding::Binding(const Binding &other) : d_ptr{ new BindingPrivate{ this, *other.d_func() } } { }
255
256/*!
257 Move-constructs a \c Binding instance.
258*/
260 : d_ptr{ new BindingPrivate{ this, *other.d_func() } } { }
261
262
263/*!
264 Assigns \a other to this Binding instance.
265*/
267{
268 if (*this == other)
269 return *this;
270
271 Q_D(Binding);
274 d->q_ptr = this;
276 return *this;
277}
278
279/*!
280 Move-assigns \a other to this Binding instance.
281*/
283{
284 if (*this == other)
285 return *this;
286
287 Q_D(Binding);
290 d->q_ptr = this;
292 return *this;
293}
294
295/*!
296 Destroys the binding.
297*/
298Binding::~Binding() = default;
299
300bool Binding::operatorEqualsImpl(const Binding &lhs, const Binding &rhs)
301{
302 return lhs.d_func()->m_binding == rhs.d_func()->m_binding
305}
306
307BindingPrivate::BindingPrivate(Binding *iface, const BindingPrivate &other)
309 m_isAttached{ other.m_isAttached }
310{
311}
312
313QQmlSA::Binding BindingPrivate::createBinding(const QQmlJSMetaPropertyBinding &binding)
314{
315 QQmlSA::Binding saBinding;
316 saBinding.d_func()->m_binding = binding;
317 return saBinding;
318}
319
320QQmlJSMetaPropertyBinding BindingPrivate::binding(QQmlSA::Binding &binding)
321{
322 return binding.d_func()->m_binding;
323}
324
325const QQmlJSMetaPropertyBinding BindingPrivate::binding(const QQmlSA::Binding &binding)
326{
327 return binding.d_func()->m_binding;
328}
329
330/*!
331 Returns the type of the property of this binding if it is a group property,
332 otherwise returns an invalid Element.
333 */
338
339/*!
340 Returns the Element scope in which the binding is defined.
341 */
343{
344 return BindingPrivate::get(this)->m_bindingScope;
345}
346
347/*!
348 Returns the type of this binding.
349 */
354
355/*!
356 Returns the associated string literal if the content type of this binding is
357 StringLiteral, otherwise returns an empty string.
358 */
360{
361 return BindingPrivate::binding(*this).stringValue();
362}
363
364/*!
365 Returns the name of the property bound with this binding.
366 */
368{
369 return BindingPrivate::binding(*this).propertyName();
370}
371
372/*!
373 Returns \c true if this type is attached to another one, \c false otherwise.
374 */
375bool Binding::isAttached() const
376{
377 return BindingPrivate::get(this)->m_isAttached;
378}
379
380/*!
381 Returns the attached type if the content type of this binding is
382 AttachedProperty, otherwise returns an invalid Element.
383 */
388
389#if QT_DEPRECATED_SINCE(6, 9)
390/*!
391 Returns the attached type if the content type of this binding is
392 AttachedProperty, otherwise returns an invalid Element.
393
394 \deprecated [6.9] Use the better named attachedType() method.
395 */
397{
398 return attachedType();
399}
400#endif
401
402/*!
403 Returns the location in the QML code where this binding is defined.
404 */
410
411/*!
412 Returns the associated number if the content type of this binding is
413 NumberLiteral, otherwise returns 0.
414 */
415double Binding::numberValue() const
416{
417 return BindingPrivate::binding(*this).numberValue();
418}
419
420/*!
421 Returns the kind of the associated script if the content type of this
422 binding is Script, otherwise returns Invalid.
423 */
428
429/*!
430 Returns \c true if this binding has an objects, otherwise returns \c false.
431 */
432bool Binding::hasObject() const
433{
434 return BindingPrivate::binding(*this).hasObject();
435}
436
437/*!
438 Returns the type of the associated object if the content type of this
439 binding is Object, otherwise returns an invalid Element.
440 */
445
446/*!
447 Returns whether this binding has script value type undefined like when it
448 is assigned \c undefined. If the content type of this binding is not
449 \l{QQmlSA::BindingType::Script}, returns \c false.
450 */
457
458/*!
459 Returns whether this binding has script value type function like when it
460 is assigned a (lambda) method, an arrow function or a statement block. If
461 the content type of this binding is not \l{QQmlSA::BindingType::Script},
462 returns \c false.
463 */
470
471/*!
472 Returns \c true if \a bindingType is a literal type, and \c false
473 otherwise.
474 */
479
480/*!
481 \fn friend bool Binding::operator==(const Binding &lhs, const Binding &rhs)
482 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise. Two
483 \c Bindings are considered equal if their property name, content type, and
484 source location match.
485 */
486/*!
487 \fn friend bool Binding::operator!=(const Binding &lhs, const Binding &rhs)
488 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
489 Two \c Bindings are considered equal if their property name, content type,
490 and source location match.
491 */
492
493/*!
494 Constructs a new Methods object.
495*/
497
498/*!
499 Creates a copy of \a other.
500 */
502 : d_ptr{ new MethodsPrivate{ this, *other.d_func() } }
503{
504}
505
506/*!
507 Destroys the Methods instance.
508 */
509QQmlSA::Method::Methods::~Methods() = default;
510
511/*!
512 Returns an iterator to the beginning of the methods.
513 */
515{
516 Q_D(const Methods);
517 return d->constBegin();
518}
519
520/*!
521 \fn QMultiHash<QString, QQmlSA::Method>::const_iterator QQmlSA::Method::Methods::begin() const
522 Returns an iterator to the beginning of the methods.
523 */
524
526{
527 return m_methods.constBegin();
528}
529
530/*!
531 Returns an iterator to the end of the methods.
532 */
534{
535 Q_D(const Methods);
536 return d->constEnd();
537}
538
539/*!
540 \fn QMultiHash<QString, QQmlSA::Method>::const_iterator QQmlSA::Method::Methods::end() const
541 Returns an iterator to the end of the methods.
542 */
543
545{
546 return m_methods.constEnd();
547}
548
549MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface) : q_ptr{ iface } { }
550
551MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface, const MethodsPrivate &other)
553{
554}
555
556MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface, MethodsPrivate &&other)
558{
559}
560
561MethodPrivate::MethodPrivate(Method *iface) : q_ptr{ iface } { }
562
563MethodPrivate::MethodPrivate(Method *iface, const MethodPrivate &other)
565{
566}
567
569{
570 return m_method.methodName();
571}
572
573QQmlSA::SourceLocation MethodPrivate::sourceLocation() const
574{
575 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_method.sourceLocation());
576}
577
579{
580 return m_method.methodType();
581}
582
583/*!
584 \class QQmlSA::Method
585 \inmodule QtQmlCompiler
586
587 \brief Represents a QML method.
588 */
589
590/*!
591 Constructs a new Method object.
592 */
593Method::Method() : d_ptr{ new MethodPrivate{ this } } { }
594
595/*!
596 Creates a copy of \a other.
597 */
598Method::Method(const Method &other) : d_ptr{ new MethodPrivate{ this, *other.d_func() } } { }
599
600/*!
601 Move-constructs a Method instance.
602 */
604 : d_ptr{ new MethodPrivate{ this, std::move(*other.d_func()) } }
605{
606}
607
608/*!
609 Assigns \a other to this Method instance.
610 */
612{
613 if (*this == other)
614 return *this;
615
617 d_func()->q_ptr = this;
618 return *this;
619}
620
621/*!
622 Move-assigns \a other to this Method instance.
623 */
625{
626 if (*this == other)
627 return *this;
628
630 d_func()->q_ptr = this;
631 return *this;
632}
633
634/*!
635 Destroys the Method.
636 */
637Method::~Method() = default;
638
639/*!
640 Returns the name of the this method.
641 */
643{
644 Q_D(const Method);
645 return d->methodName();
646}
647
648/*!
649 Returns the type of this method.
650 */
652{
653 Q_D(const Method);
654 return d->methodType();
655}
656
657/*!
658 \fn friend bool Method::operator==(const Method &lhs, const Method &rhs)
659 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
660 */
661/*!
662 \fn friend bool Method::operator!=(const Method &lhs, const Method &rhs)
663 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
664 */
665
666/*!
667 Returns the location in the QML code where this method is defined.
668 */
670{
671 Q_D(const Method);
672 return d->sourceLocation();
673}
674
675bool Method::operatorEqualsImpl(const Method &lhs, const Method &rhs)
676{
677 return lhs.d_func()->m_method == rhs.d_func()->m_method;
678}
679
680QQmlSA::Method MethodPrivate::createMethod(const QQmlJSMetaMethod &jsMethod)
681{
682 QQmlSA::Method saMethod;
683 auto &wrappedMethod = saMethod.d_func()->m_method;
684 wrappedMethod = jsMethod;
685 return saMethod;
686}
687
688QQmlSA::Method::Methods
689MethodsPrivate::createMethods(const QMultiHash<QString, QQmlJSMetaMethod> &hash)
690{
691 QMultiHash<QString, QQmlSA::Method> saMethods;
692 for (const auto &[key, value] : hash.asKeyValueRange()) {
693 saMethods.insert(key, MethodPrivate::createMethod(value));
694 }
695
696 QQmlSA::Method::Methods methods;
697 methods.d_func()->m_methods = std::move(saMethods);
698 return methods;
699}
700
701QQmlJSMetaMethod MethodPrivate::method(const QQmlSA::Method &method)
702{
703 return method.d_func()->m_method;
704}
705
706PropertyPrivate::PropertyPrivate(Property *iface) : q_ptr{ iface } { }
707
708PropertyPrivate::PropertyPrivate(Property *iface, const PropertyPrivate &other)
710{
711}
712
715{
716}
717
719{
720 return m_property.typeName();
721}
722
724{
725 return m_property.isValid();
726}
727
728/*!
729 Returns whether this property is readonly. Properties defined in QML are readonly when their
730 definition has the 'readonly' keyword. Properties defined in C++ are readonly when they do not
731 have a WRITE accessor function.
732 */
734{
735 return !m_property.isWritable();
736}
737
738/*!
739 Returns the type that this property was defined with.
740 */
741QQmlSA::Element PropertyPrivate::type() const
742{
743 return QQmlJSScope::createQQmlSAElement(m_property.type());
744}
745
746QQmlJSMetaProperty PropertyPrivate::property(const QQmlSA::Property &property)
747{
748 return property.d_func()->m_property;
749}
750
751QQmlSA::Property PropertyPrivate::createProperty(const QQmlJSMetaProperty &property)
752{
753 QQmlSA::Property saProperty;
754 auto &wrappedProperty = saProperty.d_func()->m_property;
755 wrappedProperty = property;
756 return saProperty;
757}
758
759/*!
760 \class QQmlSA::Property
761 \inmodule QtQmlCompiler
762
763 \brief Represents a QML property.
764 */
765
766/*!
767 Constructs a new Property object.
768 */
769Property::Property() : d_ptr{ new PropertyPrivate{ this } } { }
770
771/*!
772 Creates a copy of \a other.
773 */
775 : d_ptr{ new PropertyPrivate{ this, *other.d_func() } } { }
776
777/*!
778 Move-constructs a Property instance.
779 */
781 : d_ptr{ new PropertyPrivate{ this, std::move(*other.d_func()) } }
782{
783}
784
785/*!
786 Assigns \a other to this Property instance.
787 */
789{
790 if (*this == other)
791 return *this;
792
794 d_func()->q_ptr = this;
795 return *this;
796}
797
798/*!
799 Move-assigns \a other to this Property instance.
800 */
802{
803 if (*this == other)
804 return *this;
805
807 d_func()->q_ptr = this;
808 return *this;
809}
810
811/*!
812 Destroys this property.
813 */
814Property::~Property() = default;
815
816/*!
817 Returns the name of the type of this property.
818 */
820{
821 Q_D(const Property);
822 return d->typeName();
823}
824
825/*!
826 Returns \c true if this property is valid, \c false otherwise.
827 */
828bool Property::isValid() const
829{
830 Q_D(const Property);
831 return d->isValid();
832}
833
834/*!
835 Returns \c true if this property is read-only, \c false otherwise.
836 */
837bool Property::isReadonly() const
838{
839 Q_D(const Property);
840 return d->isReadonly();
841}
842
843/*!
844 Returns the type of this property.
845*/
847{
848 Q_D(const Property);
849 return d->type();
850}
851
852/*!
853 \fn friend bool Property::operator==(const Property &lhs, const Property &rhs)
854 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
855 */
856/*!
857 \fn friend bool Property::operator!=(const Property &lhs, const Property &rhs)
858 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
859 */
860
861
863{
864 return lhs.d_func()->m_property == rhs.d_func()->m_property;
865}
866
867/*!
868 \class QQmlSA::Element
869 \inmodule QtQmlCompiler
870
871 \brief Represents a QML type.
872 */
873
874/*!
875 Constructs a new Element object.
876 */
878{
879 new (m_data) QQmlJSScope::ConstPtr();
880}
881
882/*!
883 Creates a copy of \a other.
884 */
889
890/*!
891 \fn Element::Element(Element &&other) noexcept
892 Move-constructs an Element instance.
893 */
894
895/*!
896 Assigns \a other to this element instance.
897 */
899{
900 if (this == &other)
901 return *this;
902
903 *reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data) = QQmlJSScope::scope(other);
904 return *this;
905}
906
907/*!
908 \fn QQmlSA::Element &QQmlSA::Element::operator=(QQmlSA::Element &&other)
909 Move-assigns \a other to this Element instance.
910 */
911
912/*!
913 Destroys the element.
914 */
916{
917 (*reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data)).QQmlJSScope::ConstPtr::~ConstPtr();
918}
919
920/*!
921 Returns the type of Element's scope.
922 */
924{
925 return QQmlJSScope::scope(*this)->scopeType();
926}
927
928/*!
929 Returns the Element this Element derives from.
930 */
935
936/*!
937 Returns the name of the Element this Element derives from.
938 */
943
944/*!
945 Returns the Element that encloses this Element.
946 */
951
952/*!
953 Returns whether this Element inherits from \a element.
954 */
955bool Element::inherits(const Element &element) const
956{
958}
959
960/*!
961 Returns whether this Element is the root component of its QML file.
962 */
964{
965 return QQmlJSScope::scope(*this)->isFileRootComponent();
966}
967
968/*!
969 Returns \c true if this element is null, \c false otherwise.
970 */
971bool Element::isNull() const
972{
973 return QQmlJSScope::scope(*this).isNull();
974}
975
976/*!
977 \internal
978 */
980{
981 return QQmlJSScope::scope(*this)->internalName();
982}
983
984/*!
985 Returns the access semantics of this Element. For example, Reference,
986 Value or Sequence.
987 */
989{
990 return QQmlJSScope::scope(*this)->accessSemantics();
991}
992
993/*!
994 Returns \c true for objects defined from Qml, and \c false for objects declared from C++.
995 */
997{
998 return QQmlJSScope::scope(*this)->isComposite();
999}
1000
1001/*!
1002 Returns whether this Element has a property with the name \a propertyName.
1003 */
1005{
1006 return QQmlJSScope::scope(*this)->hasProperty(propertyName);
1007}
1008
1009/*!
1010 Returns whether this Element defines a property with the name \a propertyName
1011 which is not defined on its base or extension objects.
1012 */
1014{
1016}
1017
1018/*!
1019 Returns the property with the name \a propertyName if it is found in this
1020 Element or its base and extension objects, otherwise returns an invalid property.
1021 */
1026
1027/*!
1028 Returns whether the property with the name \a propertyName resolved on this
1029 Element is required. Returns false if the the property couldn't be found.
1030 */
1035
1036/*!
1037 Returns the name of the default property of this Element. If it doesn't
1038 have one, returns an empty string.
1039 */
1041{
1042 return QQmlJSScope::scope(*this)->defaultPropertyName();
1043}
1044
1045/*!
1046 Returns whether this Element has a method with the name \a methodName.
1047 */
1049{
1050 return QQmlJSScope::scope(*this)->hasMethod(methodName);
1051}
1052
1053/*!
1054 \class QQmlSA::Method::Methods
1055 \inmodule QtQmlCompiler
1056
1057 \brief Holds multiple method name to method associations.
1058 */
1059
1060/*!
1061 Returns this Elements's methods, which are not defined on its base or
1062 extension objects.
1063 */
1068
1069/*!
1070 Returns the location in the QML code where this Element is defined.
1071 */
1077
1078/*!
1079 Returns the location in the QML code where this Element is assigned its id, if it has one.
1080 */
1086
1087/*!
1088 Returns the file path of the QML code that defines this Element.
1089 */
1091{
1092 return QQmlJSScope::scope(*this)->filePath();
1093}
1094
1095/*!
1096 Returns whether this Element has a property binding with the name \a name.
1097 */
1099{
1100 return QQmlJSScope::scope(*this)->hasPropertyBindings(name);
1101}
1102
1103/*!
1104 Returns whether this Element has property bindings which are not defined in
1105 its base or extension objects and that have name \a propertyName.
1106 */
1111
1112/*!
1113 Returns this Element's property bindings which are not defined on its base
1114 or extension objects.
1115 */
1120
1121/*!
1122 Returns this Element's property bindings which are not defined on its base
1123 or extension objects and that have the name \a propertyName.
1124 */
1130
1131/*!
1132 Returns this Element's property bindings that have the name \a propertyName.
1133 */
1135{
1136 const auto &bindings = QQmlJSScope::scope(*this)->propertyBindings(propertyName);
1137
1139 for (const auto &jsBinding : bindings) {
1141 }
1142 return saBindings;
1143}
1144
1145QQmlSA::Binding::Bindings
1146BindingsPrivate::createBindings(const QMultiHash<QString, QQmlJSMetaPropertyBinding> &hash)
1147{
1148 QMultiHash<QString, QQmlSA::Binding> saBindings;
1149 for (const auto &[key, value] : hash.asKeyValueRange()) {
1150 saBindings.insert(key, BindingPrivate::createBinding(value));
1151 }
1152
1153 QQmlSA::Binding::Bindings bindings;
1154 bindings.d_func()->m_bindings = std::move(saBindings);
1155 return bindings;
1156}
1157
1171
1172/*!
1173 Returns \c true if this element is not null, \c false otherwise.
1174 */
1175Element::operator bool() const
1176{
1177 return bool(QQmlJSScope::scope(*this));
1178}
1179
1180/*!
1181 Returns \c true if this element is null, \c false otherwise.
1182 */
1183bool Element::operator!() const
1184{
1185 return !QQmlJSScope::scope(*this);
1186}
1187
1188/*!
1189 Returns the name of this Element.
1190 */
1192{
1193 if (isNull())
1194 return {};
1196}
1197
1198/*!
1199 \fn friend inline bool Element::operator==(const Element &lhs, const Element &rhs)
1200 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
1201 */
1202/*!
1203 \fn friend inline bool Element::operator!=(const Element &lhs, const Element &rhs)
1204 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
1205 */
1206
1207bool Element::operatorEqualsImpl(const Element &lhs, const Element &rhs)
1208{
1209 return QQmlJSScope::scope(lhs) == QQmlJSScope::scope(rhs);
1210}
1211
1212/*!
1213 \fn friend inline qsizetype Element::qHash(const Element &key, qsizetype seed) noexcept
1214 Returns the hash for \a key using \a seed to seed the calculation.
1215*/
1216
1218{
1219 return qHash(QQmlJSScope::scope(key), seed);
1220}
1221
1222/*!
1223 \class QQmlSA::GenericPass
1224 \inmodule QtQmlCompiler
1225
1226 \brief The base class for static analysis passes.
1227
1228 This class contains common functionality used by more specific passses.
1229 Custom passes should not directly derive from it, but rather from one of
1230 its subclasses.
1231 \sa ElementPass, PropertyPass
1232 */
1233
1235 Q_DECLARE_PUBLIC(GenericPass);
1236
1237public:
1238 GenericPassPrivate(GenericPass *iface, PassManager *manager)
1239 : m_manager{ manager }, q_ptr{ iface }
1240 {
1241 Q_ASSERT(manager);
1242 }
1243
1244private:
1245 PassManager *m_manager = nullptr;
1246
1247 GenericPass *q_ptr = nullptr;
1248};
1249
1250/*!
1251 Creates a generic pass.
1252 */
1255
1256/*!
1257 Destroys the GenericPass instance.
1258 */
1259GenericPass::~GenericPass() = default;
1260
1261/*!
1262 Emits a warning message \a diagnostic about an issue of type \a id.
1263 */
1268
1269/*!
1270 Emits warning message \a diagnostic about an issue of type \a id located at
1271 \a srcLocation.
1272 */
1282
1283/*!
1284 Emits a warning message \a diagnostic about an issue of type \a id located at
1285 \a srcLocation and with suggested fix \a fix.
1286 */
1297
1298/*!
1299 Returns the type corresponding to \a typeName inside the
1300 currently analysed file.
1301 */
1309
1310/*!
1311 Returns the attached type corresponding to \a typeName used inside
1312 the currently analysed file.
1313 */
1324
1325/*!
1326 Returns the type of \a typeName defined in module \a moduleName.
1327 If an attached type and a non-attached type share the same name
1328 (for example, \c ListView), the \l Element corresponding to the
1329 non-attached type is returned.
1330 To obtain the attached type, use \l resolveAttached.
1331 */
1340
1341/*!
1342 Returns the type of the built-in type identified by \a typeName.
1343 Built-in types encompass \c{C++} types which the QML engine can handle
1344 without any imports (e.g. \l QDateTime and \l QString), global EcmaScript
1345 objects like \c Number, as well as the \l {QML Global Object}
1346 {global Qt object}.
1347 */
1349{
1350 Q_D(const GenericPass);
1353 // we have to check both cpp names
1355 if (!scope) {
1356 // and qml names (e.g. for bool) - builtinImportHelper is private, so we can't do it in one call
1359 }
1361}
1362
1363/*!
1364 Returns the attached type of \a typeName defined in module \a moduleName.
1365 */
1371
1372/*!
1373 Returns the element representing the type of literal in \a binding. If the
1374 binding does not contain a literal value, a null Element is returned.
1375 */
1383
1384/*!
1385 Returns the element in \a context that has id \a id.
1386 */
1395
1396/*!
1397 Returns the id of \a element in a given \a context.
1398 */
1407
1408/*!
1409 Returns the source code located within \a location.
1410 */
1419
1420/*!
1421 \class QQmlSA::PassManager
1422 \inmodule QtQmlCompiler
1423
1424 \brief Can analyze an element and its children with static analysis passes.
1425 */
1426
1427// explicitly defaulted out-of-line for PIMPL
1428PassManager::PassManager() = default;
1429PassManager::~PassManager() = default;
1430
1431/*!
1432 Registers a static analysis \a pass to be run on all elements.
1433 */
1439
1440/*!
1441 \internal
1442 \brief PassManager::registerElementPass registers ElementPass
1443 with the pass manager.
1444 \param pass The registered pass. Ownership is transferred to the pass manager.
1445 */
1450
1452static QString lookupName(const QQmlSA::Element &element, LookupMode mode = Lookup)
1453{
1454 QString name;
1455 if (element.isNull() || QQmlJSScope::scope(element)->internalName().isEmpty()) {
1456 // Bail out with an invalid name, this type is so screwed up we can't do anything reasonable
1457 // with it We should have warned about it in another plac
1458 if (element.isNull() || element.baseType().isNull())
1459 return u"$INVALID$"_s;
1460 name = QQmlJSScope::scope(element.baseType())->internalName();
1461 } else {
1462 name = QQmlJSScope::scope(element)->internalName();
1463 }
1464
1465 const QString filePath =
1466 (mode == Register || !element.baseType() ? element : element.baseType()).filePath();
1467
1468 if (QQmlJSScope::scope(element)->isComposite() && !filePath.endsWith(u".h"))
1469 name += u'@' + filePath;
1470 return name;
1471}
1472
1473/*!
1474 Registers a static analysis pass for properties. The \a pass will be run on
1475 every property matching the \a moduleName, \a typeName and \a propertyName.
1476
1477 Omitting the \a propertyName will register this pass for all properties
1478 matching the \a typeName and \a moduleName.
1479
1480 Setting \a allowInheritance to \c true means that the filtering on the type
1481 also accepts types deriving from \a typeName.
1482
1483 \a pass is passed as a \c{std::shared_ptr} to allow reusing the same pass
1484 on multiple elements:
1485 \code
1486 auto titleValiadorPass = std::make_shared<TitleValidatorPass>(manager);
1487 manager->registerPropertyPass(titleValidatorPass,
1488 "QtQuick", "Window", "title");
1489 manager->registerPropertyPass(titleValidatorPass,
1490 "QtQuick.Controls", "Dialog", "title");
1491 \endcode
1492
1493 \note Running analysis passes on too many items can be expensive. This is
1494 why it is generally good to filter down the set of properties of a pass
1495 using the \a moduleName, \a typeName and \a propertyName.
1496
1497 Returns \c true if the pass was successfully added, \c false otherwise.
1498 Adding a pass fails when the \l{QQmlSA::Element}{Element} specified by
1499 \a moduleName and \a typeName does not exist.
1500
1501 \sa PropertyPass
1502*/
1510
1514{
1515 if (moduleName.isEmpty() != typeName.isEmpty()) {
1516 qWarning() << "Both the moduleName and the typeName must be specified "
1517 "for the pass to be registered for a specific element.";
1518 }
1519
1520 QString name;
1521 if (!moduleName.isEmpty() && !typeName.isEmpty()) {
1525
1526 if (element.isNull())
1527 return false;
1528
1530 }
1534
1535 return true;
1536}
1537
1558
1560 const QString prefix, bool isAttached)
1561{
1564 for (auto &binding : ownBindings) {
1565 switch (binding.bindingType()) {
1568 prefix + binding.propertyName() + u'.');
1569 continue; // don't insert into m_bindingsByLocation
1572 prefix + binding.propertyName() + u'.', true);
1573 continue; // don't insert into m_bindingsByLocation
1576 u"qsTr"_s, element, binding.sourceLocation());
1577 break;
1578 }
1581 u"qsTrId"_s, element, binding.sourceLocation());
1582 break;
1583 }
1584 default:
1585 break;
1586 }
1587
1594 }
1595}
1596
1597/*!
1598 Runs the element passes over \a root and all its children.
1599 */
1601{
1603 d->analyze(root);
1604}
1605
1606static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
1607{
1608 return QQmlJSScope::scope(element)->childScopesBegin();
1609}
1610
1611static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
1612{
1613 return QQmlJSScope::scope(element)->childScopesEnd();
1614}
1615
1617{
1620 while (!runStack.isEmpty()) {
1621 auto element = runStack.takeLast();
1623 for (auto &elementPass : m_elementPasses)
1626
1627 for (auto it = childScopesBegin(element), end = childScopesEnd(element); it != end; ++it) {
1628 if ((*it)->scopeType() == QQmlSA::ScopeType::QMLScope)
1630 }
1631 }
1632}
1633
1642
1650
1658
1661{
1662 const auto it = m_bindingsByLocation.find(location.offset());
1663
1664 // If there's no matching binding that means we're in a nested Ret somewhere inside an
1665 // expression
1666 if (it == m_bindingsByLocation.cend())
1667 return;
1668
1669 const auto &[offset, binding] = *it;
1672
1676
1678 return;
1679
1684 }
1685}
1686
1687/*!
1688 Returns \c true if the module named \a module has been imported by the
1689 QML to be analyzed, \c false otherwise.
1690
1691 This can be used to skip registering a pass which is specific to a specific
1692 module.
1693
1694 \code
1695 if (passManager->hasImportedModule("QtPositioning"))
1696 passManager->registerElementPass(
1697 std::make_unique<PositioningPass>(passManager)
1698 );
1699 \endcode
1700
1701 \sa registerPropertyPass(), registerElementPass()
1702 */
1704{
1705 return PassManagerPrivate::visitor(*this)->imports().hasType(u"$module$." + module.toString());
1706}
1707
1708/*!
1709 Returns \c true if warnings of \a category are enabled, \c false otherwise.
1710 */
1715
1720
1725
1727 const QString &propertyName)
1728{
1730
1731 for (auto it = QQmlJSScope::scope(element); it; it = it->baseType())
1733
1735
1736 for (const QString &typeName : typeNames) {
1737 for (auto &pass :
1739 if (pass.first == pass.second)
1740 continue;
1741
1742 for (auto it = pass.first; it != pass.second; it++) {
1744 continue;
1747 }
1748 }
1749 }
1750 return passes;
1751}
1752
1754 emitWarning(u"Type: " + element.baseTypeName(), qmlPlugin);
1755 if (auto bindings = element.propertyBindings(u"objectName"_s); !bindings.isEmpty()) {
1756 emitWarning(u"is named: " + bindings.first().stringValue(), qmlPlugin);
1757 }
1760 + u" elements to property "_s + defPropName,
1761 qmlPlugin);
1762 }
1763}
1764
1765/*!
1766 \class QQmlSA::LintPlugin
1767 \inmodule QtQmlCompiler
1768
1769 \brief Base class for all static analysis plugins.
1770 */
1771
1772/*!
1773 \fn LintPlugin::LintPlugin()
1774 Constructs a LintPlugin object.
1775 */
1776
1777/*!
1778 \fn virtual LintPlugin::~LintPlugin()
1779 Destroys the LintPlugin instance.
1780 */
1781
1782/*!
1783 \fn void QQmlSA::LintPlugin::registerPasses(PassManager *manager, const Element &rootElement)
1784
1785 Adds a pass \a manager that will be executed on \a rootElement.
1786 */
1787
1788/*!
1789 \class QQmlSA::ElementPass
1790 \inmodule QtQmlCompiler
1791
1792 \brief Base class for all static analysis passes on elements.
1793
1794 ElementPass is the simpler of the two analysis passes. It will consider every element in
1795 a file. The \l shouldRun() method can be used to filter out irrelevant elements, and the
1796 \l run() method is doing the initial work.
1797
1798 Common tasks suitable for an ElementPass are
1799 \list
1800 \li checking that properties of an Element are not combined in a nonsensical way
1801 \li validating property values (e.g. that a property takes only certain enum values)
1802 \li checking behavior dependent on an Element's parent (e.g. not using \l {Item::width}
1803 when the parent element is a \c Layout).
1804 \endlist
1805
1806 As shown in the snippet below, it is recommended to do necessary type resolution in the
1807 constructor of the ElementPass and cache it in local members, and to implement some
1808 filtering via \l shouldRun() to keep the static analysis performant.
1809
1810 \code
1811 using namespace QQmlSA;
1812 class MyElementPass : public ElementPass
1813 {
1814 Element myType;
1815 public:
1816 MyElementPass(QQmlSA::PassManager *manager)
1817 : myType(resolveType("MyModule", "MyType")) {}
1818
1819 bool shouldRun(const Element &element) override
1820 {
1821 return element.inherits(myType);
1822 }
1823 void run(const Element &element) override
1824 {
1825 // actual pass logic
1826 }
1827 }
1828 \endcode
1829
1830 ElementPasses have limited insight into how an element's properties are used. If you need
1831 that information, consider using a \l PropertyPass instead.
1832
1833 \note ElementPass will only ever consider instantiable types. Therefore, it is unsuitable
1834 to analyze attached types and singletons. Those need to be handled via a PropertyPass.
1835 */
1836
1837/*!
1838 \fn ElementPass::ElementPass(PassManager *manager)
1839 Creates an ElementPass object and uses \a manager to refer to the pass manager.
1840*/
1841
1842/*!
1843 \fn void QQmlSA::ElementPass::run(const Element &element)
1844
1845 Executes if \c shouldRun() returns \c true. Performs the real computation
1846 of the pass on \a element.
1847 This method is meant to be overridden. Calling the base method is not
1848 necessary.
1849 */
1850
1851/*!
1852 Controls whether the \c run() function should be executed on the given \a element.
1853 Subclasses can override this method to improve performance of the analysis by
1854 filtering out elements which are not relevant.
1855
1856 The default implementation unconditionally returns \c true.
1857 */
1859{
1860 (void)element;
1861 return true;
1862}
1863
1864/*!
1865 \class QQmlSA::PropertyPass
1866 \inmodule QtQmlCompiler
1867
1868 \brief Base class for all static analysis passes on properties.
1869 */
1870
1871
1872/*!
1873 Creates a PropertyPass object and uses \a manager to refer to the pass manager.
1874 */
1876
1877/*!
1878 Executes whenever a property gets bound to a value.
1879
1880 The property \a propertyName of \a element is bound to the \a value within
1881 \a bindingScope with \a binding.
1882 */
1893
1894/*!
1895 Executes whenever a property is read.
1896
1897 The property \a propertyName of \a element is read by an instruction within
1898 \a readScope defined at \a location.
1899
1900 This is also executed if the property \a propertyName is called as a function as that requires
1901 the property to be read first.
1902 */
1911
1912/*!
1913 Executes whenever a property or method is called.
1914
1915 The property or method \a propertyName of \a element is called as a function by an instruction
1916 within \a readScope defined at \a location.
1917
1918 \note Currently only direct calls of methods or properties are supported, indirect calls, for
1919 example by storing a method into a JavaScript variable and then calling the variable, are not
1920 recognized.
1921 */
1930
1931/*!
1932 Executes whenever a property is written to.
1933
1934 The property \a propertyName of \a element is written to by an instruction
1935 within \a writeScope defined at \a location. The type of the expression
1936 written to \a propertyName is \a expressionType.
1937 */
1948
1952
1965
1967 const QQmlSA::Binding &binding,
1968 const QQmlSA::Element &bindingScope, const QQmlSA::Element &value)
1969{
1971 emitWarning(u"onBinding element: '"_s
1975 + u"' property: '"_s + propertyName + u"' value: '"_s
1976 + (value.isNull() ? u"NULL"_s
1980 + u"' binding_scope: '"_s
1984 + u"' "_s + QString::number(location.startLine()) + u':'
1987}
1988
2000
2001/*!
2002 Returns bindings by their source location.
2003 */
2009
2010FixSuggestionPrivate::FixSuggestionPrivate(FixSuggestion *iface) : q_ptr{ iface } { }
2011
2012FixSuggestionPrivate::FixSuggestionPrivate(FixSuggestion *iface, const QString &fixDescription,
2013 const QQmlSA::SourceLocation &location,
2014 const QString &replacement)
2015 : m_fixSuggestion{ fixDescription, QQmlSA::SourceLocationPrivate::sourceLocation(location),
2016 replacement },
2017 q_ptr{ iface }
2018{
2019}
2020
2022 const FixSuggestionPrivate &other)
2023 : m_fixSuggestion{ other.m_fixSuggestion }, q_ptr{ iface }
2024{
2025}
2026
2028 : m_fixSuggestion{ std::move(other.m_fixSuggestion) }, q_ptr{ iface }
2029{
2030}
2031
2033{
2034 return m_fixSuggestion.fixDescription();
2035}
2036
2037QQmlSA::SourceLocation FixSuggestionPrivate::location() const
2038{
2039 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_fixSuggestion.location());
2040}
2041
2043{
2044 return m_fixSuggestion.replacement();
2045}
2046
2047void FixSuggestionPrivate::setFileName(const QString &fileName)
2048{
2049 m_fixSuggestion.setFilename(fileName);
2050}
2051
2053{
2054 return m_fixSuggestion.filename();
2055}
2056
2057void FixSuggestionPrivate::setHint(const QString &hint)
2058{
2059 m_fixSuggestion.setHint(hint);
2060}
2061
2063{
2064 return m_fixSuggestion.hint();
2065}
2066
2067void FixSuggestionPrivate::setAutoApplicable(bool autoApplicable)
2068{
2069 m_fixSuggestion.setAutoApplicable(autoApplicable);
2070}
2071
2073{
2074 return m_fixSuggestion.isAutoApplicable();
2075}
2076
2077QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(FixSuggestion &saFixSuggestion)
2078{
2080}
2081
2082const QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(const FixSuggestion &saFixSuggestion)
2083{
2084 return saFixSuggestion.d_func()->m_fixSuggestion;
2085}
2086
2087/*!
2088 \class QQmlSA::FixSuggestion
2089 \inmodule QtQmlCompiler
2090
2091 \brief Represents a suggested fix for an issue in the source code.
2092 */
2093
2094
2095/*!
2096 Creates a FixSuggestion object.
2097 */
2103
2104/*!
2105 Creates a copy of \a other.
2106 */
2111
2112/*!
2113 Move-constructs a FixSuggestion instance.
2114 */
2116 : d_ptr{ new FixSuggestionPrivate{ this, std::move(*other.d_func()) } }
2117{
2118}
2119
2120/*!
2121 Assigns \a other to this FixSuggestion instance.
2122 */
2124{
2125 if (*this == other)
2126 return *this;
2127
2129 return *this;
2130}
2131
2132/*!
2133 Move-assigns \a other to this FixSuggestion instance.
2134 */
2136{
2137 if (*this == other)
2138 return *this;
2139
2141 return *this;
2142}
2143
2144/*!
2145 Destorys the FixSuggestion instance.
2146 */
2147FixSuggestion::~FixSuggestion() = default;
2148
2149/*!
2150 Returns the description of the fix.
2151 */
2156
2157/*!
2158 Returns the location where the fix would be applied.
2159 */
2165
2166/*!
2167 Returns the fix that will replace the problematic source code.
2168 */
2173
2174/*!
2175 Sets \a fileName as the name of the file where this fix suggestion applies.
2176 */
2181
2182/*!
2183 Returns the name of the file where this fix suggestion applies.
2184 */
2186{
2188}
2189
2190/*!
2191 Sets \a hint as the hint for this fix suggestion.
2192 */
2197
2198/*!
2199 Returns the hint for this fix suggestion.
2200 */
2202{
2203 return FixSuggestionPrivate::fixSuggestion(*this).hint();
2204}
2205
2206/*!
2207 Sets \a autoApplicable to determine whether this suggested fix can be
2208 applied automatically.
2209 */
2214
2215/*!
2216 Returns whether this suggested fix can be applied automatically.
2217 */
2222
2223/*!
2224 \fn friend bool FixSuggestion::operator==(const FixSuggestion &lhs, const FixSuggestion &rhs)
2225 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
2226 */
2227/*!
2228 \fn friend bool FixSuggestion::operator!=(const FixSuggestion &lhs, const FixSuggestion &rhs)
2229 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
2230 */
2231
2233{
2235}
2236
2252
2254{
2255 return type >= BindingType::BoolLiteral && type <= BindingType::Object;
2256}
2257
2258} // namespace QQmlSA
2259
2260QT_END_NAMESPACE
BindingPrivate(Binding *, const BindingPrivate &)
Definition qqmlsa.cpp:307
\inmodule QtQmlCompiler
Definition qqmlsa.h:52
QMultiHash< QString, Binding >::const_iterator constBegin() const
Definition qqmlsa.cpp:213
QMultiHash< QString, Binding >::const_iterator constEnd() const
Definition qqmlsa.cpp:232
QQmlSA::SourceLocation location() const
Definition qqmlsa.cpp:2037
void setHint(const QString &)
Definition qqmlsa.cpp:2057
void setFileName(const QString &)
Definition qqmlsa.cpp:2047
QString fixDescription() const
Definition qqmlsa.cpp:2032
FixSuggestionPrivate(FixSuggestion *)
Definition qqmlsa.cpp:2010
void setAutoApplicable(bool autoApplicable=true)
Definition qqmlsa.cpp:2067
FixSuggestionPrivate(FixSuggestion *, FixSuggestionPrivate &&)
Definition qqmlsa.cpp:2027
QString replacement() const
Definition qqmlsa.cpp:2042
FixSuggestionPrivate(FixSuggestion *, const FixSuggestionPrivate &)
Definition qqmlsa.cpp:2021
GenericPassPrivate(GenericPass *iface, PassManager *manager)
Definition qqmlsa.cpp:1238
MethodPrivate(Method *, const MethodPrivate &)
Definition qqmlsa.cpp:563
QQmlSA::SourceLocation sourceLocation() const
Definition qqmlsa.cpp:573
MethodType methodType() const
Definition qqmlsa.cpp:578
QString methodName() const
Definition qqmlsa.cpp:568
MethodsPrivate(QQmlSA::Method::Methods *, MethodsPrivate &&)
Definition qqmlsa.cpp:556
QMultiHash< QString, Method >::const_iterator constEnd() const
Definition qqmlsa.cpp:544
MethodsPrivate(QQmlSA::Method::Methods *, const MethodsPrivate &)
Definition qqmlsa.cpp:551
QMultiHash< QString, Method >::const_iterator constBegin() const
Definition qqmlsa.cpp:525
PropertyPrivate(Property *, const PropertyPrivate &)
Definition qqmlsa.cpp:708
PropertyPrivate(Property *, PropertyPrivate &&)
Definition qqmlsa.cpp:713
QQmlSA::Element type() const
Returns the type that this property was defined with.
Definition qqmlsa.cpp:741
bool isValid() const
Definition qqmlsa.cpp:723
QString typeName() const
Definition qqmlsa.cpp:718
bool isReadonly() const
Returns whether this property is readonly.
Definition qqmlsa.cpp:733
\inmodule QtQmlCompiler
MethodType
Definition qqmlsa.h:48
Q_QMLCOMPILER_EXPORT void emitWarningWithOptionalFix(GenericPass &pass, QAnyStringView diagnostic, const LoggerWarningId &id, const QQmlSA::SourceLocation &srcLocation, const std::optional< QQmlJSFixSuggestion > &fix)
Definition qqmlsa.cpp:2237
@ Register
Definition qqmlsa.cpp:1451
static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
Definition qqmlsa.cpp:1611
static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
Definition qqmlsa.cpp:1606
bool isRegularBindingType(BindingType type)
Definition qqmlsa.cpp:2253
static QString lookupName(const QQmlSA::Element &element, LookupMode mode=Lookup)
Definition qqmlsa.cpp:1452