Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:significant
4
5
#
include
"qqmljsliteralbindingcheck_p.h"
6
7
#
include
"qqmlsa.h"
8
9
#
include
<
private
/
qqmljsimportvisitor_p
.
h
>
10
#
include
<
private
/
qqmljstyperesolver_p
.
h
>
11
#
include
<
private
/
qqmljsmetatypes_p
.
h
>
12
#
include
<
private
/
qqmlsa_p
.
h
>
13
#
include
<
private
/
qqmlsasourcelocation_p
.
h
>
14
#
include
<
private
/
qqmlstringconverters_p
.
h
>
15
16
QT_BEGIN_NAMESPACE
17
18
using
namespace
Qt::StringLiterals;
19
20
// This makes no sense, but we want to warn about things QQmlPropertyResolver complains about.
21
static
bool
canConvertForLiteralBinding
(QQmlJSTypeResolver *resolver,
22
const
QQmlSA
::Element &fromElement,
23
const
QQmlSA
::Element &toElement)
24
{
25
Q_ASSERT(resolver);
26
auto
from = QQmlJSScope::scope(fromElement);
27
auto
to = QQmlJSScope::scope(toElement);
28
if
(from == to)
29
return
true
;
30
31
if
(!resolver->canConvertFromTo(from, to))
32
return
false
;
33
34
const
bool
fromIsString = from == resolver->stringType();
35
36
if
(to == resolver->stringType()
37
|| to == resolver->stringListType()
38
|| to == resolver->byteArrayType()
39
|| to == resolver->urlType()) {
40
return
fromIsString;
41
}
42
43
if
(resolver->isNumeric(to))
44
return
resolver->isNumeric(from);
45
46
if
(to == resolver->boolType())
47
return
from == resolver->boolType();
48
49
return
true
;
50
}
51
52
QQmlJSLiteralBindingCheck
::QQmlJSLiteralBindingCheck(
QQmlSA
::PassManager *passManager)
53
:
LiteralBindingCheckBase
(passManager),
54
m_resolver(QQmlSA::PassManagerPrivate::resolver(*passManager))
55
{
56
}
57
58
QQmlJSStructuredTypeError
QQmlJSLiteralBindingCheck
::
check
(
const
QString &typeName,
59
const
QString &value)
const
60
{
61
return
QQmlJSValueTypeFromStringCheck::hasError(typeName, value);
62
}
63
64
static
QString
literalPrettyTypeName
(QQmlSA::BindingType type)
65
{
66
switch
(type) {
67
case
QQmlSA::BindingType::BoolLiteral:
68
return
u"bool"_s;
69
case
QQmlSA::BindingType::NumberLiteral:
70
return
u"double"_s;
71
case
QQmlSA::BindingType::StringLiteral:
72
return
u"string"_s;
73
case
QQmlSA::BindingType::RegExpLiteral:
74
return
u"regexp"_s;
75
case
QQmlSA::BindingType::Null:
76
return
u"null"_s;
77
default
:
78
return
QString();
79
}
80
Q_UNREACHABLE_RETURN(QString());
81
}
82
83
QQmlSA::Property
LiteralBindingCheckBase
::getProperty(
const
QString &propertyName,
84
const
QQmlSA::Binding &binding,
85
const
QQmlSA
::Element &bindingScope)
const
86
{
87
if
(!QQmlSA::Binding::isLiteralBinding(binding.bindingType()))
88
return
{};
89
90
const
QString unqualifiedPropertyName = [&propertyName]() -> QString {
91
if
(
auto
idx = propertyName.lastIndexOf(u'.'); idx != -1 && idx != propertyName.size() - 1)
92
return
propertyName.sliced(idx + 1);
93
return
propertyName;
94
}();
95
96
return
bindingScope.property(unqualifiedPropertyName);
97
}
98
99
void
LiteralBindingCheckBase
::warnOnCheckedBinding(
100
const
QQmlSA::Binding &binding,
const
QQmlSA
::Element &propertyType)
101
{
102
auto
construction = check(propertyType.internalId(), binding.stringValue());
103
if
(!construction.isValid())
104
return
;
105
106
const
QString warningMessage =
107
u"Construction from string is deprecated. Use structured value type "
108
u"construction instead for type \"%1\""_s.arg(propertyType.internalId());
109
110
if
(construction.code.isEmpty()) {
111
emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation());
112
return
;
113
}
114
115
const
QQmlSA
::FixSuggestion suggestion(
116
u"Replace string by structured value construction"_s,
117
binding.sourceLocation(),
118
{ binding.bindingScope().filePath(), binding.sourceLocation(), construction.code });
119
emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation(), suggestion);
120
}
121
122
void
QQmlJSLiteralBindingCheck
::onBinding(
const
QQmlSA
::Element &element,
123
const
QString &propertyName,
124
const
QQmlSA::Binding &binding,
125
const
QQmlSA
::Element &bindingScope,
126
const
QQmlSA
::Element &value)
127
{
128
Q_UNUSED(value);
129
130
const
auto
property = getProperty(propertyName, binding, bindingScope);
131
if
(!property.isValid())
132
return
;
133
134
// If the property is defined in the same scope where it is set,
135
// we are in fact allowed to set it, even if it's not writable.
136
if
(property.isReadonly() && !element.hasOwnProperty(propertyName)) {
137
emitWarning(u"Cannot assign to read-only property %1"_s.arg(propertyName),
138
qmlReadOnlyProperty, binding.sourceLocation());
139
return
;
140
}
141
142
if
(
const
auto
propertyType = property.type())
143
warnOnCheckedBinding(binding, propertyType);
144
145
if
(!canConvertForLiteralBinding(m_resolver, resolveLiteralType(binding), property.type())) {
146
emitWarning(u"Cannot assign literal of type %1 to %2"_s.arg(
147
literalPrettyTypeName(binding.bindingType()),
148
QQmlJSScope::prettyName(property.typeName())),
149
qmlIncompatibleType, binding.sourceLocation());
150
return
;
151
}
152
}
153
154
QT_END_NAMESPACE
LiteralBindingCheckBase
Definition
qqmljsliteralbindingcheck_p.h:29
QQmlJSLiteralBindingCheck
Definition
qqmljsliteralbindingcheck_p.h:43
QQmlJSLiteralBindingCheck::check
QQmlJSStructuredTypeError check(const QString &typeName, const QString &value) const override
Definition
qqmljsliteralbindingcheck.cpp:58
QQmlSA
\inmodule QtQmlCompiler
Definition
qqmljsscope_p.h:715
canConvertForLiteralBinding
static bool canConvertForLiteralBinding(QQmlJSTypeResolver *resolver, const QQmlSA::Element &fromElement, const QQmlSA::Element &toElement)
Definition
qqmljsliteralbindingcheck.cpp:21
literalPrettyTypeName
static QString literalPrettyTypeName(QQmlSA::BindingType type)
Definition
qqmljsliteralbindingcheck.cpp:64
qtdeclarative
src
qmllint
qqmljsliteralbindingcheck.cpp
Generated on
for Qt by
1.18.0