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->setCompileErrorLevel(context->returnsClosure ? QtDebugMsg : QtWarningMsg);
167 if (irBinding.type() != QmlIR::Binding::Type_Script) {
168 diagnose(u"Binding is not a script binding, but %1."_s.arg(
169 bindingTypeDescription(QmlIR::Binding::Type(quint32(irBinding.type())))),
170 bindingLocation, m_logger);
173 function.isProperty = m_objectType->hasProperty(propertyName);
174 if (function.isProperty) {
175 const auto property = m_objectType->property(propertyName);
176 if (
const QQmlJSScope::ConstPtr propertyType = property.type()) {
177 function.returnType = m_typeResolver->namedType(propertyType->isListProperty()
178 ? m_typeResolver->qObjectListType()
179 : QQmlJSScope::ConstPtr(property.type()));
181 diagnose(u"Cannot resolve property type %1 for binding on %2."_s
182 .arg(property.typeName(), propertyName),
183 bindingLocation, m_logger);
186 if (!property.bindable().isEmpty() && !property.isPrivate())
187 function.isQPropertyBinding =
true;
188 }
else if (QQmlSignalNames::isHandlerName(propertyName)) {
189 if (
auto actualPropertyName =
190 QQmlSignalNames::changedHandlerNameToPropertyName(propertyName);
191 actualPropertyName && m_objectType->hasProperty(*actualPropertyName)) {
192 setIsSignalHandler();
194 auto signalName = QQmlSignalNames::handlerNameToSignalName(propertyName);
195 const auto methods = m_objectType->methods(*signalName);
196 for (
const auto &method : methods) {
197 if (method.isCloned())
199 if (method.methodType() == QQmlJSMetaMethodType::Signal) {
200 setIsSignalHandler();
201 const auto arguments = method.parameters();
202 for (qsizetype i = 0, end = arguments.size(); i < end; ++i) {
203 const auto &type = arguments[i].type();
205 diagnose(u"Cannot resolve the argument type %1."_s.arg(
206 arguments[i].typeName()),
207 bindingLocation, m_logger);
208 function.argumentTypes.append(
209 m_typeResolver->namedType(m_typeResolver->varType()));
211 function.argumentTypes.append(m_typeResolver->namedType(type));
217 if (!function.isSignalHandler) {
218 diagnose(u"Could not find signal \"%1\"."_s.arg(*signalName),
219 bindingLocation, m_logger);
223 QString message = u"Could not find property \"%1\"."_s.arg(propertyName);
224 if (m_objectType->isNameDeferred(propertyName)) {
228 message += u" You may want use ID-based grouped properties here.";
231 diagnose(message, bindingLocation, m_logger);
234 QQmlJS::MemoryPool pool;
235 auto ast = astNode->asFunctionDefinition();
237 QQmlJS::AST::Statement *stmt = astNode->statementCast();
239 Q_ASSERT(astNode->expressionCast());
240 QQmlJS::AST::ExpressionNode *expr = astNode->expressionCast();
241 stmt =
new (&pool) QQmlJS::AST::ExpressionStatement(expr);
243 auto body =
new (&pool) QQmlJS::AST::StatementList(stmt);
244 body = body->finish();
246 QString name = u"binding for "_s;
247 ast =
new (&pool) QQmlJS::AST::FunctionDeclaration(
248 pool.newString(std::move(name)),
nullptr, body);
249 ast->lbraceToken = astNode->firstSourceLocation();
250 ast->functionToken = ast->lbraceToken;
251 ast->rbraceToken = astNode->lastSourceLocation();
254 populateSignature(context, ast, &function);