@@ -132,7 +132,7 @@ class JavaGenerator extends StructuredGenerator<JavaOptions> {
132132 indent.writeln (
133133 '$_docCommentPrefix Generated class from Pigeon.$_docCommentSuffix ' );
134134 indent.writeln (
135- '@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})' );
135+ '@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial" })' );
136136 if (generatorOptions.useGeneratedAnnotation ?? false ) {
137137 indent.writeln ('@javax.annotation.Generated("dev.flutter.pigeon")' );
138138 }
@@ -606,46 +606,36 @@ class JavaGenerator extends StructuredGenerator<JavaOptions> {
606606 : _javaTypeForDartType (method.returnType);
607607 indent.writeln (
608608 'ArrayList<Object> wrapped = new ArrayList<Object>();' );
609- indent.write ('try ' );
610- indent.addScoped ('{' , '}' , () {
611- final List <String > methodArgument = < String > [];
612- if (method.arguments.isNotEmpty) {
613- indent.writeln (
614- 'ArrayList<Object> args = (ArrayList<Object>) message;' );
615- indent.writeln ('assert args != null;' );
616- enumerate (method.arguments, (int index, NamedType arg) {
617- // The StandardMessageCodec can give us [Integer, Long] for
618- // a Dart 'int'. To keep things simple we just use 64bit
619- // longs in Pigeon with Java.
620- final bool isInt = arg.type.baseName == 'int' ;
621- final String argType =
622- isInt ? 'Number' : _javaTypeForDartType (arg.type);
623- final String argName = _getSafeArgumentName (index, arg);
624- final String argExpression = isInt
625- ? '($argName == null) ? null : $argName .longValue()'
626- : argName;
627- String accessor = 'args.get($index )' ;
628- if (isEnum (root, arg.type)) {
629- accessor = _intToEnum (accessor, arg.type.baseName);
630- } else {
631- accessor = _cast (accessor, javaType: argType);
632- }
633- indent.writeln ('$argType $argName = $accessor ;' );
634- if (! arg.type.isNullable) {
635- indent.write ('if ($argName == null) ' );
636- indent.addScoped ('{' , '}' , () {
637- indent.writeln (
638- 'throw new NullPointerException("$argName unexpectedly null.");' );
639- });
640- }
641- methodArgument.add (argExpression);
642- });
643- }
644- if (method.isAsynchronous) {
645- final String resultValue =
646- method.returnType.isVoid ? 'null' : 'result' ;
647- const String resultName = 'resultCallback' ;
648- indent.format ('''
609+ final List <String > methodArgument = < String > [];
610+ if (method.arguments.isNotEmpty) {
611+ indent.writeln (
612+ 'ArrayList<Object> args = (ArrayList<Object>) message;' );
613+ enumerate (method.arguments, (int index, NamedType arg) {
614+ // The StandardMessageCodec can give us [Integer, Long] for
615+ // a Dart 'int'. To keep things simple we just use 64bit
616+ // longs in Pigeon with Java.
617+ final bool isInt = arg.type.baseName == 'int' ;
618+ final String argType =
619+ isInt ? 'Number' : _javaTypeForDartType (arg.type);
620+ final String argName = _getSafeArgumentName (index, arg);
621+ final String argExpression = isInt
622+ ? '($argName == null) ? null : $argName .longValue()'
623+ : argName;
624+ String accessor = 'args.get($index )' ;
625+ if (isEnum (root, arg.type)) {
626+ accessor = _intToEnum (accessor, arg.type.baseName);
627+ } else if (argType != 'Object' ) {
628+ accessor = _cast (accessor, javaType: argType);
629+ }
630+ indent.writeln ('$argType $argName = $accessor ;' );
631+ methodArgument.add (argExpression);
632+ });
633+ }
634+ if (method.isAsynchronous) {
635+ final String resultValue =
636+ method.returnType.isVoid ? 'null' : 'result' ;
637+ const String resultName = 'resultCallback' ;
638+ indent.format ('''
649639Result<$returnType > $resultName =
650640\t\t new Result<$returnType >() {
651641\t\t\t public void success($returnType result) {
@@ -659,31 +649,33 @@ Result<$returnType> $resultName =
659649\t\t\t }
660650\t\t };
661651''' );
662- methodArgument.add (resultName);
663- }
664- final String call =
665- 'api.${method .name }(${methodArgument .join (', ' )})' ;
666- if (method.isAsynchronous) {
667- indent.writeln ('$call ;' );
668- } else if (method.returnType.isVoid) {
669- indent.writeln ('$call ;' );
670- indent.writeln ('wrapped.add(0, null);' );
671- } else {
672- indent.writeln ('$returnType output = $call ;' );
673- indent.writeln ('wrapped.add(0, output);' );
674- }
675- }, addTrailingNewline: false );
676- indent.add (' catch (Error | RuntimeException exception) ' );
677- indent.addScoped ('{' , '}' , () {
678- indent.writeln (
679- 'ArrayList<Object> wrappedError = wrapError(exception);' );
680- if (method.isAsynchronous) {
681- indent.writeln ('reply.reply(wrappedError);' );
682- } else {
683- indent.writeln ('wrapped = wrappedError;' );
684- }
685- });
686- if (! method.isAsynchronous) {
652+ methodArgument.add (resultName);
653+ }
654+ final String call =
655+ 'api.${method .name }(${methodArgument .join (', ' )})' ;
656+ if (method.isAsynchronous) {
657+ indent.writeln ('$call ;' );
658+ } else {
659+ indent.write ('try ' );
660+ indent.addScoped ('{' , '}' , () {
661+ if (method.returnType.isVoid) {
662+ indent.writeln ('$call ;' );
663+ indent.writeln ('wrapped.add(0, null);' );
664+ } else {
665+ indent.writeln ('$returnType output = $call ;' );
666+ indent.writeln ('wrapped.add(0, output);' );
667+ }
668+ });
669+ indent.add (' catch (Throwable exception) ' );
670+ indent.addScoped ('{' , '}' , () {
671+ indent.writeln (
672+ 'ArrayList<Object> wrappedError = wrapError(exception);' );
673+ if (method.isAsynchronous) {
674+ indent.writeln ('reply.reply(wrappedError);' );
675+ } else {
676+ indent.writeln ('wrapped = wrappedError;' );
677+ }
678+ });
687679 indent.writeln ('reply.reply(wrapped);' );
688680 }
689681 });
@@ -765,22 +757,55 @@ Result<$returnType> $resultName =
765757 });
766758 }
767759
760+ void _writeErrorClass (Indent indent) {
761+ indent.writeln (
762+ '/** Error class for passing custom error details to Flutter via a thrown PlatformException. */' );
763+ indent.write ('public static class FlutterError extends RuntimeException ' );
764+ indent.addScoped ('{' , '}' , () {
765+ indent.newln ();
766+ indent.writeln ('/** The error code. */' );
767+ indent.writeln ('public final String code;' );
768+ indent.newln ();
769+ indent.writeln (
770+ '/** The error details. Must be a datatype supported by the api codec. */' );
771+ indent.writeln ('public final Object details;' );
772+ indent.newln ();
773+ indent.writeln (
774+ 'public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) ' );
775+ indent.writeScoped ('{' , '}' , () {
776+ indent.writeln ('super(message);' );
777+ indent.writeln ('this.code = code;' );
778+ indent.writeln ('this.details = details;' );
779+ });
780+ });
781+ }
782+
768783 void _writeWrapError (Indent indent) {
769784 indent.format ('''
770785@NonNull
771786private static ArrayList<Object> wrapError(@NonNull Throwable exception) {
772787\t ArrayList<Object> errorList = new ArrayList<Object>(3);
773- \t errorList.add(exception.toString());
774- \t errorList.add(exception.getClass().getSimpleName());
775- \t errorList.add(
776- \t\t "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
788+ \t if (exception instanceof FlutterError) {
789+ \t\t FlutterError error = (FlutterError) exception;
790+ \t\t errorList.add(error.code);
791+ \t\t errorList.add(error.getMessage());
792+ \t\t errorList.add(error.details);
793+ \t } else {
794+ \t\t errorList.add(exception.toString());
795+ \t\t errorList.add(exception.getClass().getSimpleName());
796+ \t\t errorList.add(
797+ \t\t\t "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
798+ \t }
777799\t return errorList;
778800}''' );
779801 }
780802
781803 @override
782804 void writeGeneralUtilities (
783805 JavaOptions generatorOptions, Root root, Indent indent) {
806+ indent.newln ();
807+ _writeErrorClass (indent);
808+ indent.newln ();
784809 _writeWrapError (indent);
785810 }
786811
0 commit comments