Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmljsliteralbindingcheck.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
5
6#include <private/qqmljsimportvisitor_p.h>
7#include <private/qqmljstyperesolver_p.h>
8#include <private/qqmljsmetatypes_p.h>
9#include <private/qqmlsa_p.h>
10#include <private/qqmlsasourcelocation_p.h>
11#include <private/qqmlstringconverters_p.h>
12
14
15using namespace Qt::StringLiterals;
16
17// This makes no sense, but we want to warn about things QQmlPropertyResolver complains about.
19 const QQmlSA::Element &fromElement,
20 const QQmlSA::Element &toElement)
21{
22 Q_ASSERT(resolver);
23 auto from = QQmlJSScope::scope(fromElement);
24 auto to = QQmlJSScope::scope(toElement);
25 if (resolver->equals(from, to))
26 return true;
27
28 if (!resolver->canConvertFromTo(from, to))
29 return false;
30
31 const bool fromIsString = resolver->equals(from, resolver->stringType());
32
33 if (resolver->equals(to, resolver->stringType())
34 || resolver->equals(to, resolver->stringListType())
35 || resolver->equals(to, resolver->byteArrayType())
36 || resolver->equals(to, resolver->urlType())) {
37 return fromIsString;
38 }
39
40 if (resolver->isNumeric(to))
41 return resolver->isNumeric(from);
42
43 if (resolver->equals(to, resolver->boolType()))
44 return resolver->equals(from, resolver->boolType());
45
46 return true;
47}
48
50 : LiteralBindingCheckBase(passManager),
51 m_resolver(QQmlSA::PassManagerPrivate::resolver(*passManager))
52{
53}
54
60
62{
63 switch (type) {
65 return u"bool"_s;
67 return u"double"_s;
69 return u"string"_s;
71 return u"regexp"_s;
73 return u"null"_s;
74 default:
75 return QString();
76 }
77 Q_UNREACHABLE_RETURN(QString());
78}
79
81 const QQmlSA::Binding &binding,
82 const QQmlSA::Element &bindingScope) const
83{
85 return {};
86
87 const QString unqualifiedPropertyName = [&propertyName]() -> QString {
88 if (auto idx = propertyName.lastIndexOf(u'.'); idx != -1 && idx != propertyName.size() - 1)
89 return propertyName.sliced(idx + 1);
90 return propertyName;
91 }();
92
93 return bindingScope.property(unqualifiedPropertyName);
94}
95
96
97void LiteralBindingCheckBase::onBinding(const QQmlSA::Element &element, const QString &propertyName,
98 const QQmlSA::Binding &binding,
99 const QQmlSA::Element &bindingScope,
100 const QQmlSA::Element &value)
101{
103
104 const auto property = getProperty(propertyName, binding, bindingScope);
105 if (!property.isValid())
106 return;
107
108 // If the property is defined in the same scope where it is set,
109 // we are in fact allowed to set it, even if it's not writable.
110 if (property.isReadonly() && !element.hasOwnProperty(propertyName)) {
111 emitWarning(u"Cannot assign to read-only property %1"_s.arg(propertyName),
113 return;
114 }
115 if (auto propertyType = property.type(); propertyType) {
116 auto construction = check(propertyType.internalId(), binding.stringValue());
117 if (construction.isValid()) {
118 const QString warningMessage =
119 u"Binding is not supported: Type %1 should be constructed using"
120 u" QML_STRUCTURED_VALUE's construction mechanism, instead of a "
121 u"string."_s.arg(propertyType.internalId());
122
123 if (!construction.code.isNull()) {
124 QQmlSA::FixSuggestion suggestion(
125 u"Replace string by structured value construction"_s,
126 binding.sourceLocation(), construction.code);
127 emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation(), suggestion);
128 return;
129 }
130 emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation());
131 return;
132 }
133 }
134
135}
136
138 const QString &propertyName,
139 const QQmlSA::Binding &binding,
140 const QQmlSA::Element &bindingScope,
141 const QQmlSA::Element &value)
142{
143 LiteralBindingCheckBase::onBinding(element, propertyName, binding, bindingScope, value);
144
145 const auto property = getProperty(propertyName, binding, bindingScope);
146 if (!property.isValid())
147 return;
148
149 if (!canConvertForLiteralBinding(m_resolver, resolveLiteralType(binding), property.type())) {
150 emitWarning(u"Cannot assign literal of type %1 to %2"_s.arg(
154 return;
155 }
156}
157
QQmlSA::Property getProperty(const QString &propertyName, const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope) const
virtual QQmlJSStructuredTypeError check(const QString &typeName, const QString &value) const =0
void onBinding(const QQmlSA::Element &element, const QString &propertyName, const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope, const QQmlSA::Element &value) override
Executes whenever a property gets bound to a value.
QQmlJSLiteralBindingCheck(QQmlSA::PassManager *manager)
QQmlJSStructuredTypeError check(const QString &typeName, const QString &value) const override
void onBinding(const QQmlSA::Element &element, const QString &propertyName, const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope, const QQmlSA::Element &value) override
Executes whenever a property gets bound to a value.
static const QQmlJSScope::ConstPtr & scope(const QQmlSA::Element &)
static QString prettyName(QAnyStringView name)
bool equals(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const
QQmlJSScope::ConstPtr stringType() const
bool isNumeric(const QQmlJSRegisterContent &type) const
QQmlJSScope::ConstPtr byteArrayType() const
QQmlJSScope::ConstPtr boolType() const
bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const
QQmlJSScope::ConstPtr stringListType() const
QQmlJSScope::ConstPtr urlType() const
static QQmlJSStructuredTypeError hasError(const QString &typeName, const QString &value)
\inmodule QtQmlCompiler
Definition qqmlsa.h:52
BindingType bindingType() const
Definition qqmlsa.cpp:165
static bool isLiteralBinding(BindingType)
Returns true if bindingType is a literal type, and false otherwise.
Definition qqmlsa.cpp:252
QString stringValue() const
Returns the associated string literal if the content type of this binding is StringLiteral,...
Definition qqmlsa.cpp:174
QQmlSA::SourceLocation sourceLocation() const
Returns the location in the QML code where this binding is defined.
Definition qqmlsa.cpp:199
\inmodule QtQmlCompiler
Definition qqmlsa.h:193
Property property(const QString &propertyName) const
Returns the property with the name propertyName if it is found in this Element or its base and extens...
Definition qqmlsa.cpp:671
bool hasOwnProperty(const QString &propertyName) const
Returns whether this Element defines a property with the name propertyName which is not defined on it...
Definition qqmlsa.cpp:662
\inmodule QtQmlCompiler
Definition qqmlsa.h:386
void emitWarning(QAnyStringView diagnostic, LoggerWarningId id)
Emits a warning message diagnostic about an issue of type id.
Definition qqmlsa.cpp:881
Element resolveLiteralType(const Binding &binding)
Returns the element representing the type of literal in binding.
Definition qqmlsa.cpp:993
\inmodule QtQmlCompiler
Definition qqmlsa.h:303
\inmodule QtQmlCompiler
Definition qqmlsa.h:160
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
QString sliced(qsizetype pos) const &
Definition qstring.h:394
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
\inmodule QtQmlCompiler
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * typeName
GLenum type
static bool canConvertForLiteralBinding(QQmlJSTypeResolver *resolver, const QQmlSA::Element &fromElement, const QQmlSA::Element &toElement)
static QString literalPrettyTypeName(QQmlSA::BindingType type)
const QQmlSA::LoggerWarningId qmlReadOnlyProperty
const QQmlSA::LoggerWarningId qmlIncompatibleType
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
const char property[13]
Definition qwizard.cpp:101