writeFlutterApi method
void
writeFlutterApi(
- GObjectOptions generatorOptions,
- Root root,
- Indent indent,
- Api api, {
- required String dartPackageName,
override
Writes a single Flutter Api to indent
.
Implementation
@override
void writeFlutterApi(
GObjectOptions generatorOptions,
Root root,
Indent indent,
Api api, {
required String dartPackageName,
}) {
final String module = _getModule(generatorOptions, dartPackageName);
final String className = _getClassName(module, api.name);
final String methodPrefix = _getMethodPrefix(module, api.name);
final String codecClassName = _getClassName(module, _codecBaseName);
final String codecMethodPrefix = _getMethodPrefix(module, _codecBaseName);
indent.newln();
_writeObjectStruct(indent, module, api.name, () {
indent.writeln('FlBinaryMessenger* messenger;');
indent.writeln('gchar *suffix;');
});
indent.newln();
_writeDefineType(indent, module, api.name);
indent.newln();
_writeDispose(indent, module, api.name, () {
_writeCastSelf(indent, module, api.name, 'object');
indent.writeln('g_clear_object(&self->messenger);');
indent.writeln('g_clear_pointer(&self->suffix, g_free);');
});
indent.newln();
_writeInit(indent, module, api.name, () {});
indent.newln();
_writeClassInit(indent, module, api.name, () {});
indent.newln();
indent.writeScoped(
'$className* ${methodPrefix}_new(FlBinaryMessenger* messenger, const gchar* suffix) {',
'}', () {
_writeObjectNew(indent, module, api.name);
indent.writeln(
'self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));');
indent.writeln(
'self->suffix = suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup("");');
indent.writeln('return self;');
});
for (final Method method in api.methods) {
final String methodName = _getMethodName(method.name);
final String responseName = _getResponseName(api.name, method.name);
final String responseClassName = _getClassName(module, responseName);
final String responseMethodPrefix =
_getMethodPrefix(module, responseName);
final String testResponseMacro =
'${_snakeCaseFromCamelCase(module)}_IS_${_snakeCaseFromCamelCase(responseName)}'
.toUpperCase();
indent.newln();
_writeObjectStruct(indent, module, responseName, () {
indent.writeln('FlValue* error;');
if (!method.returnType.isVoid) {
indent.writeln('FlValue* return_value;');
if (_isNullablePrimitiveType(method.returnType)) {
final String primitiveType =
_getType(module, method.returnType, primitive: true);
indent.writeln('$primitiveType return_value_;');
}
}
});
indent.newln();
_writeDefineType(indent, module, responseName);
indent.newln();
_writeDispose(indent, module, responseName, () {
_writeCastSelf(indent, module, responseName, 'object');
indent.writeln('g_clear_pointer(&self->error, fl_value_unref);');
if (!method.returnType.isVoid) {
indent
.writeln('g_clear_pointer(&self->return_value, fl_value_unref);');
}
});
indent.newln();
_writeInit(indent, module, responseName, () {});
indent.newln();
_writeClassInit(indent, module, responseName, () {});
indent.newln();
indent.writeScoped(
'static $responseClassName* ${responseMethodPrefix}_new(FlValue* response) {',
'}', () {
_writeObjectNew(indent, module, responseName);
indent.writeScoped('if (fl_value_get_length(response) > 1) {', '}', () {
indent.writeln('self->error = fl_value_ref(response);');
});
if (!method.returnType.isVoid) {
indent.writeScoped('else {', '}', () {
indent.writeln(
'FlValue* value = fl_value_get_list_value(response, 0);');
indent.writeln('self->return_value = fl_value_ref(value);');
});
}
indent.writeln('return self;');
});
indent.newln();
indent.writeScoped(
'gboolean ${responseMethodPrefix}_is_error($responseClassName* self) {',
'}', () {
indent
.writeln('g_return_val_if_fail($testResponseMacro(self), FALSE);');
indent.writeln('return self->error != nullptr;');
});
indent.newln();
indent.writeScoped(
'const gchar* ${responseMethodPrefix}_get_error_code($responseClassName* self) {',
'}', () {
indent.writeln(
'g_return_val_if_fail($testResponseMacro(self), nullptr);');
indent.writeln('g_assert(${responseMethodPrefix}_is_error(self));');
indent.writeln(
'return fl_value_get_string(fl_value_get_list_value(self->error, 0));');
});
indent.newln();
indent.writeScoped(
'const gchar* ${responseMethodPrefix}_get_error_message($responseClassName* self) {',
'}', () {
indent.writeln(
'g_return_val_if_fail($testResponseMacro(self), nullptr);');
indent.writeln('g_assert(${responseMethodPrefix}_is_error(self));');
indent.writeln(
'return fl_value_get_string(fl_value_get_list_value(self->error, 1));');
});
indent.newln();
indent.writeScoped(
'FlValue* ${responseMethodPrefix}_get_error_details($responseClassName* self) {',
'}', () {
indent.writeln(
'g_return_val_if_fail($testResponseMacro(self), nullptr);');
indent.writeln('g_assert(${responseMethodPrefix}_is_error(self));');
indent.writeln('return fl_value_get_list_value(self->error, 2);');
});
if (!method.returnType.isVoid) {
final String primitiveType =
_getType(module, method.returnType, primitive: true);
indent.newln();
final String returnType = _isNullablePrimitiveType(method.returnType)
? '$primitiveType*'
: primitiveType;
indent.writeScoped(
'$returnType ${responseMethodPrefix}_get_return_value($responseClassName* self${_isNumericListType(method.returnType) ? ', size_t* return_value_length' : ''}) {',
'}', () {
indent.writeln(
'g_return_val_if_fail($testResponseMacro(self), ${_getDefaultValue(module, method.returnType)});');
indent.writeln('g_assert(!${responseMethodPrefix}_is_error(self));');
if (method.returnType.isNullable) {
indent.writeScoped(
'if (fl_value_get_type(self->return_value) == FL_VALUE_TYPE_NULL) {',
'}', () {
indent.writeln('return nullptr;');
});
}
if (_isNumericListType(method.returnType)) {
indent.writeScoped('if (return_value_length != nullptr) {', '}',
() {
indent.writeln(
'*return_value_length = fl_value_get_length(self->return_value);');
});
}
if (_isNullablePrimitiveType(method.returnType)) {
indent.writeln(
'self->return_value_ = ${_fromFlValue(module, method.returnType, 'self->return_value')};');
indent.writeln('return &self->return_value_;');
} else {
indent.writeln(
'return ${_fromFlValue(module, method.returnType, 'self->return_value')};');
}
});
}
indent.newln();
indent.writeScoped(
'static void ${methodPrefix}_${methodName}_cb(GObject* object, GAsyncResult* result, gpointer user_data) {',
'}', () {
indent.writeln('GTask* task = G_TASK(user_data);');
indent.writeln('g_task_return_pointer(task, result, g_object_unref);');
});
final List<String> asyncArgs = <String>['$className* self'];
for (final Parameter param in method.parameters) {
final String name = _snakeCaseFromCamelCase(param.name);
asyncArgs.add('${_getType(module, param.type)} $name');
if (_isNumericListType(param.type)) {
asyncArgs.add('size_t ${name}_length');
}
}
asyncArgs.addAll(<String>[
'GCancellable* cancellable',
'GAsyncReadyCallback callback',
'gpointer user_data',
]);
indent.newln();
indent.writeScoped(
"void ${methodPrefix}_$methodName(${asyncArgs.join(', ')}) {", '}',
() {
indent.writeln('g_autoptr(FlValue) args = fl_value_new_list();');
for (final Parameter param in method.parameters) {
final String name = _snakeCaseFromCamelCase(param.name);
final String value = _makeFlValue(root, module, param.type, name,
lengthVariableName: '${name}_length');
indent.writeln('fl_value_append_take(args, $value);');
}
final String channelName =
makeChannelName(api, method, dartPackageName);
indent.writeln(
'g_autofree gchar* channel_name = g_strdup_printf("$channelName%s", self->suffix);');
indent.writeln(
'g_autoptr($codecClassName) codec = ${codecMethodPrefix}_new();');
indent.writeln(
'FlBasicMessageChannel* channel = fl_basic_message_channel_new(self->messenger, channel_name, FL_MESSAGE_CODEC(codec));');
indent.writeln(
'GTask* task = g_task_new(self, cancellable, callback, user_data);');
indent.writeln('g_task_set_task_data(task, channel, g_object_unref);');
indent.writeln(
'fl_basic_message_channel_send(channel, args, cancellable, ${methodPrefix}_${methodName}_cb, task);');
});
final List<String> finishArgs = <String>[
'$className* self',
'GAsyncResult* result',
'GError** error',
];
indent.newln();
indent.writeScoped(
"$responseClassName* ${methodPrefix}_${methodName}_finish(${finishArgs.join(', ')}) {",
'}', () {
indent.writeln('g_autoptr(GTask) task = G_TASK(result);');
indent.writeln(
'GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));');
indent.writeln(
'FlBasicMessageChannel* channel = FL_BASIC_MESSAGE_CHANNEL(g_task_get_task_data(task));');
indent.writeln(
'g_autoptr(FlValue) response = fl_basic_message_channel_send_finish(channel, r, error);');
indent.writeScoped('if (response == nullptr) { ', '}', () {
indent.writeln('return nullptr;');
});
indent.writeln('return ${responseMethodPrefix}_new(response);');
});
}
}