@@ -19,16 +19,21 @@ class SwiftOptions {
1919 /// Creates a [SwiftOptions] object
2020 const SwiftOptions ({
2121 this .copyrightHeader,
22+ this .errorClassName,
2223 });
2324
2425 /// A copyright header that will get prepended to generated code.
2526 final Iterable <String >? copyrightHeader;
2627
28+ /// The name of the error class used for passing custom error parameters.
29+ final String ? errorClassName;
30+
2731 /// Creates a [SwiftOptions] from a Map representation where:
2832 /// `x = SwiftOptions.fromList(x.toMap())` .
2933 static SwiftOptions fromList (Map <String , Object > map) {
3034 return SwiftOptions (
3135 copyrightHeader: map['copyrightHeader' ] as Iterable <String >? ,
36+ errorClassName: map['errorClassName' ] as String ? ,
3237 );
3338 }
3439
@@ -37,6 +42,7 @@ class SwiftOptions {
3742 Map <String , Object > toMap () {
3843 final Map <String , Object > result = < String , Object > {
3944 if (copyrightHeader != null ) 'copyrightHeader' : copyrightHeader! ,
45+ if (errorClassName != null ) 'errorClassName' : errorClassName! ,
4046 };
4147 return result;
4248 }
@@ -316,7 +322,7 @@ class SwiftGenerator extends StructuredGenerator<SwiftOptions> {
316322 name: func.name,
317323 parameters: func.parameters,
318324 returnType: func.returnType,
319- errorTypeName: 'FlutterError' ,
325+ errorTypeName: _getErrorClassName (generatorOptions) ,
320326 isAsynchronous: true ,
321327 swiftFunction: func.swiftFunction,
322328 getParameterName: _getSafeArgumentName,
@@ -350,6 +356,7 @@ class SwiftGenerator extends StructuredGenerator<SwiftOptions> {
350356 indent, func.documentationComments, _docCommentSpec);
351357 _writeFlutterMethod (
352358 indent,
359+ generatorOptions: generatorOptions,
353360 name: func.name,
354361 channelName: makeChannelName (api, func, dartPackageName),
355362 parameters: func.parameters,
@@ -614,10 +621,20 @@ class SwiftGenerator extends StructuredGenerator<SwiftOptions> {
614621 });
615622 }
616623
617- void _writeWrapError (Indent indent) {
624+ void _writeWrapError (SwiftOptions generatorOptions, Indent indent) {
618625 indent.newln ();
619626 indent.write ('private func wrapError(_ error: Any) -> [Any?] ' );
620627 indent.addScoped ('{' , '}' , () {
628+ indent.write (
629+ 'if let pigeonError = error as? ${_getErrorClassName (generatorOptions )} ' );
630+ indent.addScoped ('{' , '}' , () {
631+ indent.write ('return ' );
632+ indent.addScoped ('[' , ']' , () {
633+ indent.writeln ('pigeonError.code,' );
634+ indent.writeln ('pigeonError.message,' );
635+ indent.writeln ('pigeonError.details,' );
636+ });
637+ });
621638 indent.write ('if let flutterError = error as? FlutterError ' );
622639 indent.addScoped ('{' , '}' , () {
623640 indent.write ('return ' );
@@ -645,13 +662,14 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
645662}''' );
646663 }
647664
648- void _writeCreateConnectionError (Indent indent) {
665+ void _writeCreateConnectionError (
666+ SwiftOptions generatorOptions, Indent indent) {
649667 indent.newln ();
650668 indent.writeScoped (
651- 'private func createConnectionError(withChannelName channelName: String) -> FlutterError {' ,
669+ 'private func createConnectionError(withChannelName channelName: String) -> ${ _getErrorClassName ( generatorOptions )} {' ,
652670 '}' , () {
653671 indent.writeln (
654- 'return FlutterError (code: "channel-error", message: "Unable to establish connection on channel: \'\\ (channelName)\' .", details: "")' );
672+ 'return ${ _getErrorClassName ( generatorOptions )} (code: "channel-error", message: "Unable to establish connection on channel: \'\\ (channelName)\' .", details: "")' );
655673 });
656674 }
657675
@@ -669,19 +687,23 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
669687 .whereType <AstFlutterApi >()
670688 .any ((Api api) => api.methods.isNotEmpty);
671689
690+ _writePigeonError (generatorOptions, indent);
691+
672692 if (hasHostApi) {
673693 _writeWrapResult (indent);
674- _writeWrapError (indent);
694+ _writeWrapError (generatorOptions, indent);
675695 }
676696 if (hasFlutterApi) {
677- _writeCreateConnectionError (indent);
697+ _writeCreateConnectionError (generatorOptions, indent);
678698 }
699+
679700 _writeIsNullish (indent);
680701 _writeNilOrValue (indent);
681702 }
682703
683704 void _writeFlutterMethod (
684705 Indent indent, {
706+ required SwiftOptions generatorOptions,
685707 required String name,
686708 required String channelName,
687709 required List <Parameter > parameters,
@@ -693,7 +715,7 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
693715 name: name,
694716 parameters: parameters,
695717 returnType: returnType,
696- errorTypeName: 'FlutterError' ,
718+ errorTypeName: _getErrorClassName (generatorOptions) ,
697719 isAsynchronous: true ,
698720 swiftFunction: swiftFunction,
699721 getParameterName: _getSafeArgumentName,
@@ -735,12 +757,12 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
735757 indent.writeln ('let message: String? = nilOrValue(listResponse[1])' );
736758 indent.writeln ('let details: String? = nilOrValue(listResponse[2])' );
737759 indent.writeln (
738- 'completion(.failure(FlutterError (code: code, message: message, details: details)))' );
760+ 'completion(.failure(${ _getErrorClassName ( generatorOptions )} (code: code, message: message, details: details)))' );
739761 }, addTrailingNewline: false );
740762 if (! returnType.isNullable && ! returnType.isVoid) {
741763 indent.addScoped ('else if listResponse[0] == nil {' , '} ' , () {
742764 indent.writeln (
743- 'completion(.failure(FlutterError (code: "null-error", message: "Flutter api returned null value for non-null return value.", details: "")))' );
765+ 'completion(.failure(${ _getErrorClassName ( generatorOptions )} (code: "null-error", message: "Flutter api returned null value for non-null return value.", details: "")))' );
744766 }, addTrailingNewline: false );
745767 }
746768 indent.addScoped ('else {' , '}' , () {
@@ -870,11 +892,41 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
870892 indent.writeln ('$varChannelName .setMessageHandler(nil)' );
871893 });
872894 }
895+
896+ void _writePigeonError (SwiftOptions generatorOptions, Indent indent) {
897+ indent.newln ();
898+ indent.writeln (
899+ '/// Error class for passing custom error details to Dart side.' );
900+ indent.writeScoped (
901+ 'final class ${_getErrorClassName (generatorOptions )}: Error {' , '}' ,
902+ () {
903+ indent.writeln ('let code: String' );
904+ indent.writeln ('let message: String?' );
905+ indent.writeln ('let details: Any?' );
906+ indent.newln ();
907+ indent.writeScoped (
908+ 'init(code: String, message: String?, details: Any?) {' , '}' , () {
909+ indent.writeln ('self.code = code' );
910+ indent.writeln ('self.message = message' );
911+ indent.writeln ('self.details = details' );
912+ });
913+ indent.newln ();
914+ indent.writeScoped ('var localizedDescription: String {' , '}' , () {
915+ indent.writeScoped ('return' , '' , () {
916+ indent.writeln (
917+ '"${_getErrorClassName (generatorOptions )}(code: \\ (code), message: \\ (message ?? "<nil>"), details: \\ (details ?? "<nil>")"' );
918+ }, addTrailingNewline: false );
919+ });
920+ });
921+ }
873922}
874923
875924/// Calculates the name of the codec that will be generated for [api] .
876925String _getCodecName (Api api) => '${api .name }Codec' ;
877926
927+ String _getErrorClassName (SwiftOptions generatorOptions) =>
928+ generatorOptions.errorClassName ?? 'PigeonError' ;
929+
878930String _getArgumentName (int count, NamedType argument) =>
879931 argument.name.isEmpty ? 'arg$count ' : argument.name;
880932
0 commit comments