Skip to content

Commit

Permalink
[pigeon] fixed bug when using integer primitives on java (flutter#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
gaaclarke authored Sep 17, 2021
1 parent 881fccf commit b0238fb
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 7 deletions.
5 changes: 5 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
13 changes: 11 additions & 2 deletions packages/pigeon/lib/java_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,13 @@ static MessageCodec<Object> getCodec() {
indent.writeln(
'ArrayList<Object> args = (ArrayList<Object>)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);');
Expand All @@ -180,7 +186,7 @@ static MessageCodec<Object> getCodec() {
indent.writeln(
'throw new NullPointerException("$argName unexpectedly null.");');
});
methodArgument.add(argName);
methodArgument.add('$argName$argCast');
});
}
if (method.isAsynchronous) {
Expand Down Expand Up @@ -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<Class> classes, List<Enum> enums, String varName) {
final HostDatatype hostDatatype = getHostDatatype(field, classes, enums,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -122,4 +123,15 @@ public void hasValues() {
});
assertTrue(didCall[0]);
}

@Test
public void integerToLong() {
Everything everything = new Everything();
everything.setAnInt(123L);
Map<String, Object> map = everything.toMap();
assertTrue(map.containsKey("anInt"));
map.put("anInt", 123);
Everything readEverything = Everything.fromMap(map);
assertEquals(readEverything.getAnInt(), everything.getAnInt());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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<BinaryMessenger.BinaryMessageHandler> handler =
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
verify(binaryMessenger)
.setMessageHandler(eq("dev.flutter.pigeon.PrimitiveHostApi.anInt"), handler.capture());
MessageCodec<Object> codec = PrimitiveHostApi.getCodec();
ByteBuffer message = codec.encodeMessage(new ArrayList<Object>(Arrays.asList((Integer) 1)));
message.rewind();
handler
.getValue()
.onMessage(
message,
(bytes) -> {
bytes.rewind();
@SuppressWarnings("unchecked")
Map<String, Object> wrapped = (Map<String, Object>) codec.decodeMessage(bytes);
assertTrue(wrapped.containsKey("result"));
assertEquals(1L, ((Long) wrapped.get("result")).longValue());
});
}

@Test
public void primitiveBool() {
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
7 changes: 4 additions & 3 deletions packages/pigeon/test/java_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -818,9 +818,10 @@ void main() {
expect(code, contains('Long add(Long x, Long y)'));
expect(
code, contains('ArrayList<Object> args = (ArrayList<Object>)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', () {
Expand Down

0 comments on commit b0238fb

Please sign in to comment.