From b0238fb523cc3cd2453078535b0de49ec764d7ff Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Fri, 17 Sep 2021 15:49:35 -0700 Subject: [PATCH] [pigeon] fixed bug when using integer primitives on java (#472) --- packages/pigeon/CHANGELOG.md | 5 ++++ packages/pigeon/lib/generator_tools.dart | 2 +- packages/pigeon/lib/java_generator.dart | 13 ++++++-- .../android_unit_tests/AllDatatypesTest.java | 12 ++++++++ .../android_unit_tests/PrimitiveTest.java | 30 +++++++++++++++++++ packages/pigeon/pubspec.yaml | 2 +- packages/pigeon/test/java_generator_test.dart | 7 +++-- 7 files changed, 64 insertions(+), 7 deletions(-) diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index da16220a6ace..1f64a3b85105 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.5 + +* [java] Fixed bug when using Integer arguments to methods declared with 'int' + arguments. + ## 1.0.4 * [front-end] Fixed bug where codecs weren't generating support for types that diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index 451fcc2f5727..7656288fef38 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -8,7 +8,7 @@ import 'dart:mirrors'; import 'ast.dart'; /// The current version of pigeon. This must match the version in pubspec.yaml. -const String pigeonVersion = '1.0.4'; +const String pigeonVersion = '1.0.5'; /// Read all the content from [stdin] to a String. String readStdin() { diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 2a4aac067caa..f239989b9c1e 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -171,7 +171,13 @@ static MessageCodec getCodec() { indent.writeln( 'ArrayList args = (ArrayList)message;'); enumerate(method.arguments, (int index, NamedType arg) { - final String argType = _javaTypeForDartType(arg.type); + // The StandardMessageCodec can give us [Integer, Long] for + // a Dart 'int'. To keep things simple we just use 64bit + // longs in Pigeon with Java. + final bool isInt = arg.type.baseName == 'int'; + final String argType = + isInt ? 'Number' : _javaTypeForDartType(arg.type); + final String argCast = isInt ? '.longValue()' : ''; final String argName = _getSafeArgumentName(index, arg); indent.writeln( '$argType $argName = ($argType)args.get($index);'); @@ -180,7 +186,7 @@ static MessageCodec getCodec() { indent.writeln( 'throw new NullPointerException("$argName unexpectedly null.");'); }); - methodArgument.add(argName); + methodArgument.add('$argName$argCast'); }); } if (method.isAsynchronous) { @@ -365,6 +371,9 @@ String _javaTypeForDartType(TypeDeclaration type) { return _javaTypeForBuiltinDartType(type) ?? type.baseName; } +/// Casts variable named [varName] to the correct host datatype for [field]. +/// This is for use in codecs where we may have a map representation of an +/// object. String _castObject( NamedType field, List classes, List enums, String varName) { final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/AllDatatypesTest.java b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/AllDatatypesTest.java index c59e6605c6bd..b6a8cf1675f4 100644 --- a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/AllDatatypesTest.java +++ b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/AllDatatypesTest.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Map; import org.junit.Test; public class AllDatatypesTest { @@ -122,4 +123,15 @@ public void hasValues() { }); assertTrue(didCall[0]); } + + @Test + public void integerToLong() { + Everything everything = new Everything(); + everything.setAnInt(123L); + Map map = everything.toMap(); + assertTrue(map.containsKey("anInt")); + map.put("anInt", 123); + Everything readEverything = Everything.fromMap(map); + assertEquals(readEverything.getAnInt(), everything.getAnInt()); + } } diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java index dae86adceb46..eabdb5fbedb6 100644 --- a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java +++ b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java @@ -8,13 +8,17 @@ import static org.mockito.Mockito.*; import com.example.android_unit_tests.Primitive.PrimitiveFlutterApi; +import com.example.android_unit_tests.Primitive.PrimitiveHostApi; import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MessageCodec; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.junit.Test; +import org.mockito.ArgumentCaptor; public class PrimitiveTest { private static BinaryMessenger makeMockBinaryMessenger() { @@ -50,6 +54,32 @@ public void primitiveInt() { assertTrue(didCall[0]); } + @Test + public void primitiveIntHostApi() { + PrimitiveHostApi mockApi = mock(PrimitiveHostApi.class); + when(mockApi.anInt(1L)).thenReturn(1L); + BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); + PrimitiveHostApi.setup(binaryMessenger, mockApi); + ArgumentCaptor handler = + ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class); + verify(binaryMessenger) + .setMessageHandler(eq("dev.flutter.pigeon.PrimitiveHostApi.anInt"), handler.capture()); + MessageCodec codec = PrimitiveHostApi.getCodec(); + ByteBuffer message = codec.encodeMessage(new ArrayList(Arrays.asList((Integer) 1))); + message.rewind(); + handler + .getValue() + .onMessage( + message, + (bytes) -> { + bytes.rewind(); + @SuppressWarnings("unchecked") + Map wrapped = (Map) codec.decodeMessage(bytes); + assertTrue(wrapped.containsKey("result")); + assertEquals(1L, ((Long) wrapped.get("result")).longValue()); + }); + } + @Test public void primitiveBool() { BinaryMessenger binaryMessenger = makeMockBinaryMessenger(); diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index ca87553b26de..0d4b8d2393cd 100644 --- a/packages/pigeon/pubspec.yaml +++ b/packages/pigeon/pubspec.yaml @@ -2,7 +2,7 @@ name: pigeon description: Code generator tool to make communication between Flutter and the host platform type-safe and easier. repository: https://github.com/flutter/packages/tree/master/packages/pigeon issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon -version: 1.0.4 # This must match the version in lib/generator_tools.dart +version: 1.0.5 # This must match the version in lib/generator_tools.dart environment: sdk: '>=2.12.0 <3.0.0' diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 5fe056a8abca..835725a1c8d4 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -818,9 +818,10 @@ void main() { expect(code, contains('Long add(Long x, Long y)')); expect( code, contains('ArrayList args = (ArrayList)message;')); - expect(code, contains('Long xArg = (Long)args.get(0)')); - expect(code, contains('Long yArg = (Long)args.get(1)')); - expect(code, contains('Long output = api.add(xArg, yArg)')); + expect(code, contains('Number xArg = (Number)args.get(0)')); + expect(code, contains('Number yArg = (Number)args.get(1)')); + expect(code, + contains('Long output = api.add(xArg.longValue(), yArg.longValue())')); }); test('flutter multiple args', () {