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 GroupedProperty The binding is a \l{QML Object Attributes#Grouped Properties}{grouped property}
78 \omitvalue GroupProperty
79*/
80
81/*!
82 \enum QQmlSA::ScriptBindingKind
83 \inmodule QtQmlCompiler
84
85 \brief Describes the script type of a \l{QQmlSA::Binding} of type \l{Script}.
86 \value Invalid The binding has an invalid script
87 \value PropertyBinding The binding is bound to a property
88 \value SignalHandler The binding is a \l{Signal and Handler Event System#Receiving signals with signal handlers}{signal handler}
89 \value ChangeHandler The binding is a \l{Signal and Handler Event System#Property change signal handlers}{change handler}
90*/
91
92/*!
93 \enum QQmlSA::ScopeType
94 \brief Describes the type of QML scope.
95 \value JSFunctionScope The scope is a JavaScript function:
96 \badcode
97 Item {
98 function f() : int { <- begin
99 return 1
100 } <- end
101 }
102 \endcode
103 \value JSLexicalScope The scope is a JavaScript lexical scope:
104 \badcode
105 property int i: { <- begin
106 let a = 1
107 { <- begin
108 console.log("hello")
109 } <- end
110 return a
111 } <- end
112 \endcode
113 \value QMLScope The scope is a QML Object:
114 \badcode
115 Item { <- begin
116 x: 50
117 } <- end
118 \endcode
119 \value GroupedPropertyScope The scope is a \l{QML Object Attributes#Grouped Properties}{grouped property}:
120 \badcode
121 Text {
122 font { <- begin
123 pixelSize: 12
124 bold: true
125 } <- end
126 }
127 \endcode
128 \value AttachedPropertyScope The scope is an \l{QML Object Attributes#Attached Properties and Attached Signal Handlers}{attached property}:
129 \badcode
130 Item {
131 Component.onCompleted: console.log("Hello")
132 ^^^^^^^^^
133 \ Scope of attached property Component
134 }
135 \endcode
136 \value EnumScope The scope is a QML \l{QML Enumerations}{enum}:
137 \badcode
138 enum E { <- begin
139 A,
140 B,
141 C
142 } <- end
143 \endcode
144 \value [since 6.11] BindingFunctionScope The scope represents the expression of a binding:
145 \badcode
146 Item {
147 width: <- begin 10 +
148 2 *parent.width <- end
149 }
150 \endcode
151 Before Qt 6.11, this was reported as a JSFunctionScope
152 \value [since 6.11] SignalHandlerFunctionScope The scope represents a function used as a signal handler:
153 \badcode
154 Timer {
155 onTriggered: <- begin console.log("hi") <- end
156 }
157 \endcode
158 Before Qt 6.11, this was reported as a JSFunctionScope
159
160 Each entry is shown with an example scope of the matching type in QML code.
161*/
162
163/*!
164 \class QQmlSA::Binding::Bindings
165 \inmodule QtQmlCompiler
166
167 \brief Holds multiple property name to property binding associations.
168 */
169
170/*!
171 Constructs a new Bindings object.
172 */
174
175BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface) : q_ptr{ iface } { }
176
177/*!
178 Creates a copy of \a other.
179 */
181 : d_ptr{ new BindingsPrivate{ this, *other.d_func() } }
182{
183}
184
185/*!
186 Destroys the Bindings object.
187 */
188Binding::Bindings::~Bindings() = default;
189
190BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface, const BindingsPrivate &other)
191 : m_bindings{ other.m_bindings.begin(), other.m_bindings.end() }, q_ptr{ iface }
192{
193}
194
195BindingsPrivate::BindingsPrivate(QQmlSA::Binding::Bindings *iface, BindingsPrivate &&other)
196 : m_bindings{ std::move(other.m_bindings) }, q_ptr{ iface }
197{
198}
199
200/*!
201 Returns an iterator to the beginning of the bindings.
202 */
204{
205 Q_D(const Bindings);
206 return d->constBegin();
207}
208
209/*!
210 \fn QMultiHash<QString, Binding>::const_iterator Binding::Bindings::begin() const
211 Same as constBegin().
212 */
213
215{
216 return m_bindings.constBegin();
217}
218
219/*!
220 Returns an iterator to the end of the bindings.
221 */
223{
224 Q_D(const Bindings);
225 return d->constEnd();
226}
227
228/*!
229 \fn QMultiHash<QString, Binding>::const_iterator Binding::Bindings::end() const
230 Same as constEnd().
231 */
232
234{
235 return m_bindings.constEnd();
236}
237
238/*!
239 \class QQmlSA::Binding
240 \inmodule QtQmlCompiler
241
242 \brief Represents a single QML property binding for a specific type.
243 */
244
245/*!
246 Constructs a new Binding object.
247 */
248Binding::Binding() : d_ptr{ new BindingPrivate{ this } } { }
249
250BindingPrivate::BindingPrivate(Binding *iface) : q_ptr{ iface } { }
251
252/*!
253 Creates a copy of \a other.
254*/
255Binding::Binding(const Binding &other) : d_ptr{ new BindingPrivate{ this, *other.d_func() } } { }
256
257/*!
258 Move-constructs a \c Binding instance.
259*/
261 : d_ptr{ new BindingPrivate{ this, *other.d_func() } } { }
262
263
264/*!
265 Assigns \a other to this Binding instance.
266*/
268{
269 if (*this == other)
270 return *this;
271
272 Q_D(Binding);
275 d->q_ptr = this;
277 return *this;
278}
279
280/*!
281 Move-assigns \a other to this Binding instance.
282*/
284{
285 if (*this == other)
286 return *this;
287
288 Q_D(Binding);
291 d->q_ptr = this;
293 return *this;
294}
295
296/*!
297 Destroys the binding.
298*/
299Binding::~Binding() = default;
300
301bool Binding::operatorEqualsImpl(const Binding &lhs, const Binding &rhs)
302{
303 return lhs.d_func()->m_binding == rhs.d_func()->m_binding
306}
307
308BindingPrivate::BindingPrivate(Binding *iface, const BindingPrivate &other)
310 m_isAttached{ other.m_isAttached }
311{
312}
313
314QQmlSA::Binding BindingPrivate::createBinding(const QQmlJSMetaPropertyBinding &binding)
315{
316 QQmlSA::Binding saBinding;
317 saBinding.d_func()->m_binding = binding;
318 return saBinding;
319}
320
321QQmlJSMetaPropertyBinding BindingPrivate::binding(QQmlSA::Binding &binding)
322{
323 return binding.d_func()->m_binding;
324}
325
326const QQmlJSMetaPropertyBinding BindingPrivate::binding(const QQmlSA::Binding &binding)
327{
328 return binding.d_func()->m_binding;
329}
330
331/*!
332 Returns the type of the property of this binding if it is a grouped property,
333 otherwise returns an invalid Element.
334 */
339
340/*!
341 Returns the Element scope in which the binding is defined.
342 */
344{
345 return BindingPrivate::get(this)->m_bindingScope;
346}
347
348/*!
349 Returns the type of this binding.
350 */
355
356/*!
357 Returns the associated string literal if the content type of this binding is
358 StringLiteral, otherwise returns an empty string.
359 */
361{
362 return BindingPrivate::binding(*this).stringValue();
363}
364
365/*!
366 Returns the name of the property bound with this binding.
367 */
369{
370 return BindingPrivate::binding(*this).propertyName();
371}
372
373/*!
374 Returns \c true if this type is attached to another one, \c false otherwise.
375 */
376bool Binding::isAttached() const
377{
378 return BindingPrivate::get(this)->m_isAttached;
379}
380
381/*!
382 Returns the attached type if the content type of this binding is
383 AttachedProperty, otherwise returns an invalid Element.
384 */
389
390#if QT_DEPRECATED_SINCE(6, 9)
391/*!
392 Returns the attached type if the content type of this binding is
393 AttachedProperty, otherwise returns an invalid Element.
394
395 \deprecated [6.9] Use the better named attachedType() method.
396 */
398{
399 return attachedType();
400}
401#endif
402
403/*!
404 Returns the location in the QML code where this binding is defined.
405 */
411
412/*!
413 Returns the associated number if the content type of this binding is
414 NumberLiteral, otherwise returns 0.
415 */
416double Binding::numberValue() const
417{
418 return BindingPrivate::binding(*this).numberValue();
419}
420
421/*!
422 Returns the kind of the associated script if the content type of this
423 binding is Script, otherwise returns Invalid.
424 */
429
430/*!
431 Returns \c true if this binding has an objects, otherwise returns \c false.
432 */
433bool Binding::hasObject() const
434{
435 return BindingPrivate::binding(*this).hasObject();
436}
437
438/*!
439 Returns the type of the associated object if the content type of this
440 binding is Object, otherwise returns an invalid Element.
441 */
446
447/*!
448 Returns whether this binding has script value type undefined like when it
449 is assigned \c undefined. If the content type of this binding is not
450 \l{QQmlSA::BindingType::Script}, returns \c false.
451 */
458
459/*!
460 Returns whether this binding has script value type function like when it
461 is assigned a (lambda) method, an arrow function or a statement block. If
462 the content type of this binding is not \l{QQmlSA::BindingType::Script},
463 returns \c false.
464 */
471
472/*!
473 Returns \c true if \a bindingType is a literal type, and \c false
474 otherwise.
475 */
480
481/*!
482 \fn friend bool Binding::operator==(const Binding &lhs, const Binding &rhs)
483 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise. Two
484 \c Bindings are considered equal if their property name, content type, and
485 source location match.
486 */
487/*!
488 \fn friend bool Binding::operator!=(const Binding &lhs, const Binding &rhs)
489 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
490 Two \c Bindings are considered equal if their property name, content type,
491 and source location match.
492 */
493
494/*!
495 Constructs a new Methods object.
496*/
498
499/*!
500 Creates a copy of \a other.
501 */
503 : d_ptr{ new MethodsPrivate{ this, *other.d_func() } }
504{
505}
506
507/*!
508 Destroys the Methods instance.
509 */
510QQmlSA::Method::Methods::~Methods() = default;
511
512/*!
513 Returns an iterator to the beginning of the methods.
514 */
516{
517 Q_D(const Methods);
518 return d->constBegin();
519}
520
521/*!
522 \fn QMultiHash<QString, QQmlSA::Method>::const_iterator QQmlSA::Method::Methods::begin() const
523 Returns an iterator to the beginning of the methods.
524 */
525
527{
528 return m_methods.constBegin();
529}
530
531/*!
532 Returns an iterator to the end of the methods.
533 */
535{
536 Q_D(const Methods);
537 return d->constEnd();
538}
539
540/*!
541 \fn QMultiHash<QString, QQmlSA::Method>::const_iterator QQmlSA::Method::Methods::end() const
542 Returns an iterator to the end of the methods.
543 */
544
546{
547 return m_methods.constEnd();
548}
549
550MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface) : q_ptr{ iface } { }
551
552MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface, const MethodsPrivate &other)
554{
555}
556
557MethodsPrivate::MethodsPrivate(QQmlSA::Method::Methods *iface, MethodsPrivate &&other)
559{
560}
561
562MethodPrivate::MethodPrivate(Method *iface) : q_ptr{ iface } { }
563
564MethodPrivate::MethodPrivate(Method *iface, const MethodPrivate &other)
566{
567}
568
570{
571 return m_method.methodName();
572}
573
574QQmlSA::SourceLocation MethodPrivate::sourceLocation() const
575{
576 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_method.sourceLocation());
577}
578
580{
581 return m_method.methodType();
582}
583
584/*!
585 \class QQmlSA::Method
586 \inmodule QtQmlCompiler
587
588 \brief Represents a QML method.
589 */
590
591/*!
592 Constructs a new Method object.
593 */
594Method::Method() : d_ptr{ new MethodPrivate{ this } } { }
595
596/*!
597 Creates a copy of \a other.
598 */
599Method::Method(const Method &other) : d_ptr{ new MethodPrivate{ this, *other.d_func() } } { }
600
601/*!
602 Move-constructs a Method instance.
603 */
605 : d_ptr{ new MethodPrivate{ this, std::move(*other.d_func()) } }
606{
607}
608
609/*!
610 Assigns \a other to this Method instance.
611 */
613{
614 if (*this == other)
615 return *this;
616
618 d_func()->q_ptr = this;
619 return *this;
620}
621
622/*!
623 Move-assigns \a other to this Method instance.
624 */
626{
627 if (*this == other)
628 return *this;
629
631 d_func()->q_ptr = this;
632 return *this;
633}
634
635/*!
636 Destroys the Method.
637 */
638Method::~Method() = default;
639
640/*!
641 Returns the name of the this method.
642 */
644{
645 Q_D(const Method);
646 return d->methodName();
647}
648
649/*!
650 Returns the type of this method.
651 */
653{
654 Q_D(const Method);
655 return d->methodType();
656}
657
658/*!
659 \fn friend bool Method::operator==(const Method &lhs, const Method &rhs)
660 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
661 */
662/*!
663 \fn friend bool Method::operator!=(const Method &lhs, const Method &rhs)
664 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
665 */
666
667/*!
668 Returns the location in the QML code where this method is defined.
669 */
671{
672 Q_D(const Method);
673 return d->sourceLocation();
674}
675
676bool Method::operatorEqualsImpl(const Method &lhs, const Method &rhs)
677{
678 return lhs.d_func()->m_method == rhs.d_func()->m_method;
679}
680
681QQmlSA::Method MethodPrivate::createMethod(const QQmlJSMetaMethod &jsMethod)
682{
683 QQmlSA::Method saMethod;
684 auto &wrappedMethod = saMethod.d_func()->m_method;
685 wrappedMethod = jsMethod;
686 return saMethod;
687}
688
689QQmlSA::Method::Methods
690MethodsPrivate::createMethods(const QMultiHash<QString, QQmlJSMetaMethod> &hash)
691{
692 QMultiHash<QString, QQmlSA::Method> saMethods;
693 for (const auto &[key, value] : hash.asKeyValueRange()) {
694 saMethods.insert(key, MethodPrivate::createMethod(value));
695 }
696
697 QQmlSA::Method::Methods methods;
698 methods.d_func()->m_methods = std::move(saMethods);
699 return methods;
700}
701
702QQmlJSMetaMethod MethodPrivate::method(const QQmlSA::Method &method)
703{
704 return method.d_func()->m_method;
705}
706
707/*!
708 \class QQmlSA::PropertyPrivate
709 \inmodule QtQmlCompiler
710 \internal
711*/
713
718
723
725{
726 return m_property.typeName();
727}
728
730{
731 return m_property.isValid();
732}
733
734/*!
735 Returns whether this property is readonly. Properties defined in QML are readonly when their
736 definition has the 'readonly' keyword. Properties defined in C++ are readonly when they do not
737 have a WRITE accessor function.
738 */
740{
741 return !m_property.isWritable();
742}
743
744/*!
745 Returns the type that this property was defined with.
746 */
751
756
764
765/*!
766 \class QQmlSA::Property
767 \inmodule QtQmlCompiler
768
769 \brief Represents a QML property.
770 */
771
772/*!
773 Constructs a new Property object.
774 */
775Property::Property() : d_ptr{ new PropertyPrivate{ this } } { }
776
777/*!
778 Creates a copy of \a other.
779 */
781 : d_ptr{ new PropertyPrivate{ this, *other.d_func() } } { }
782
783/*!
784 Move-constructs a Property instance.
785 */
787 : d_ptr{ new PropertyPrivate{ this, std::move(*other.d_func()) } }
788{
789}
790
791/*!
792 Assigns \a other to this Property instance.
793 */
795{
796 if (*this == other)
797 return *this;
798
800 d_func()->q_ptr = this;
801 return *this;
802}
803
804/*!
805 Move-assigns \a other to this Property instance.
806 */
808{
809 if (*this == other)
810 return *this;
811
813 d_func()->q_ptr = this;
814 return *this;
815}
816
817/*!
818 Destroys this property.
819 */
820Property::~Property() = default;
821
822/*!
823 Returns the name of the type of this property.
824 */
826{
827 Q_D(const Property);
828 return d->typeName();
829}
830
831/*!
832 Returns \c true if this property is valid, \c false otherwise.
833 */
834bool Property::isValid() const
835{
836 Q_D(const Property);
837 return d->isValid();
838}
839
840/*!
841 Returns \c true if this property is read-only, \c false otherwise.
842 */
843bool Property::isReadonly() const
844{
845 Q_D(const Property);
846 return d->isReadonly();
847}
848
849/*!
850 Returns the type of this property.
851*/
853{
854 Q_D(const Property);
855 return d->type();
856}
857
858/*!
859 \fn friend bool Property::operator==(const Property &lhs, const Property &rhs)
860 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
861 */
862/*!
863 \fn friend bool Property::operator!=(const Property &lhs, const Property &rhs)
864 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
865 */
866
867
869{
870 return lhs.d_func()->m_property == rhs.d_func()->m_property;
871}
872
873/*!
874 \class QQmlSA::Element
875 \inmodule QtQmlCompiler
876
877 \brief Represents a QML type.
878 */
879
880/*!
881 Constructs a new Element object.
882 */
884{
885 new (m_data) QQmlJSScope::ConstPtr();
886}
887
888/*!
889 Creates a copy of \a other.
890 */
895
896/*!
897 \fn Element::Element(Element &&other) noexcept
898 Move-constructs an Element instance.
899 */
900
901/*!
902 Assigns \a other to this element instance.
903 */
905{
906 if (this == &other)
907 return *this;
908
909 *reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data) = QQmlJSScope::scope(other);
910 return *this;
911}
912
913/*!
914 \fn QQmlSA::Element &QQmlSA::Element::operator=(QQmlSA::Element &&other)
915 Move-assigns \a other to this Element instance.
916 */
917
918/*!
919 Destroys the element.
920 */
922{
923 (*reinterpret_cast<QQmlJSScope::ConstPtr *>(m_data)).QQmlJSScope::ConstPtr::~ConstPtr();
924}
925
926/*!
927 Returns the type of Element's scope.
928 */
930{
931 return QQmlJSScope::scope(*this)->scopeType();
932}
933
934/*!
935 Returns the Element this Element derives from.
936 */
941
942/*!
943 Returns the name of the Element this Element derives from.
944 */
949
950/*!
951 Returns the Element that encloses this Element.
952 */
957
958/*!
959 Returns whether this Element inherits from \a element.
960 */
961bool Element::inherits(const Element &element) const
962{
964}
965
966/*!
967 Returns whether this Element is the root component of its QML file.
968 */
970{
971 return QQmlJSScope::scope(*this)->isFileRootComponent();
972}
973
974/*!
975 Returns \c true if this element is null, \c false otherwise.
976 */
977bool Element::isNull() const
978{
979 return QQmlJSScope::scope(*this).isNull();
980}
981
982/*!
983 \internal
984 */
986{
987 return QQmlJSScope::scope(*this)->internalName();
988}
989
990/*!
991 Returns the access semantics of this Element. For example, Reference,
992 Value or Sequence.
993 */
995{
996 return QQmlJSScope::scope(*this)->accessSemantics();
997}
998
999/*!
1000 Returns \c true for objects defined from Qml, and \c false for objects declared from C++.
1001 */
1003{
1004 return QQmlJSScope::scope(*this)->isComposite();
1005}
1006
1007/*!
1008 Returns whether this Element has a property with the name \a propertyName.
1009 */
1011{
1012 return QQmlJSScope::scope(*this)->hasProperty(propertyName);
1013}
1014
1015/*!
1016 Returns whether this Element defines a property with the name \a propertyName
1017 which is not defined on its base or extension objects.
1018 */
1020{
1022}
1023
1024/*!
1025 Returns the property with the name \a propertyName if it is found in this
1026 Element or its base and extension objects, otherwise returns an invalid property.
1027 */
1032
1033/*!
1034 Returns whether the property with the name \a propertyName resolved on this
1035 Element is required. Returns false if the the property couldn't be found.
1036 */
1041
1042/*!
1043 Returns the name of the default property of this Element. If it doesn't
1044 have one, returns an empty string.
1045 */
1047{
1048 return QQmlJSScope::scope(*this)->defaultPropertyName();
1049}
1050
1051/*!
1052 Returns whether this Element has a method with the name \a methodName.
1053 */
1055{
1056 return QQmlJSScope::scope(*this)->hasMethod(methodName);
1057}
1058
1059/*!
1060 \class QQmlSA::Method::Methods
1061 \inmodule QtQmlCompiler
1062
1063 \brief Holds multiple method name to method associations.
1064 */
1065
1066/*!
1067 Returns this Elements's methods, which are not defined on its base or
1068 extension objects.
1069 */
1074
1075/*!
1076 Returns the location in the QML code where this Element is defined.
1077 */
1083
1084/*!
1085 Returns the location in the QML code where this Element is assigned its id, if it has one.
1086 */
1092
1093/*!
1094 Returns the file path of the QML code that defines this Element.
1095 */
1097{
1098 return QQmlJSScope::scope(*this)->filePath();
1099}
1100
1101/*!
1102 Returns whether this Element has a property binding with the name \a name.
1103 */
1105{
1106 return QQmlJSScope::scope(*this)->hasPropertyBindings(name);
1107}
1108
1109/*!
1110 Returns whether this Element has property bindings which are not defined in
1111 its base or extension objects and that have name \a propertyName.
1112 */
1117
1118/*!
1119 Returns this Element's property bindings which are not defined on its base
1120 or extension objects.
1121 */
1126
1127/*!
1128 Returns this Element's property bindings which are not defined on its base
1129 or extension objects and that have the name \a propertyName.
1130 */
1136
1137/*!
1138 Returns this Element's property bindings that have the name \a propertyName.
1139 */
1141{
1142 const auto &bindings = QQmlJSScope::scope(*this)->propertyBindings(propertyName);
1143
1145 for (const auto &jsBinding : bindings) {
1147 }
1148 return saBindings;
1149}
1150
1151QQmlSA::Binding::Bindings
1152BindingsPrivate::createBindings(const QMultiHash<QString, QQmlJSMetaPropertyBinding> &hash)
1153{
1154 QMultiHash<QString, QQmlSA::Binding> saBindings;
1155 for (const auto &[key, value] : hash.asKeyValueRange()) {
1156 saBindings.insert(key, BindingPrivate::createBinding(value));
1157 }
1158
1159 QQmlSA::Binding::Bindings bindings;
1160 bindings.d_func()->m_bindings = std::move(saBindings);
1161 return bindings;
1162}
1163
1177
1178/*!
1179 Returns \c true if this element is not null, \c false otherwise.
1180 */
1181Element::operator bool() const
1182{
1183 return bool(QQmlJSScope::scope(*this));
1184}
1185
1186/*!
1187 Returns \c true if this element is null, \c false otherwise.
1188 */
1189bool Element::operator!() const
1190{
1191 return !QQmlJSScope::scope(*this);
1192}
1193
1194/*!
1195 Returns the name of this Element.
1196 */
1198{
1199 if (isNull())
1200 return {};
1202}
1203
1204/*!
1205 \fn friend inline bool Element::operator==(const Element &lhs, const Element &rhs)
1206 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
1207 */
1208/*!
1209 \fn friend inline bool Element::operator!=(const Element &lhs, const Element &rhs)
1210 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
1211 */
1212
1213bool Element::operatorEqualsImpl(const Element &lhs, const Element &rhs)
1214{
1215 return QQmlJSScope::scope(lhs) == QQmlJSScope::scope(rhs);
1216}
1217
1218/*!
1219 \fn size_t Element::qHash(const Element &key, size_t seed)
1220 \qhash{Element}
1221*/
1222
1223size_t Element::hash(size_t seed) const noexcept
1224{
1225 return qHash(QQmlJSScope::scope(*this), seed);
1226}
1227
1228/*!
1229 \class QQmlSA::GenericPass
1230 \inmodule QtQmlCompiler
1231
1232 \brief The base class for static analysis passes.
1233
1234 This class contains common functionality used by more specific passses.
1235 Custom passes should not directly derive from it, but rather from one of
1236 its subclasses.
1237 \sa ElementPass, PropertyPass
1238 */
1239
1241 Q_DECLARE_PUBLIC(GenericPass);
1242
1243public:
1244 GenericPassPrivate(GenericPass *iface, PassManager *manager)
1245 : m_manager{ manager }, q_ptr{ iface }
1246 {
1247 Q_ASSERT(manager);
1248 }
1249
1250private:
1251 PassManager *m_manager = nullptr;
1252
1253 GenericPass *q_ptr = nullptr;
1254};
1255
1256/*!
1257 Creates a generic pass.
1258 */
1261
1262/*!
1263 Destroys the GenericPass instance.
1264 */
1265GenericPass::~GenericPass() = default;
1266
1267/*!
1268 Emits a warning message \a diagnostic about an issue of type \a id.
1269 */
1274
1275/*!
1276 Emits warning message \a diagnostic about an issue of type \a id located at
1277 \a srcLocation.
1278 */
1288
1289/*!
1290 Emits a warning message \a diagnostic about an issue of type \a id located at
1291 \a srcLocation and with suggested fix \a fix.
1292 */
1303
1304/*!
1305 Returns the type corresponding to \a typeName inside the
1306 currently analysed file.
1307 */
1315
1316/*!
1317 Returns the attached type corresponding to \a typeName used inside
1318 the currently analysed file.
1319 */
1330
1331/*!
1332 Returns the type of \a typeName defined in module \a moduleName.
1333 If an attached type and a non-attached type share the same name
1334 (for example, \c ListView), the \l Element corresponding to the
1335 non-attached type is returned.
1336 To obtain the attached type, use \l resolveAttached.
1337 */
1347
1348/*!
1349 Returns the type of the built-in type identified by \a typeName.
1350 Built-in types encompass \c{C++} types which the QML engine can handle
1351 without any imports (e.g. \l QDateTime and \l QString), global EcmaScript
1352 objects like \c Number, as well as the \l {QML Global Object}
1353 {global Qt object}.
1354 */
1356{
1357 Q_D(const GenericPass);
1360 // we have to check both cpp names
1362 if (!scope) {
1363 // and qml names (e.g. for bool) - builtinImportHelper is private, so we can't do it in one call
1366 }
1368}
1369
1370/*!
1371 Returns the attached type of \a typeName defined in module \a moduleName.
1372 */
1383
1384/*!
1385 Returns the element representing the type of literal in \a binding. If the
1386 binding does not contain a literal value, a null Element is returned.
1387 */
1395
1396/*!
1397 Returns the element in \a context that has id \a id.
1398 */
1407
1408/*!
1409 Returns the id of \a element in a given \a context.
1410 */
1419
1420/*!
1421 Returns the source code located within \a location.
1422 */
1431
1432/*!
1433 \class QQmlSA::PassManager
1434 \inmodule QtQmlCompiler
1435
1436 \brief Can analyze an element and its children with static analysis passes.
1437 */
1438
1439// explicitly defaulted out-of-line for PIMPL
1440PassManager::PassManager() = default;
1441PassManager::~PassManager() = default;
1442
1443/*!
1444 Registers a static analysis \a pass to be run on all elements.
1445 */
1451
1452/*!
1453 \internal
1454 \brief PassManager::registerElementPass registers ElementPass
1455 with the pass manager.
1456 \param pass The registered pass. Ownership is transferred to the pass manager.
1457 */
1462
1464static QString lookupName(const QQmlSA::Element &element, LookupMode mode = Lookup)
1465{
1466 QString name;
1467 if (element.isNull() || QQmlJSScope::scope(element)->internalName().isEmpty()) {
1468 // Bail out with an invalid name, this type is so screwed up we can't do anything reasonable
1469 // with it We should have warned about it in another plac
1470 if (element.isNull() || element.baseType().isNull())
1471 return u"$INVALID$"_s;
1472 name = QQmlJSScope::scope(element.baseType())->internalName();
1473 } else {
1474 name = QQmlJSScope::scope(element)->internalName();
1475 }
1476
1477 const QString filePath =
1478 (mode == Register || !element.baseType() ? element : element.baseType()).filePath();
1479
1480 if (QQmlJSScope::scope(element)->isComposite() && !filePath.endsWith(u".h"))
1481 name += u'@' + filePath;
1482 return name;
1483}
1484
1485/*!
1486 Registers a static analysis pass for properties. The \a pass will be run on
1487 every property matching the \a moduleName, \a typeName and \a propertyName.
1488
1489 Omitting the \a propertyName will register this pass for all properties
1490 matching the \a typeName and \a moduleName.
1491
1492 Setting \a allowInheritance to \c true means that the filtering on the type
1493 also accepts types deriving from \a typeName.
1494
1495 \a pass is passed as a \c{std::shared_ptr} to allow reusing the same pass
1496 on multiple elements:
1497 \code
1498 auto titleValiadorPass = std::make_shared<TitleValidatorPass>(manager);
1499 manager->registerPropertyPass(titleValidatorPass,
1500 "QtQuick", "Window", "title");
1501 manager->registerPropertyPass(titleValidatorPass,
1502 "QtQuick.Controls", "Dialog", "title");
1503 \endcode
1504
1505 \note Running analysis passes on too many items can be expensive. This is
1506 why it is generally good to filter down the set of properties of a pass
1507 using the \a moduleName, \a typeName and \a propertyName.
1508
1509 Returns \c true if the pass was successfully added, \c false otherwise.
1510 Adding a pass fails when the \l{QQmlSA::Element}{Element} specified by
1511 \a moduleName and \a typeName does not exist.
1512
1513 \sa PropertyPass
1514*/
1522
1526{
1527 if (moduleName.isEmpty() != typeName.isEmpty()) {
1528 qWarning() << "Both the moduleName and the typeName must be specified "
1529 "for the pass to be registered for a specific element.";
1530 }
1531
1532 QString name;
1533 if (!moduleName.isEmpty() && !typeName.isEmpty()) {
1538
1539 if (element.isNull())
1540 return false;
1541
1543 }
1547
1548 return true;
1549}
1550
1571
1573 const QString prefix, bool isAttached)
1574{
1577 for (auto &binding : ownBindings) {
1578 switch (binding.bindingType()) {
1581 prefix + binding.propertyName() + u'.');
1582 continue; // don't insert into m_bindingsByLocation
1585 prefix + binding.propertyName() + u'.', true);
1586 continue; // don't insert into m_bindingsByLocation
1589 u"qsTr"_s, element, binding.sourceLocation());
1590 break;
1591 }
1594 u"qsTrId"_s, element, binding.sourceLocation());
1595 break;
1596 }
1597 default:
1598 break;
1599 }
1600
1607 }
1608}
1609
1610/*!
1611 Runs the element passes over \a root and all its children.
1612 */
1614{
1616 d->analyze(root);
1617}
1618
1619static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
1620{
1621 return QQmlJSScope::scope(element)->childScopesBegin();
1622}
1623
1624static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
1625{
1626 return QQmlJSScope::scope(element)->childScopesEnd();
1627}
1628
1630{
1633 while (!runStack.isEmpty()) {
1634 auto element = runStack.takeLast();
1636 for (auto &elementPass : m_elementPasses)
1639
1640 for (auto it = childScopesBegin(element), end = childScopesEnd(element); it != end; ++it) {
1641 if ((*it)->scopeType() == QQmlSA::ScopeType::QMLScope)
1643 }
1644 }
1645}
1646
1655
1663
1671
1674{
1675 const auto it = m_bindingsByLocation.find(location.offset());
1676
1677 // If there's no matching binding that means we're in a nested Ret somewhere inside an
1678 // expression
1679 if (it == m_bindingsByLocation.cend())
1680 return;
1681
1682 const auto &[offset, binding] = *it;
1685
1689
1691 return;
1692
1697 }
1698}
1699
1700/*!
1701 Returns \c true if the module named \a module has been imported by the
1702 QML to be analyzed, \c false otherwise.
1703
1704 This can be used to skip registering a pass which is specific to a specific
1705 module.
1706
1707 \code
1708 if (passManager->hasImportedModule("QtPositioning"))
1709 passManager->registerElementPass(
1710 std::make_unique<PositioningPass>(passManager)
1711 );
1712 \endcode
1713
1714 \sa registerPropertyPass(), registerElementPass()
1715 */
1717{
1718 return PassManagerPrivate::visitor(*this)->imports().hasType(u"$module$." + module.toString());
1719}
1720
1721/*!
1722 Returns \c true if warnings of \a category are enabled, \c false otherwise.
1723 */
1729
1734
1739
1741 const QString &propertyName)
1742{
1744
1745 for (auto it = QQmlJSScope::scope(element); it; it = it->baseType())
1747
1749
1750 for (const QString &typeName : typeNames) {
1751 for (auto &pass :
1753 if (pass.first == pass.second)
1754 continue;
1755
1756 for (auto it = pass.first; it != pass.second; it++) {
1758 continue;
1761 }
1762 }
1763 }
1764 return passes;
1765}
1766
1767/*!
1768 \class QQmlSA::LintPlugin
1769 \inmodule QtQmlCompiler
1770
1771 \brief Base class for all static analysis plugins.
1772 */
1773
1774/*!
1775 \fn LintPlugin::LintPlugin()
1776 Constructs a LintPlugin object.
1777 */
1778
1779/*!
1780 \fn virtual LintPlugin::~LintPlugin()
1781 Destroys the LintPlugin instance.
1782 */
1783
1784/*!
1785 \fn void QQmlSA::LintPlugin::registerPasses(PassManager *manager, const Element &rootElement)
1786
1787 Adds a pass \a manager that will be executed on \a rootElement.
1788 */
1789
1790/*!
1791 \class QQmlSA::ElementPass
1792 \inmodule QtQmlCompiler
1793
1794 \brief Base class for all static analysis passes on elements.
1795
1796 ElementPass is the simpler of the two analysis passes. It will consider every element in
1797 a file. The \l shouldRun() method can be used to filter out irrelevant elements, and the
1798 \l run() method is doing the initial work.
1799
1800 Common tasks suitable for an ElementPass are
1801 \list
1802 \li checking that properties of an Element are not combined in a nonsensical way
1803 \li validating property values (e.g. that a property takes only certain enum values)
1804 \li checking behavior dependent on an Element's parent (e.g. not using \l {Item::width}
1805 when the parent element is a \c Layout).
1806 \endlist
1807
1808 As shown in the snippet below, it is recommended to do necessary type resolution in the
1809 constructor of the ElementPass and cache it in local members, and to implement some
1810 filtering via \l shouldRun() to keep the static analysis performant.
1811
1812 \code
1813 using namespace QQmlSA;
1814 class MyElementPass : public ElementPass
1815 {
1816 Element myType;
1817 public:
1818 MyElementPass(QQmlSA::PassManager *manager)
1819 : myType(resolveType("MyModule", "MyType")) {}
1820
1821 bool shouldRun(const Element &element) override
1822 {
1823 return element.inherits(myType);
1824 }
1825 void run(const Element &element) override
1826 {
1827 // actual pass logic
1828 }
1829 }
1830 \endcode
1831
1832 ElementPasses have limited insight into how an element's properties are used. If you need
1833 that information, consider using a \l PropertyPass instead.
1834
1835 \note ElementPass will only ever consider instantiable types. Therefore, it is unsuitable
1836 to analyze attached types and singletons. Those need to be handled via a PropertyPass.
1837 */
1838
1839/*!
1840 \fn ElementPass::ElementPass(PassManager *manager)
1841 Creates an ElementPass object and uses \a manager to refer to the pass manager.
1842*/
1843
1844/*!
1845 \fn void QQmlSA::ElementPass::run(const Element &element)
1846
1847 Executes if \c shouldRun() returns \c true. Performs the real computation
1848 of the pass on \a element.
1849 This method is meant to be overridden. Calling the base method is not
1850 necessary.
1851 */
1852
1853/*!
1854 Controls whether the \c run() function should be executed on the given \a element.
1855 Subclasses can override this method to improve performance of the analysis by
1856 filtering out elements which are not relevant.
1857
1858 The default implementation unconditionally returns \c true.
1859 */
1861{
1862 (void)element;
1863 return true;
1864}
1865
1866/*!
1867 \class QQmlSA::PropertyPass
1868 \inmodule QtQmlCompiler
1869
1870 \brief Base class for all static analysis passes on properties.
1871 */
1872
1873
1874/*!
1875 Creates a PropertyPass object and uses \a manager to refer to the pass manager.
1876 */
1878
1879/*!
1880 Executes whenever a property gets bound to a value.
1881
1882 The property \a propertyName of \a element is bound to the \a value within
1883 \a bindingScope with \a binding.
1884 */
1895
1896/*!
1897 Executes whenever a property is read.
1898
1899 The property \a propertyName of \a element is read by an instruction within
1900 \a readScope defined at \a location.
1901
1902 This is also executed if the property \a propertyName is called as a function as that requires
1903 the property to be read first.
1904 */
1913
1914/*!
1915 Executes whenever a property or method is called.
1916
1917 The property or method \a propertyName of \a element is called as a function by an instruction
1918 within \a readScope defined at \a location.
1919
1920 \note Currently only direct calls of methods or properties are supported, indirect calls, for
1921 example by storing a method into a JavaScript variable and then calling the variable, are not
1922 recognized.
1923 */
1932
1933/*!
1934 Executes whenever a property is written to.
1935
1936 The property \a propertyName of \a element is written to by an instruction
1937 within \a writeScope defined at \a location. The type of the expression
1938 written to \a propertyName is \a expressionType.
1939 */
1950
1951/*!
1952 Returns bindings by their source location.
1953 */
1959
1960FixSuggestionPrivate::FixSuggestionPrivate(FixSuggestion *iface) : q_ptr{ iface } { }
1961
1962FixSuggestionPrivate::FixSuggestionPrivate(
1963 FixSuggestion *iface, const QString &description, const SourceLocation &location,
1964 const QList<DocumentEdit> &documentEdits)
1965 : m_fixSuggestion{ description, SourceLocationPrivate::sourceLocation(location),
1966 DocumentEditPrivate::documentEdits(documentEdits) }
1967 , q_ptr{ iface }
1968{
1969}
1970
1972 const FixSuggestionPrivate &other)
1973 : m_fixSuggestion{ other.m_fixSuggestion }, q_ptr{ iface }
1974{
1975}
1976
1978 : m_fixSuggestion{ std::move(other.m_fixSuggestion) }, q_ptr{ iface }
1979{
1980}
1981
1983{
1984 return m_fixSuggestion.description();
1985}
1986
1987QQmlSA::SourceLocation FixSuggestionPrivate::location() const
1988{
1989 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_fixSuggestion.location());
1990}
1991
1992void FixSuggestionPrivate::addDocumentEdit(const DocumentEdit &editSA)
1993{
1994 auto editJS = DocumentEditPrivate::documentEdit(editSA);
1995 m_fixSuggestion.addDocumentEdit(editJS);
1996}
1997
1999{
2000 QList<DocumentEdit> edits;
2001 for (const auto &edit : m_fixSuggestion.documentEdits())
2002 edits << DocumentEditPrivate::createQQmlSADocumentEdit(edit);
2003 return edits;
2004}
2005
2006void FixSuggestionPrivate::setFileName(const QString &fileName)
2007{
2008 m_fixSuggestion.setFilename(fileName);
2009}
2010
2012{
2013 return m_fixSuggestion.filename();
2014}
2015
2016void FixSuggestionPrivate::setAutoApplicable(bool autoApplicable)
2017{
2018 m_fixSuggestion.setAutoApplicable(autoApplicable);
2019}
2020
2022{
2023 return m_fixSuggestion.isAutoApplicable();
2024}
2025
2026QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(FixSuggestion &saFixSuggestion)
2027{
2029}
2030
2031const QQmlJSFixSuggestion &FixSuggestionPrivate::fixSuggestion(const FixSuggestion &saFixSuggestion)
2032{
2033 return saFixSuggestion.d_func()->m_fixSuggestion;
2034}
2035
2036FixSuggestion FixSuggestionPrivate::createQQmlSAFixSuggestion(const QQmlJSFixSuggestion &jsFix)
2037{
2038 auto saLocation = SourceLocationPrivate::createQQmlSASourceLocation(jsFix.location());
2039 FixSuggestion saFix(jsFix.description(), saLocation);
2040 saFix.d_ptr->m_fixSuggestion.setDocumentEdits(jsFix.documentEdits());
2041 saFix.setAutoApplicable(jsFix.isAutoApplicable());
2042 return saFix;
2043}
2044
2045/*!
2046 \class QQmlSA::DocumentEdit
2047 \inmodule QtQmlCompiler
2048
2049 \brief Represents a single edit to a document.
2050 */
2051
2052/*!
2053 Creates a DocumentEdit object.
2054 */
2060
2061/*!
2062 Creates a copy of \a other.
2063 */
2068
2069/*!
2070 Move-constructs a DocumentEdit instance.
2071 */
2076
2077/*!
2078 Assigns \a other to this DocumentEdit instance.
2079 */
2081{
2082 if (*this == other)
2083 return *this;
2084
2086 d_func()->q_ptr = this;
2087 return *this;
2088}
2089
2090/*!
2091 Move-assigns \a other to this DocumentEdit instance.
2092 */
2094{
2095 if (*this == other)
2096 return *this;
2097
2099 d_func()->q_ptr = this;
2100 return *this;
2101}
2102
2103/*!
2104 Destroys the DocumentEdit instance.
2105 */
2106DocumentEdit::~DocumentEdit() = default;
2107
2108/*!
2109 Returns the file this edit applies to.
2110 */
2112{
2113 Q_D(const DocumentEdit);
2114 return d->filename();
2115}
2116
2117/*!
2118 Returns the location where the edit applies.
2119 */
2121{
2122 Q_D(const DocumentEdit);
2123 return d->location();
2124}
2125
2126/*!
2127 Returns the replacement string of the edit.
2128 */
2130{
2131 Q_D(const DocumentEdit);
2132 return d->replacement();
2133}
2134
2135/*!
2136 \fn friend bool DocumentEdit::operator==(const DocumentEdit &lhs, const DocumentEdit &rhs)
2137 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
2138 */
2139/*!
2140 \fn friend bool DocumentEdit::operator!=(const DocumentEdit &lhs, const DocumentEdit &rhs)
2141 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
2142 */
2143
2144
2145DocumentEditPrivate::DocumentEditPrivate(
2146 DocumentEdit *iface, const QString &filename, const SourceLocation &location,
2147 const QString &replacement)
2148 : m_documentEdit{ filename, SourceLocationPrivate::sourceLocation(location), replacement }
2149 , q_ptr{ iface }
2150{
2151}
2152
2154 DocumentEdit *iface, const DocumentEditPrivate &other)
2156{
2157}
2158
2160 DocumentEdit *iface, DocumentEditPrivate &&other)
2162{
2163}
2164
2166{
2167 return m_documentEdit.m_filename;
2168}
2169
2170QQmlSA::SourceLocation DocumentEditPrivate::location() const
2171{
2172 return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_documentEdit.m_location);
2173}
2174
2176{
2177 return m_documentEdit.m_replacement;
2178}
2179
2180QQmlJSDocumentEdit DocumentEditPrivate::documentEdit(const DocumentEdit &edit)
2181{
2182 return edit.d_ptr->m_documentEdit;
2183}
2184
2185QList<QQmlJSDocumentEdit> DocumentEditPrivate::documentEdits(const QList<DocumentEdit> &editsSA)
2186{
2187 QList<QQmlJSDocumentEdit> editsJS;
2188 for (const auto &editsSA : editsSA)
2189 editsJS << DocumentEditPrivate::documentEdit(editsSA);
2190 return editsJS;
2191}
2192
2193DocumentEdit DocumentEditPrivate::createQQmlSADocumentEdit(const QQmlJSDocumentEdit &jsEdit)
2194{
2195 auto saLocation = QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(jsEdit.m_location);
2196 return DocumentEdit{ jsEdit.m_filename, saLocation, jsEdit.m_replacement };
2197}
2198
2199/*!
2200 \class QQmlSA::FixSuggestion
2201 \inmodule QtQmlCompiler
2202
2203 \brief Represents a suggested fix for an issue in the source code.
2204 */
2205
2206
2207/*!
2208 Creates a FixSuggestion object.
2209 */
2215
2216
2217/*!
2218 Creates a FixSuggestion object.
2219 */
2225
2226/*!
2227 Creates a copy of \a other.
2228 */
2233
2234/*!
2235 Move-constructs a FixSuggestion instance.
2236 */
2238 : d_ptr{ new FixSuggestionPrivate{ this, std::move(*other.d_func()) } }
2239{
2240}
2241
2242/*!
2243 Assigns \a other to this FixSuggestion instance.
2244 */
2246{
2247 if (*this == other)
2248 return *this;
2249
2251 return *this;
2252}
2253
2254/*!
2255 Move-assigns \a other to this FixSuggestion instance.
2256 */
2258{
2259 if (*this == other)
2260 return *this;
2261
2263 return *this;
2264}
2265
2266/*!
2267 Destroys the FixSuggestion instance.
2268 */
2269FixSuggestion::~FixSuggestion() = default;
2270
2271/*!
2272 Returns the description of the fix.
2273 */
2275{
2276 Q_D(const FixSuggestion);
2277 return d->description();
2278}
2279
2280/*!
2281 Returns the location of the fix.
2282 */
2284{
2285 Q_D(const FixSuggestion);
2286 return d->location();
2287}
2288
2289/*!
2290 Adds a document \a edit to the list of edits for this fix.
2291 */
2297
2298/*!
2299 Returns the list of document edits that applying this fix would make.
2300 */
2302{
2303 Q_D(const FixSuggestion);
2304 return d->documentEdits();
2305}
2306
2307/*!
2308 Sets \a fileName as the name of the file where this fix suggestion applies.
2309 */
2314
2315/*!
2316 Returns the name of the file where this fix suggestion applies.
2317 */
2319{
2321}
2322
2323/*!
2324 Sets \a autoApplicable to determine whether this suggested fix can be
2325 applied automatically.
2326 */
2332
2333/*!
2334 Returns whether this suggested fix can be applied automatically.
2335 */
2337{
2338 Q_D(const FixSuggestion);
2339 return d->isAutoApplicable();
2340}
2341
2342/*!
2343 \fn friend bool FixSuggestion::operator==(const FixSuggestion &lhs, const FixSuggestion &rhs)
2344 Returns \c true if \a lhs and \a rhs are equal, and \c false otherwise.
2345 */
2346/*!
2347 \fn friend bool FixSuggestion::operator!=(const FixSuggestion &lhs, const FixSuggestion &rhs)
2348 Returns \c true if \a lhs and \a rhs are not equal, and \c false otherwise.
2349 */
2350
2352{
2354}
2355
2369
2371{
2372 return type >= BindingType::BoolLiteral && type <= BindingType::Object;
2373}
2374
2375} // namespace QQmlSA
2376
2377QT_END_NAMESPACE
BindingPrivate(Binding *, const BindingPrivate &)
Definition qqmlsa.cpp:308
\inmodule QtQmlCompiler
Definition qqmlsa.h:53
QMultiHash< QString, Binding >::const_iterator constBegin() const
Definition qqmlsa.cpp:214
QMultiHash< QString, Binding >::const_iterator constEnd() const
Definition qqmlsa.cpp:233
DocumentEditPrivate(DocumentEdit *, DocumentEditPrivate &&)
Definition qqmlsa.cpp:2159
QString replacement() const
Definition qqmlsa.cpp:2175
DocumentEditPrivate(DocumentEdit *, const DocumentEditPrivate &)
Definition qqmlsa.cpp:2153
SourceLocation location() const
Definition qqmlsa.cpp:2170
QString filename() const
Definition qqmlsa.cpp:2165
QList< DocumentEdit > documentEdits() const
Definition qqmlsa.cpp:1998
SourceLocation location() const
Definition qqmlsa.cpp:1987
QString description() const
Definition qqmlsa.cpp:1982
void setFileName(const QString &)
Definition qqmlsa.cpp:2006
void addDocumentEdit(const DocumentEdit &)
Definition qqmlsa.cpp:1992
FixSuggestionPrivate(FixSuggestion *)
Definition qqmlsa.cpp:1960
void setAutoApplicable(bool autoApplicable=true)
Definition qqmlsa.cpp:2016
FixSuggestionPrivate(FixSuggestion *, FixSuggestionPrivate &&)
Definition qqmlsa.cpp:1977
FixSuggestionPrivate(FixSuggestion *, const FixSuggestionPrivate &)
Definition qqmlsa.cpp:1971
GenericPassPrivate(GenericPass *iface, PassManager *manager)
Definition qqmlsa.cpp:1244
MethodPrivate(Method *, const MethodPrivate &)
Definition qqmlsa.cpp:564
QQmlSA::SourceLocation sourceLocation() const
Definition qqmlsa.cpp:574
MethodType methodType() const
Definition qqmlsa.cpp:579
QString methodName() const
Definition qqmlsa.cpp:569
MethodsPrivate(QQmlSA::Method::Methods *, MethodsPrivate &&)
Definition qqmlsa.cpp:557
QMultiHash< QString, Method >::const_iterator constEnd() const
Definition qqmlsa.cpp:545
MethodsPrivate(QQmlSA::Method::Methods *, const MethodsPrivate &)
Definition qqmlsa.cpp:552
QMultiHash< QString, Method >::const_iterator constBegin() const
Definition qqmlsa.cpp:526
\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:2356
@ Register
Definition qqmlsa.cpp:1463
static QQmlJS::ChildScopesIterator childScopesEnd(const Element &element)
Definition qqmlsa.cpp:1624
static QQmlJS::ChildScopesIterator childScopesBegin(const Element &element)
Definition qqmlsa.cpp:1619
bool isRegularBindingType(BindingType type)
Definition qqmlsa.cpp:2370
static QString lookupName(const QQmlSA::Element &element, LookupMode mode=Lookup)
Definition qqmlsa.cpp:1464
Combined button and popup list for selecting options.