30 case QmlIR::Binding::Type_Invalid:
32 case QmlIR::Binding::Type_Boolean:
33 return u"a boolean"_s;
34 case QmlIR::Binding::Type_Number:
36 case QmlIR::Binding::Type_String:
38 case QmlIR::Binding::Type_Null:
40 case QmlIR::Binding::Type_Translation:
41 return u"a translation"_s;
42 case QmlIR::Binding::Type_TranslationById:
43 return u"a translation by id"_s;
44 case QmlIR::Binding::Type_Script:
46 case QmlIR::Binding::Type_Object:
47 return u"an object"_s;
48 case QmlIR::Binding::Type_AttachedProperty:
49 return u"an attached property"_s;
50 case QmlIR::Binding::Type_GroupProperty:
51 return u"a grouped property"_s;
144QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run(
145 const QV4::Compiler::Context *context,
const QString &propertyName,
146 QQmlJS::AST::Node *astNode,
const QmlIR::Binding &irBinding)
148 QQmlJS::SourceLocation bindingLocation;
149 bindingLocation.startLine = irBinding.location.line();
150 bindingLocation.startColumn = irBinding.location.column();
152 QQmlJSCompilePass::Function function;
153 function.qmlScope = m_typeResolver->registerContentPool()->createType(
154 m_scopeType, QQmlJSRegisterContent::InvalidLookupIndex,
155 QQmlJSRegisterContent::ScopeObject);
159 const auto setIsSignalHandler = [&]() {
160 function.isSignalHandler =
true;
164 m_logger->setCompileErrorSeverity(context->returnsClosure
165 ? QQmlJS::WarningSeverity::Info
166 : QQmlJS::WarningSeverity::Warning);
169 if (irBinding.type() != QmlIR::Binding::Type_Script) {
170 diagnose(u"Binding is not a script binding, but %1."_s.arg(
171 bindingTypeDescription(QmlIR::Binding::Type(quint32(irBinding.type())))),
172 bindingLocation, m_logger);
175 function.isProperty = m_objectType->hasProperty(propertyName);
176 if (function.isProperty) {
177 const auto property = m_objectType->property(propertyName);
178 if (
const QQmlJSScope::ConstPtr propertyType = property.type()) {
179 function.returnType = m_typeResolver->namedType(propertyType->isListProperty()
180 ? m_typeResolver->qObjectListType()
181 : QQmlJSScope::ConstPtr(property.type()));
183 diagnose(u"Cannot resolve property type %1 for binding on %2."_s
184 .arg(property.typeName(), propertyName),
185 bindingLocation, m_logger);
188 if (!property.bindable().isEmpty() && !property.isPrivate())
189 function.isQPropertyBinding =
true;
190 }
else if (QQmlSignalNames::isHandlerName(propertyName)) {
191 if (
auto actualPropertyName =
192 QQmlSignalNames::changedHandlerNameToPropertyName(propertyName);
193 actualPropertyName && m_objectType->hasProperty(*actualPropertyName)) {
194 setIsSignalHandler();
196 auto signalName = QQmlSignalNames::handlerNameToSignalName(propertyName);
197 const auto methods = m_objectType->methods(*signalName);
198 for (
const auto &method : methods) {
199 if (method.isCloned())
201 if (method.methodType() == QQmlJSMetaMethodType::Signal) {
202 setIsSignalHandler();
203 const auto arguments = method.parameters();
204 for (qsizetype i = 0, end = arguments.size(); i < end; ++i) {
205 const auto &type = arguments[i].type();
207 diagnose(u"Cannot resolve the argument type %1."_s.arg(
208 arguments[i].typeName()),
209 bindingLocation, m_logger);
210 function.argumentTypes.append(
211 m_typeResolver->namedType(m_typeResolver->varType()));
213 function.argumentTypes.append(m_typeResolver->namedType(type));
219 if (!function.isSignalHandler) {
220 diagnose(u"Could not find signal \"%1\"."_s.arg(*signalName),
221 bindingLocation, m_logger);
225 QString message = u"Could not find property \"%1\"."_s.arg(propertyName);
226 if (m_objectType->isNameDeferred(propertyName)) {
230 message += u" You may want use ID-based grouped properties here.";
233 diagnose(message, bindingLocation, m_logger);
236 QQmlJS::MemoryPool pool;
237 auto ast = astNode->asFunctionDefinition();
239 QQmlJS::AST::Statement *stmt = astNode->statementCast();
241 Q_ASSERT(astNode->expressionCast());
242 QQmlJS::AST::ExpressionNode *expr = astNode->expressionCast();
243 stmt =
new (&pool) QQmlJS::AST::ExpressionStatement(expr);
245 auto body =
new (&pool) QQmlJS::AST::StatementList(stmt);
246 body = body->finish();
248 QString name = u"binding for "_s;
249 ast =
new (&pool) QQmlJS::AST::FunctionDeclaration(
250 pool.newString(std::move(name)),
nullptr, body);
251 ast->lbraceToken = astNode->firstSourceLocation();
252 ast->functionToken = ast->lbraceToken;
253 ast->rbraceToken = astNode->lastSourceLocation();
256 populateSignature(context, ast, &function);