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 */
351{
352 return BindingPrivate::binding(*this).bindingType();
353}
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
706/*!
707 \class QQmlSA::PropertyPrivate
708 \inmodule QtQmlCompiler
709 \internal
710*/
712
717
722
724{
725 return m_property.typeName();
726}
727
729{
730 return m_property.isValid();
731}
732
733/*!
734 Returns whether this property is readonly. Properties defined in QML are readonly when their
735 definition has the 'readonly' keyword. Properties defined in C++ are readonly when they do not
736 have a WRITE accessor function.
737 */
739{
740 return !m_property.isWritable();
741}
742
743/*!
744 Returns the type that this property was defined with.
745 */
750
755
763
764/*!
765 \class QQmlSA::Property
766 \inmodule QtQmlCompiler
767
768 \brief Represents a QML property.
769 */
770
771/*!
772 Constructs a new Property object.
773 */
774Property::Property() : d_ptr{ new PropertyPrivate{ this } } { }
775
776/*!
777 Creates a copy of \a other.
778 */
780 : d_ptr{ new PropertyPrivate{ this, *other.d_func() } } { }
781
782/*!
783 Move-constructs a Property instance.
784 */
786 : d_ptr{ new PropertyPrivate{ this, std::move(*other.d_func()) } }
787{
788}
789
790/*!
791 Assigns \a other to this Property instance.
792 */
794{
795 if (*this == other)
796 return *this;
797
799 d_func()->q_ptr = this;
800 return *this;
801}
802
803/*!
804 Move-assigns \a other to this Property instance.
805 */
807{
808 if (*this == other)
809 return *this;
810
812 d_func()->q_ptr = this;
813 return *this;
814}
815
816/*!
817 Destroys this property.
818 */
819Property::~Property() = default;
820
821/*!
822 Returns the name of the type of this property.
823 */
825{
826 Q_D(const Property);
827 return d->typeName();
828}
829
830/*!
831 Returns \c true if this property is valid, \c false otherwise.
832 */
833bool Property::isValid() const
834{
835 Q_D(const Property);
836 return d->isValid();
837}
838
839/*!
840 Returns \c true if this property is read-only, \c false otherwise.
841 */
842bool Property::isReadonly() const
843{
844 Q_D(const Property);
845 return d->isReadonly();
846}
847
848/*!
849 Returns the type of this property.
850*/
852{
853 Q_D(const Property);
854 return d->type();
855}
856
857/*!
858 \fn friend bool Property::operator==(const Property &lhs, const Property &rhs)
859 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
860 */
861/*!
862 \fn friend bool Property::operator!=(const Property &lhs, const Property &rhs)
863 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
864 */
865
866
868{
869 return lhs.d_func()->m_property == rhs.d_func()->m_property;
870}
871
872/*!
873 \class QQmlSA::Element
874 \inmodule QtQmlCompiler
875
876 \brief Represents a QML type.
877 */
878
879/*!
880 Constructs a new Element object.
881 */
883{
884 new (m_data) QQmlJSScope::ConstPtr();
885}
886
887/*!
888 Creates a copy of \a other.
889 */
894
895/*!
896 \fn Element::Element(Element &&other) noexcept
897 Move-constructs an Element instance.
898 */
899
900/*!
901 Assigns \a other to this element instance.
902 */
904{
905 if (this == &other)
906 return *this;
907
908 *reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data) = QQmlJSScope::scope(other);
909 return *this;
910}
911
912/*!
913 \fn QQmlSA::Element &QQmlSA::Element::operator=(QQmlSA::Element &&other)
914 Move-assigns \a other to this Element instance.
915 */
916
917/*!
918 Destroys the element.
919 */
921{
922 (*reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data)).QQmlJSScope::ConstPtr::~ConstPtr();
923}
924
925/*!
926 Returns the type of Element's scope.
927 */
929{
930 return QQmlJSScope::scope(*this)->scopeType();
931}
932
933/*!
934 Returns the Element this Element derives from.
935 */
940
941/*!
942 Returns the name of the Element this Element derives from.
943 */
948
949/*!
950 Returns the Element that encloses this Element.
951 */
956
957/*!
958 Returns whether this Element inherits from \a element.
959 */
960bool Element::inherits(const Element &element) const
961{
963}
964
965/*!
966 Returns whether this Element is the root component of its QML file.
967 */
969{
970 return QQmlJSScope::scope(*this)->isFileRootComponent();
971}
972
973/*!
974 Returns \c true if this element is null, \c false otherwise.
975 */
976bool Element::isNull() const
977{
978 return QQmlJSScope::scope(*this).isNull();
979}
980
981/*!
982 \internal
983 */
985{
986 return QQmlJSScope::scope(*this)->internalName();
987}
988
989/*!
990 Returns the access semantics of this Element. For example, Reference,
991 Value or Sequence.
992 */
994{
995 return QQmlJSScope::scope(*this)->accessSemantics();
996}
997
998/*!
999 Returns \c true for objects defined from Qml, and \c false for objects declared from C++.
1000 */
1002{
1003 return QQmlJSScope::scope(*this)->isComposite();
1004}
1005
1006/*!
1007 Returns whether this Element has a property with the name \a propertyName.
1008 */
1010{
1011 return QQmlJSScope::scope(*this)->hasProperty(propertyName);
1012}
1013
1014/*!
1015 Returns whether this Element defines a property with the name \a propertyName
1016 which is not defined on its base or extension objects.
1017 */
1019{
1021}
1022
1023/*!
1024 Returns the property with the name \a propertyName if it is found in this
1025 Element or its base and extension objects, otherwise returns an invalid property.
1026 */
1031
1032/*!
1033 Returns whether the property with the name \a propertyName resolved on this
1034 Element is required. Returns false if the the property couldn't be found.
1035 */
1040
1041/*!
1042 Returns the name of the default property of this Element. If it doesn't
1043 have one, returns an empty string.
1044 */
1046{
1047 return QQmlJSScope::scope(*this)->defaultPropertyName();
1048}
1049
1050/*!
1051 Returns whether this Element has a method with the name \a methodName.
1052 */
1054{
1055 return QQmlJSScope::scope(*this)->hasMethod(methodName);
1056}
1057
1058/*!
1059 \class QQmlSA::Method::Methods
1060 \inmodule QtQmlCompiler
1061
1062 \brief Holds multiple method name to method associations.
1063 */
1064
1065/*!
1066 Returns this Elements's methods, which are not defined on its base or
1067 extension objects.
1068 */
1073
1074/*!
1075 Returns the location in the QML code where this Element is defined.
1076 */
1082
1083/*!
1084 Returns the location in the QML code where this Element is assigned its id, if it has one.
1085 */
1091
1092/*!
1093 Returns the file path of the QML code that defines this Element.
1094 */
1096{
1097 return QQmlJSScope::scope(*this)->filePath();
1098}
1099
1100/*!
1101 Returns whether this Element has a property binding with the name \a name.
1102 */
1104{
1105 return QQmlJSScope::scope(*this)->hasPropertyBindings(name);
1106}
1107
1108/*!
1109 Returns whether this Element has property bindings which are not defined in
1110 its base or extension objects and that have name \a propertyName.
1111 */
1116
1117/*!
1118 Returns this Element's property bindings which are not defined on its base
1119 or extension objects.
1120 */
1125
1126/*!
1127 Returns this Element's property bindings which are not defined on its base
1128 or extension objects and that have the name \a propertyName.
1129 */
1135
1136/*!
1137 Returns this Element's property bindings that have the name \a propertyName.
1138 */
1140{
1141 const auto &bindings = QQmlJSScope::scope(*this)->propertyBindings(propertyName);
1142
1144 for (const auto &jsBinding : bindings) {
1146 }
1147 return saBindings;
1148}
1149
1150QQmlSA::Binding::Bindings
1151BindingsPrivate::createBindings(const QMultiHash<QString, QQmlJSMetaPropertyBinding> &hash)
1152{
1153 QMultiHash<QString, QQmlSA::Binding> saBindings;
1154 for (const auto &[key, value] : hash.asKeyValueRange()) {
1155 saBindings.insert(key, BindingPrivate::createBinding(value));
1156 }
1157
1158 QQmlSA::Binding::Bindings bindings;
1159 bindings.d_func()->m_bindings = std::move(saBindings);
1160 return bindings;
1161}
1162
1176
1177/*!
1178 Returns \c true if this element is not null, \c false otherwise.
1179 */
1180Element::operator bool() const
1181{
1182 return bool(QQmlJSScope::scope(*this));
1183}
1184
1185/*!
1186 Returns \c true if this element is null, \c false otherwise.
1187 */
1188bool Element::operator!() const
1189{
1190 return !QQmlJSScope::scope(*this);
1191}
1192
1193/*!
1194 Returns the name of this Element.
1195 */
1197{
1198 if (isNull())
1199 return {};
1201}
1202
1203/*!
1204 \fn friend inline bool Element::operator==(const Element &lhs, const Element &rhs)
1205 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
1206 */
1207/*!
1208 \fn friend inline bool Element::operator!=(const Element &lhs, const Element &rhs)
1209 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
1210 */
1211
1212bool Element::operatorEqualsImpl(const Element &lhs, const Element &rhs)
1213{
1214 return QQmlJSScope::scope(lhs) == QQmlJSScope::scope(rhs);
1215}
1216
1217/*!
1218 \fn size_t Element::qHash(const Element &key, size_t seed)
1219 \qhash{Element}
1220*/
1221
1222size_t Element::hash(size_t seed) const noexcept
1223{
1224 return qHash(QQmlJSScope::scope(*this), seed);
1225}
1226
1227/*!
1228 \class QQmlSA::GenericPass
1229 \inmodule QtQmlCompiler
1230
1231 \brief The base class for static analysis passes.
1232
1233 This class contains common functionality used by more specific passses.
1234 Custom passes should not directly derive from it, but rather from one of
1235 its subclasses.
1236 \sa ElementPass, PropertyPass
1237 */
1238
1240 Q_DECLARE_PUBLIC(GenericPass);
1241
1242public:
1243 GenericPassPrivate(GenericPass *iface, PassManager *manager)
1244 : m_manager{ manager }, q_ptr{ iface }
1245 {
1246 Q_ASSERT(manager);
1247 }
1248
1249private:
1250 PassManager *m_manager = nullptr;
1251
1252 GenericPass *q_ptr = nullptr;
1253};
1254
1255/*!
1256 Creates a generic pass.
1257 */
1260
1261/*!
1262 Destroys the GenericPass instance.
1263 */
1264GenericPass::~GenericPass() = default;
1265
1266/*!
1267 Emits a warning message \a diagnostic about an issue of type \a id.
1268 */
1273
1274/*!
1275 Emits warning message \a diagnostic about an issue of type \a id located at
1276 \a srcLocation.
1277 */
1287
1288/*!
1289 Emits a warning message \a diagnostic about an issue of type \a id located at
1290 \a srcLocation and with suggested fix \a fix.
1291 */
1302
1303/*!
1304 Returns the type corresponding to \a typeName inside the
1305 currently analysed file.
1306 */
1314
1315/*!
1316 Returns the attached type corresponding to \a typeName used inside
1317 the currently analysed file.
1318 */
1329
1330/*!
1331 Returns the type of \a typeName defined in module \a moduleName.
1332 If an attached type and a non-attached type share the same name
1333 (for example, \c ListView), the \l Element corresponding to the
1334 non-attached type is returned.
1335 To obtain the attached type, use \l resolveAttached.
1336 */
1346
1347/*!
1348 Returns the type of the built-in type identified by \a typeName.
1349 Built-in types encompass \c{C++} types which the QML engine can handle
1350 without any imports (e.g. \l QDateTime and \l QString), global EcmaScript
1351 objects like \c Number, as well as the \l {QML Global Object}
1352 {global Qt object}.
1353 */
1355{
1356 Q_D(const GenericPass);
1359 // we have to check both cpp names
1361 if (!scope) {
1362 // and qml names (e.g. for bool) - builtinImportHelper is private, so we can't do it in one call
1365 }
1367}
1368
1369/*!
1370 Returns the attached type of \a typeName defined in module \a moduleName.
1371 */
1382
1383/*!
1384 Returns the element representing the type of literal in \a binding. If the
1385 binding does not contain a literal value, a null Element is returned.
1386 */
1394
1395/*!
1396 Returns the element in \a context that has id \a id.
1397 */
1406
1407/*!
1408 Returns the id of \a element in a given \a context.
1409 */
1418
1419/*!
1420 Returns the source code located within \a location.
1421 */
1430
1431/*!
1432 \class QQmlSA::PassManager
1433 \inmodule QtQmlCompiler
1434
1435 \brief Can analyze an element and its children with static analysis passes.
1436 */
1437
1438// explicitly defaulted out-of-line for PIMPL
1439PassManager::PassManager() = default;
1440PassManager::~PassManager() = default;
1441
1442/*!
1443 Registers a static analysis \a pass to be run on all elements.
1444 */
1450
1451/*!
1452 \internal
1453 \brief PassManager::registerElementPass registers ElementPass
1454 with the pass manager.
1455 \param pass The registered pass. Ownership is transferred to the pass manager.
1456 */
1461
1463static QString lookupName(const QQmlSA::Element &element, LookupMode mode = Lookup)
1464{
1465 QString name;
1466 if (element.isNull() || QQmlJSScope::scope(element)->internalName().isEmpty()) {
1467 // Bail out with an invalid name, this type is so screwed up we can't do anything reasonable
1468 // with it We should have warned about it in another plac
1469 if (element.isNull() || element.baseType().isNull())
1470 return u"$INVALID$"_s;
1471 name = QQmlJSScope::scope(element.baseType())->internalName();
1472 } else {
1473 name = QQmlJSScope::scope(element)->internalName();
1474 }
1475
1476 const QString filePath =
1477 (mode == Register || !element.baseType() ? element : element.baseType()).filePath();
1478
1479 if (QQmlJSScope::scope(element)->isComposite() && !filePath.endsWith(u".h"))
1480 name += u'@' + filePath;
1481 return name;
1482}
1483
1484/*!
1485 Registers a static analysis pass for properties. The \a pass will be run on
1486 every property matching the \a moduleName, \a typeName and \a propertyName.
1487
1488 Omitting the \a propertyName will register this pass for all properties
1489 matching the \a typeName and \a moduleName.
1490
1491 Setting \a allowInheritance to \c true means that the filtering on the type
1492 also accepts types deriving from \a typeName.
1493
1494 \a pass is passed as a \c{std::shared_ptr} to allow reusing the same pass
1495 on multiple elements:
1496 \code
1497 auto titleValiadorPass = std::make_shared<TitleValidatorPass>(manager);
1498 manager->registerPropertyPass(titleValidatorPass,
1499 "QtQuick", "Window", "title");
1500 manager->registerPropertyPass(titleValidatorPass,
1501 "QtQuick.Controls", "Dialog", "title");
1502 \endcode
1503
1504 \note Running analysis passes on too many items can be expensive. This is
1505 why it is generally good to filter down the set of properties of a pass
1506 using the \a moduleName, \a typeName and \a propertyName.
1507
1508 Returns \c true if the pass was successfully added, \c false otherwise.
1509 Adding a pass fails when the \l{QQmlSA::Element}{Element} specified by
1510 \a moduleName and \a typeName does not exist.
1511
1512 \sa PropertyPass
1513*/
1521
1525{
1526 if (moduleName.isEmpty() != typeName.isEmpty()) {
1527 qWarning() << "Both the moduleName and the typeName must be specified "
1528 "for the pass to be registered for a specific element.";
1529 }
1530
1531 QString name;
1532 if (!moduleName.isEmpty() && !typeName.isEmpty()) {
1537
1538 if (element.isNull())
1539 return false;
1540
1542 }
1546
1547 return true;
1548}
1549
1570
1572 const QString prefix, bool isAttached)
1573{
1576 for (auto &binding : ownBindings) {
1577 switch (binding.bindingType()) {
1580 prefix + binding.propertyName() + u'.');
1581 continue; // don't insert into m_bindingsByLocation
1584 prefix + binding.propertyName() + u'.', true);
1585 continue; // don't insert into m_bindingsByLocation
1588 u"qsTr"_s, element, binding.sourceLocation());
1589 break;
1590 }
1593 u"qsTrId"_s, element, binding.sourceLocation());
1594 break;
1595 }
1596 default:
1597 break;
1598 }
1599
1606 }
1607}
1608
1609/*!
1610 Runs the element passes over \a root and all its children.
1611 */
1613{
1615 d->analyze(root);
1616}
1617
1618static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
1619{
1620 return QQmlJSScope::scope(element)->childScopesBegin();
1621}
1622
1623static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
1624{
1625 return QQmlJSScope::scope(element)->childScopesEnd();
1626}
1627
1629{
1632 while (!runStack.isEmpty()) {
1633 auto element = runStack.takeLast();
1635 for (auto &elementPass : m_elementPasses)
1638
1639 for (auto it = childScopesBegin(element), end = childScopesEnd(element); it != end; ++it) {
1640 if ((*it)->scopeType() == QQmlSA::ScopeType::QMLScope)
1642 }
1643 }
1644}
1645
1654
1662
1670
1673{
1674 const auto it = m_bindingsByLocation.find(location.offset());
1675
1676 // If there's no matching binding that means we're in a nested Ret somewhere inside an
1677 // expression
1678 if (it == m_bindingsByLocation.cend())
1679 return;
1680
1681 const auto &[offset, binding] = *it;
1684
1688
1690 return;
1691
1696 }
1697}
1698
1699/*!
1700 Returns \c true if the module named \a module has been imported by the
1701 QML to be analyzed, \c false otherwise.
1702
1703 This can be used to skip registering a pass which is specific to a specific
1704 module.
1705
1706 \code
1707 if (passManager->hasImportedModule("QtPositioning"))
1708 passManager->registerElementPass(
1709 std::make_unique<PositioningPass>(passManager)
1710 );
1711 \endcode
1712
1713 \sa registerPropertyPass(), registerElementPass()
1714 */
1716{
1717 return PassManagerPrivate::visitor(*this)->imports().hasType(u"$module$." + module.toString());
1718}
1719
1720/*!
1721 Returns \c true if warnings of \a category are enabled, \c false otherwise.
1722 */
1728
1733
1738
1740 const QString &propertyName)
1741{
1743
1744 for (auto it = QQmlJSScope::scope(element); it; it = it->baseType())
1746
1748
1749 for (const QString &typeName : typeNames) {
1750 for (auto &pass :
1752 if (pass.first == pass.second)
1753 continue;
1754
1755 for (auto it = pass.first; it != pass.second; it++) {
1757 continue;
1760 }
1761 }
1762 }
1763 return passes;
1764}
1765
1766/*!
1767 \class QQmlSA::LintPlugin
1768 \inmodule QtQmlCompiler
1769
1770 \brief Base class for all static analysis plugins.
1771 */
1772
1773/*!
1774 \fn LintPlugin::LintPlugin()
1775 Constructs a LintPlugin object.
1776 */
1777
1778/*!
1779 \fn virtual LintPlugin::~LintPlugin()
1780 Destroys the LintPlugin instance.
1781 */
1782
1783/*!
1784 \fn void QQmlSA::LintPlugin::registerPasses(PassManager *manager, const Element &rootElement)
1785
1786 Adds a pass \a manager that will be executed on \a rootElement.
1787 */
1788
1789/*!
1790 \class QQmlSA::ElementPass
1791 \inmodule QtQmlCompiler
1792
1793 \brief Base class for all static analysis passes on elements.
1794
1795 ElementPass is the simpler of the two analysis passes. It will consider every element in
1796 a file. The \l shouldRun() method can be used to filter out irrelevant elements, and the
1797 \l run() method is doing the initial work.
1798
1799 Common tasks suitable for an ElementPass are
1800 \list
1801 \li checking that properties of an Element are not combined in a nonsensical way
1802 \li validating property values (e.g. that a property takes only certain enum values)
1803 \li checking behavior dependent on an Element's parent (e.g. not using \l {Item::width}
1804 when the parent element is a \c Layout).
1805 \endlist
1806
1807 As shown in the snippet below, it is recommended to do necessary type resolution in the
1808 constructor of the ElementPass and cache it in local members, and to implement some
1809 filtering via \l shouldRun() to keep the static analysis performant.
1810
1811 \code
1812 using namespace QQmlSA;
1813 class MyElementPass : public ElementPass
1814 {
1815 Element myType;
1816 public:
1817 MyElementPass(QQmlSA::PassManager *manager)
1818 : myType(resolveType("MyModule", "MyType")) {}
1819
1820 bool shouldRun(const Element &element) override
1821 {
1822 return element.inherits(myType);
1823 }
1824 void run(const Element &element) override
1825 {
1826 // actual pass logic
1827 }
1828 }
1829 \endcode
1830
1831 ElementPasses have limited insight into how an element's properties are used. If you need
1832 that information, consider using a \l PropertyPass instead.
1833
1834 \note ElementPass will only ever consider instantiable types. Therefore, it is unsuitable
1835 to analyze attached types and singletons. Those need to be handled via a PropertyPass.
1836 */
1837
1838/*!
1839 \fn ElementPass::ElementPass(PassManager *manager)
1840 Creates an ElementPass object and uses \a manager to refer to the pass manager.
1841*/
1842
1843/*!
1844 \fn void QQmlSA::ElementPass::run(const Element &element)
1845
1846 Executes if \c shouldRun() returns \c true. Performs the real computation
1847 of the pass on \a element.
1848 This method is meant to be overridden. Calling the base method is not
1849 necessary.
1850 */
1851
1852/*!
1853 Controls whether the \c run() function should be executed on the given \a element.
1854 Subclasses can override this method to improve performance of the analysis by
1855 filtering out elements which are not relevant.
1856
1857 The default implementation unconditionally returns \c true.
1858 */
1860{
1861 (void)element;
1862 return true;
1863}
1864
1865/*!
1866 \class QQmlSA::PropertyPass
1867 \inmodule QtQmlCompiler
1868
1869 \brief Base class for all static analysis passes on properties.
1870 */
1871
1872
1873/*!
1874 Creates a PropertyPass object and uses \a manager to refer to the pass manager.
1875 */
1877
1878/*!
1879 Executes whenever a property gets bound to a value.
1880
1881 The property \a propertyName of \a element is bound to the \a value within
1882 \a bindingScope with \a binding.
1883 */
1894
1895/*!
1896 Executes whenever a property is read.
1897
1898 The property \a propertyName of \a element is read by an instruction within
1899 \a readScope defined at \a location.
1900
1901 This is also executed if the property \a propertyName is called as a function as that requires
1902 the property to be read first.
1903 */
1912
1913/*!
1914 Executes whenever a property or method is called.
1915
1916 The property or method \a propertyName of \a element is called as a function by an instruction
1917 within \a readScope defined at \a location.
1918
1919 \note Currently only direct calls of methods or properties are supported, indirect calls, for
1920 example by storing a method into a JavaScript variable and then calling the variable, are not
1921 recognized.
1922 */
1931
1932/*!
1933 Executes whenever a property is written to.
1934
1935 The property \a propertyName of \a element is written to by an instruction
1936 within \a writeScope defined at \a location. The type of the expression
1937 written to \a propertyName is \a expressionType.
1938 */
1949
1950/*!
1951 Returns bindings by their source location.
1952 */
1958
1959FixSuggestionPrivate::FixSuggestionPrivate(FixSuggestion *iface) : q_ptr{ iface } { }
1960
1961FixSuggestionPrivate::FixSuggestionPrivate(
1962 FixSuggestion *iface, const QString &description, const SourceLocation &location,
1963 const QList<DocumentEdit> &documentEdits)
1964 : m_fixSuggestion{ description, SourceLocationPrivate::sourceLocation(location),
1965 DocumentEditPrivate::documentEdits(documentEdits) }
1966 , q_ptr{ iface }
1967{
1968}
1969
1971 const FixSuggestionPrivate &other)
1972 : m_fixSuggestion{ other.m_fixSuggestion }, q_ptr{ iface }
1973{
1974}
1975
1977 : m_fixSuggestion{ std::move(other.m_fixSuggestion) }, q_ptr{ iface }
1978{
1979}
1980
1982{
1983 return m_fixSuggestion.description();
1984}
1985
1986QQmlSA::SourceLocation FixSuggestionPrivate::location() const
1987{
1988 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_fixSuggestion.location());
1989}
1990
1991void FixSuggestionPrivate::addDocumentEdit(const DocumentEdit &editSA)
1992{
1993 auto editJS = DocumentEditPrivate::documentEdit(editSA);
1994 m_fixSuggestion.addDocumentEdit(editJS);
1995}
1996
1998{
1999 QList<DocumentEdit> edits;
2000 for (const auto &edit : m_fixSuggestion.documentEdits())
2001 edits << DocumentEditPrivate::createQQmlSADocumentEdit(edit);
2002 return edits;
2003}
2004
2005void FixSuggestionPrivate::setFileName(const QString &fileName)
2006{
2007 m_fixSuggestion.setFilename(fileName);
2008}
2009
2011{
2012 return m_fixSuggestion.filename();
2013}
2014
2015void FixSuggestionPrivate::setAutoApplicable(bool autoApplicable)
2016{
2017 m_fixSuggestion.setAutoApplicable(autoApplicable);
2018}
2019
2021{
2022 return m_fixSuggestion.isAutoApplicable();
2023}
2024
2025QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(FixSuggestion &saFixSuggestion)
2026{
2028}
2029
2030const QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(const FixSuggestion &saFixSuggestion)
2031{
2032 return saFixSuggestion.d_func()->m_fixSuggestion;
2033}
2034
2035FixSuggestion FixSuggestionPrivate::createQQmlSAFixSuggestion(const QQmlJSFixSuggestion &jsFix)
2036{
2037 auto saLocation = SourceLocationPrivate::createQQmlSASourceLocation(jsFix.location());
2038 FixSuggestion saFix(jsFix.description(), saLocation);
2039 saFix.d_ptr->m_fixSuggestion.setDocumentEdits(jsFix.documentEdits());
2040 saFix.setAutoApplicable(jsFix.isAutoApplicable());
2041 return saFix;
2042}
2043
2044/*!
2045 \class QQmlSA::DocumentEdit
2046 \inmodule QtQmlCompiler
2047
2048 \brief Represents a single edit to a document.
2049 */
2050
2051/*!
2052 Creates a DocumentEdit object.
2053 */
2059
2060/*!
2061 Creates a copy of \a other.
2062 */
2067
2068/*!
2069 Move-constructs a DocumentEdit instance.
2070 */
2075
2076/*!
2077 Assigns \a other to this DocumentEdit instance.
2078 */
2080{
2081 if (*this == other)
2082 return *this;
2083
2085 d_func()->q_ptr = this;
2086 return *this;
2087}
2088
2089/*!
2090 Move-assigns \a other to this DocumentEdit instance.
2091 */
2093{
2094 if (*this == other)
2095 return *this;
2096
2098 d_func()->q_ptr = this;
2099 return *this;
2100}
2101
2102/*!
2103 Destroys the DocumentEdit instance.
2104 */
2105DocumentEdit::~DocumentEdit() = default;
2106
2107/*!
2108 Returns the file this edit applies to.
2109 */
2111{
2112 Q_D(const DocumentEdit);
2113 return d->filename();
2114}
2115
2116/*!
2117 Returns the location where the edit applies.
2118 */
2120{
2121 Q_D(const DocumentEdit);
2122 return d->location();
2123}
2124
2125/*!
2126 Returns the replacement string of the edit.
2127 */
2129{
2130 Q_D(const DocumentEdit);
2131 return d->replacement();
2132}
2133
2134/*!
2135 \fn friend bool DocumentEdit::operator==(const DocumentEdit &lhs, const DocumentEdit &rhs)
2136 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
2137 */
2138/*!
2139 \fn friend bool DocumentEdit::operator!=(const DocumentEdit &lhs, const DocumentEdit &rhs)
2140 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
2141 */
2142
2143
2144DocumentEditPrivate::DocumentEditPrivate(
2145 DocumentEdit *iface, const QString &filename, const SourceLocation &location,
2146 const QString &replacement)
2147 : m_documentEdit{ filename, SourceLocationPrivate::sourceLocation(location), replacement }
2148 , q_ptr{ iface }
2149{
2150}
2151
2153 DocumentEdit *iface, const DocumentEditPrivate &other)
2155{
2156}
2157
2159 DocumentEdit *iface, DocumentEditPrivate &&other)
2161{
2162}
2163
2165{
2166 return m_documentEdit.m_filename;
2167}
2168
2169QQmlSA::SourceLocation DocumentEditPrivate::location() const
2170{
2171 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_documentEdit.m_location);
2172}
2173
2175{
2176 return m_documentEdit.m_replacement;
2177}
2178
2179QQmlJSDocumentEdit DocumentEditPrivate::documentEdit(const DocumentEdit &edit)
2180{
2181 return edit.d_ptr->m_documentEdit;
2182}
2183
2184QList<QQmlJSDocumentEdit> DocumentEditPrivate::documentEdits(const QList<DocumentEdit> &editsSA)
2185{
2186 QList<QQmlJSDocumentEdit> editsJS;
2187 for (const auto &editsSA : editsSA)
2188 editsJS << DocumentEditPrivate::documentEdit(editsSA);
2189 return editsJS;
2190}
2191
2192DocumentEdit DocumentEditPrivate::createQQmlSADocumentEdit(const QQmlJSDocumentEdit &jsEdit)
2193{
2194 auto saLocation = QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(jsEdit.m_location);
2195 return DocumentEdit{ jsEdit.m_filename, saLocation, jsEdit.m_replacement };
2196}
2197
2198/*!
2199 \class QQmlSA::FixSuggestion
2200 \inmodule QtQmlCompiler
2201
2202 \brief Represents a suggested fix for an issue in the source code.
2203 */
2204
2205
2206/*!
2207 Creates a FixSuggestion object.
2208 */
2214
2215
2216/*!
2217 Creates a FixSuggestion object.
2218 */
2224
2225/*!
2226 Creates a copy of \a other.
2227 */
2232
2233/*!
2234 Move-constructs a FixSuggestion instance.
2235 */
2237 : d_ptr{ new FixSuggestionPrivate{ this, std::move(*other.d_func()) } }
2238{
2239}
2240
2241/*!
2242 Assigns \a other to this FixSuggestion instance.
2243 */
2245{
2246 if (*this == other)
2247 return *this;
2248
2250 return *this;
2251}
2252
2253/*!
2254 Move-assigns \a other to this FixSuggestion instance.
2255 */
2257{
2258 if (*this == other)
2259 return *this;
2260
2262 return *this;
2263}
2264
2265/*!
2266 Destroys the FixSuggestion instance.
2267 */
2268FixSuggestion::~FixSuggestion() = default;
2269
2270/*!
2271 Returns the description of the fix.
2272 */
2274{
2275 Q_D(const FixSuggestion);
2276 return d->description();
2277}
2278
2279/*!
2280 Returns the location of the fix.
2281 */
2283{
2284 Q_D(const FixSuggestion);
2285 return d->location();
2286}
2287
2288/*!
2289 Adds a document \a edit to the list of edits for this fix.
2290 */
2296
2297/*!
2298 Returns the list of document edits that applying this fix would make.
2299 */
2301{
2302 Q_D(const FixSuggestion);
2303 return d->documentEdits();
2304}
2305
2306/*!
2307 Sets \a fileName as the name of the file where this fix suggestion applies.
2308 */
2313
2314/*!
2315 Returns the name of the file where this fix suggestion applies.
2316 */
2318{
2320}
2321
2322/*!
2323 Sets \a autoApplicable to determine whether this suggested fix can be
2324 applied automatically.
2325 */
2331
2332/*!
2333 Returns whether this suggested fix can be applied automatically.
2334 */
2336{
2337 Q_D(const FixSuggestion);
2338 return d->isAutoApplicable();
2339}
2340
2341/*!
2342 \fn friend bool FixSuggestion::operator==(const FixSuggestion &lhs, const FixSuggestion &rhs)
2343 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
2344 */
2345/*!
2346 \fn friend bool FixSuggestion::operator!=(const FixSuggestion &lhs, const FixSuggestion &rhs)
2347 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
2348 */
2349
2351{
2353}
2354
2368
2370{
2371 return type >= BindingType::BoolLiteral && type <= BindingType::Object;
2372}
2373
2374} // namespace QQmlSA
2375
2376QT_END_NAMESPACE
BindingPrivate(Binding *, const BindingPrivate &)
Definition qqmlsa.cpp:307
\inmodule QtQmlCompiler
Definition qqmlsa.h:53
QMultiHash< QString, Binding >::const_iterator constBegin() const
Definition qqmlsa.cpp:213
QMultiHash< QString, Binding >::const_iterator constEnd() const
Definition qqmlsa.cpp:232
DocumentEditPrivate(DocumentEdit *, DocumentEditPrivate &&)
Definition qqmlsa.cpp:2158
QString replacement() const
Definition qqmlsa.cpp:2174
DocumentEditPrivate(DocumentEdit *, const DocumentEditPrivate &)
Definition qqmlsa.cpp:2152
SourceLocation location() const
Definition qqmlsa.cpp:2169
QString filename() const
Definition qqmlsa.cpp:2164
QList< DocumentEdit > documentEdits() const
Definition qqmlsa.cpp:1997
SourceLocation location() const
Definition qqmlsa.cpp:1986
QString description() const
Definition qqmlsa.cpp:1981
void setFileName(const QString &)
Definition qqmlsa.cpp:2005
void addDocumentEdit(const DocumentEdit &)
Definition qqmlsa.cpp:1991
FixSuggestionPrivate(FixSuggestion *)
Definition qqmlsa.cpp:1959
void setAutoApplicable(bool autoApplicable=true)
Definition qqmlsa.cpp:2015
FixSuggestionPrivate(FixSuggestion *, FixSuggestionPrivate &&)
Definition qqmlsa.cpp:1976
FixSuggestionPrivate(FixSuggestion *, const FixSuggestionPrivate &)
Definition qqmlsa.cpp:1970
GenericPassPrivate(GenericPass *iface, PassManager *manager)
Definition qqmlsa.cpp:1243
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
\inmodule QtQmlCompiler
MethodType
Definition qqmlsa.h:49
Q_QMLCOMPILER_EXPORT void emitWarningWithOptionalFix(GenericPass &pass, QAnyStringView diagnostic, const LoggerWarningId &id, const QQmlSA::SourceLocation &srcLocation, const std::optional< QQmlJSFixSuggestion > &fixSuggestion)
Definition qqmlsa.cpp:2355
@ Register
Definition qqmlsa.cpp:1462
static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
Definition qqmlsa.cpp:1623
static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
Definition qqmlsa.cpp:1618
bool isRegularBindingType(BindingType type)
Definition qqmlsa.cpp:2369
static QString lookupName(const QQmlSA::Element &element, LookupMode mode=Lookup)
Definition qqmlsa.cpp:1463
Combined button and popup list for selecting options.