Skip to content

Commit

Permalink
nullable
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrinneal committed Aug 8, 2023
1 parent 765618f commit 6958a07
Show file tree
Hide file tree
Showing 28 changed files with 409 additions and 47 deletions.
34 changes: 23 additions & 11 deletions packages/pigeon/lib/cpp_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,11 @@ class CppSourceGenerator extends StructuredGenerator<CppOptions> {
argName: argName,
encodableArgName: encodableArgName,
);
methodArgument.add(argName);
final String unwrapEnum =
isEnum(root, arg.type) && arg.type.isNullable
? ' ? &(*$argName) : nullptr'
: '';
methodArgument.add('$argName$unwrapEnum');
});
}

Expand Down Expand Up @@ -1207,19 +1211,19 @@ return EncodableValue(EncodableList{
final String errorGetter;

const String nullValue = 'EncodableValue()';
String enumPrefix = '';
if (isEnum(root, returnType)) {
enumPrefix = '(int) ';
}
if (returnType.isVoid) {
nonErrorPath = '${prefix}wrapped.push_back($nullValue);';
errorCondition = 'output.has_value()';
errorGetter = 'value';
} else {
final HostDatatype hostType = getHostDatatype(returnType, root.classes,
root.enums, _shortBaseCppTypeForBuiltinDartType);
String enumPrefix = '';
if (isEnum(root, returnType)) {
enumPrefix = '(int) ';
}
final String extractedValue =
'${enumPrefix}std::move(output).TakeValue()';

const String extractedValue = 'std::move(output).TakeValue()';
final String wrapperType = hostType.isBuiltin || isEnum(root, returnType)
? 'EncodableValue'
: 'CustomEncodableValue';
Expand All @@ -1229,13 +1233,13 @@ return EncodableValue(EncodableList{
nonErrorPath = '''
${prefix}auto output_optional = $extractedValue;
${prefix}if (output_optional) {
$prefix\twrapped.push_back($wrapperType(std::move(output_optional).value()));
$prefix\twrapped.push_back($wrapperType(${enumPrefix}std::move(output_optional).value()));
$prefix} else {
$prefix\twrapped.push_back($nullValue);
$prefix}''';
} else {
nonErrorPath =
'${prefix}wrapped.push_back($wrapperType($extractedValue));';
'${prefix}wrapped.push_back($wrapperType($enumPrefix$extractedValue));';
}
errorCondition = 'output.has_error()';
errorGetter = 'error';
Expand Down Expand Up @@ -1337,8 +1341,16 @@ ${prefix}reply(EncodableValue(std::move(wrapped)));''';
indent.writeln(
'const auto* $argName = std::get_if<${hostType.datatype}>(&$encodableArgName);');
} else if (hostType.isEnum) {
indent.writeln(
'const auto* $argName = &((${hostType.datatype})std::get<int>($encodableArgName));');
if (hostType.isNullable) {
indent.writeln('std::optional<${hostType.datatype}> $argName;');
indent.writeScoped('if (!$encodableArgName.IsNull()) {', '}', () {
indent.writeln(
'$argName = std::make_optional<${hostType.datatype}>(std::get<int>($encodableArgName));');
});
} else {
indent.writeln(
'const auto* $argName = &((${hostType.datatype})std::get<int>($encodableArgName));');
}
} else {
indent.writeln(
'const auto* $argName = &(std::any_cast<const ${hostType.datatype}&>(std::get<CustomEncodableValue>($encodableArgName)));');
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ final BinaryMessenger? _binaryMessenger;
if (customEnumNames.contains(returnType)) {
if (func.returnType.isNullable) {
returnStatement =
'$returnStatement $nullablyTypedAccessor == null ? null : $returnType.values[$accessor as int]';
'$returnStatement ($accessor as int?) == null ? null : $returnType.values[$accessor! as int]';
} else {
returnStatement =
'$returnStatement $returnType.values[$accessor! as int]';
Expand Down
13 changes: 10 additions & 3 deletions packages/pigeon/lib/java_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ class JavaGenerator extends StructuredGenerator<JavaOptions> {
indent.nest(2, () {
indent.write('(message, reply) -> ');
indent.addScoped('{', '});', () {
String enumTag = '';
final String returnType = method.returnType.isVoid
? 'Void'
: _javaTypeForDartType(method.returnType);
Expand Down Expand Up @@ -706,12 +707,17 @@ class JavaGenerator extends StructuredGenerator<JavaOptions> {
if (method.isAsynchronous) {
final String resultValue =
method.returnType.isVoid ? 'null' : 'result';
if (isEnum(root, method.returnType)) {
enumTag = method.returnType.isNullable
? ' == null ? null : $resultValue.index'
: '.index';
}
const String resultName = 'resultCallback';
indent.format('''
Result<$returnType> $resultName =
\t\tnew Result<$returnType>() {
\t\t\tpublic void success($returnType result) {
\t\t\t\twrapped.add(0, $resultValue);
\t\t\t\twrapped.add(0, $resultValue$enumTag);
\t\t\t\treply.reply(wrapped);
\t\t\t}
Expand All @@ -734,9 +740,10 @@ Result<$returnType> $resultName =
indent.writeln('$call;');
indent.writeln('wrapped.add(0, null);');
} else {
String enumTag = '';
if (isEnum(root, method.returnType)) {
enumTag = '.index';
enumTag = method.returnType.isNullable
? ' == null ? null : output.index'
: '.index';
}
indent.writeln('$returnType output = $call;');
indent.writeln('wrapped.add(0, output$enumTag);');
Expand Down
11 changes: 8 additions & 3 deletions packages/pigeon/lib/kotlin_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,14 @@ class KotlinGenerator extends StructuredGenerator<KotlinOptions> {
indent.writeln('reply.reply(wrapError(error))');
}, addTrailingNewline: false);
indent.addScoped(' else {', '}', () {
final String enumTag =
isEnum(root, method.returnType) ? '!!.raw' : '';
if (method.returnType.isVoid) {
indent.writeln('reply.reply(wrapResult(null))');
} else {
indent.writeln('val data = result.getOrNull()');
indent.writeln('reply.reply(wrapResult(data))');
indent
.writeln('reply.reply(wrapResult(data$enumTag))');
}
});
});
Expand All @@ -593,7 +596,9 @@ class KotlinGenerator extends StructuredGenerator<KotlinOptions> {
} else {
String enumTag = '';
if (isEnum(root, method.returnType)) {
enumTag = '.raw';
final String safeUnwrap =
method.returnType.isNullable ? '?' : '';
enumTag = '$safeUnwrap.raw';
}
indent.writeln('wrapped = listOf<Any?>($call$enumTag)');
}
Expand Down Expand Up @@ -748,7 +753,7 @@ String _castForceUnwrap(String value, TypeDeclaration type, Root root) {
if (isEnum(root, type)) {
final String forceUnwrap = type.isNullable ? '' : '!!';
final String nullableConditionPrefix =
type.isNullable ? '$value == null ? null : ' : '';
type.isNullable ? 'if ($value == null) null else ' : '';
return '$nullableConditionPrefix${_kotlinTypeForDartType(type)}.ofRaw($value as Int)$forceUnwrap';
} else {
// The StandardMessageCodec can give us [Integer, Long] for
Expand Down
51 changes: 39 additions & 12 deletions packages/pigeon/lib/objc_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ class ObjcHeaderGenerator extends StructuredGenerator<ObjcOptions> {
lastArgName: 'completion',
lastArgType: callbackType,
isEnum: (TypeDeclaration t) => isEnum(root, t),
root: root,
)};');
}
indent.writeln('@end');
Expand Down Expand Up @@ -355,8 +356,10 @@ class ObjcHeaderGenerator extends StructuredGenerator<ObjcOptions> {
if (func.returnType.isVoid) {
lastArgType = 'void (^)(FlutterError *_Nullable)';
} else if (isEnum(root, func.returnType)) {
lastArgType =
'void (^)(${returnTypeName.baseName}, FlutterError *_Nullable)';
final String enumReturnType = func.returnType.isNullable
? 'nullable ${returnTypeName.baseName}Wrapper *'
: returnTypeName.baseName;
lastArgType = 'void (^)($enumReturnType, FlutterError *_Nullable)';
} else {
lastArgType =
'void (^)(${returnTypeName.withPtr}_Nullable, FlutterError *_Nullable)';
Expand All @@ -365,7 +368,9 @@ class ObjcHeaderGenerator extends StructuredGenerator<ObjcOptions> {
if (func.returnType.isVoid) {
returnType = 'void';
} else if (isEnum(root, func.returnType)) {
returnType = returnTypeName.baseName;
returnType = func.returnType.isNullable
? '${returnTypeName.baseName}Wrapper *_Nullable'
: returnTypeName.baseName;
} else {
returnType = 'nullable ${returnTypeName.withPtr.trim()}';
}
Expand All @@ -390,6 +395,7 @@ class ObjcHeaderGenerator extends StructuredGenerator<ObjcOptions> {
lastArgName: lastArgName,
lastArgType: lastArgType,
isEnum: (TypeDeclaration t) => isEnum(root, t),
root: root,
);
indent.writeln('$signature;');
}
Expand Down Expand Up @@ -688,10 +694,19 @@ class ObjcSourceGenerator extends StructuredGenerator<ObjcOptions> {
if (isEnum(root, arg.type)) {
final String className =
_className(generatorOptions.prefix, arg.type.baseName);
// indent.writeln(
// '$className *$argName = [[${className}Wrapper alloc] init];');
indent.writeln(
'$className $argName = [GetNullableObjectAtIndex(args, $count) integerValue];');
if (arg.type.isNullable) {
indent.writeln(
'NSNumber *${argName}AsNumber = GetNullableObjectAtIndex(args, $count);');
indent.writeln(
'${className}Wrapper *$argName = ${argName}AsNumber == nil ? nil : [[${className}Wrapper alloc] init];');
indent.writeScoped('if ($argName != nil) {', '}', () {
indent.writeln(
'$argName.value = [${argName}AsNumber integerValue];');
});
} else {
indent.writeln(
'$className $argName = [GetNullableObjectAtIndex(args, $count) integerValue];');
}
} else {
final _ObjcPtr argType =
_objcTypeForDartType(generatorOptions.prefix, arg.type);
Expand Down Expand Up @@ -756,9 +771,16 @@ class ObjcSourceGenerator extends StructuredGenerator<ObjcOptions> {
indent.writeln('callback(wrapResult(nil, error));');
} else {
if (isEnum(root, func.returnType)) {
indent.writeln('${returnType.baseName} enumValue = $call;');
indent.writeln(
'NSNumber *output = [NSNumber numberWithInteger:enumValue];');
if (func.returnType.isNullable) {
indent.writeln(
'${returnType.baseName}Wrapper * enumWrapper = $call;');
indent.writeln(
'NSNumber *output = enumWrapper == nil ? nil : [NSNumber numberWithInteger:enumWrapper.value];');
} else {
indent.writeln('${returnType.baseName} enumValue = $call;');
indent.writeln(
'NSNumber *output = [NSNumber numberWithInteger:enumValue];');
}
} else {
indent.writeln('${returnType.withPtr}output = $call;');
}
Expand Down Expand Up @@ -1016,6 +1038,7 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) {
lastArgType: callbackType,
argNameFunc: argNameFunc,
isEnum: (TypeDeclaration t) => isEnum(root, t),
root: root,
));
indent.addScoped(' {', '}', () {
indent.writeln('FlutterBasicMessageChannel *channel =');
Expand Down Expand Up @@ -1235,17 +1258,21 @@ String _makeObjcSignature({
required String lastArgType,
required String lastArgName,
required bool Function(TypeDeclaration) isEnum,
required Root root,
String Function(int, NamedType)? argNameFunc,
}) {
argNameFunc = argNameFunc ?? (int _, NamedType e) => e.name;
argNameFunc = argNameFunc ??
(int _, NamedType e) =>
e.type.isNullable && isEnum(e.type) ? '${e.name}Wrapped' : e.name;
final Iterable<String> argNames =
followedByOne(indexMap(func.arguments, argNameFunc), lastArgName);
final Iterable<String> selectorComponents =
_getSelectorComponents(func, lastArgName);
final Iterable<String> argTypes = followedByOne(
func.arguments.map((NamedType arg) {
if (isEnum(arg.type)) {
return _className(options.prefix, arg.type.baseName);
final String enumName = _className(options.prefix, arg.type.baseName);
return arg.type.isNullable ? 'nullable ${enumName}Wrapper *' : enumName;
} else {
final String nullable = arg.type.isNullable ? 'nullable ' : '';
final _ObjcPtr argType = _objcTypeForDartType(options.prefix, arg.type);
Expand Down
21 changes: 15 additions & 6 deletions packages/pigeon/lib/swift_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,11 @@ import FlutterMacOS
indent.addScoped('{ result in', '}', () {
indent.write('switch result ');
indent.addScoped('{', '}', () {
final String enumTag =
isEnum(root, method.returnType) ? '.rawValue' : '';
indent.writeln('case .success$successVariableInit:');
indent.nest(1, () {
indent.writeln('reply(wrapResult($resultName))');
indent.writeln('reply(wrapResult($resultName$enumTag))');
});
indent.writeln('case .failure(let error):');
indent.nest(1, () {
Expand All @@ -524,8 +526,12 @@ import FlutterMacOS
if (isEnum(root, method.returnType)) {
enumTag = '.rawValue';
}
indent.writeln('let result = $call$enumTag');
indent.writeln('reply(wrapResult(result))');
enumTag = method.returnType.isNullable &&
isEnum(root, method.returnType)
? '?$enumTag'
: enumTag;
indent.writeln('let result = $call');
indent.writeln('reply(wrapResult(result$enumTag))');
}
}, addTrailingNewline: false);
indent.addScoped(' catch {', '}', () {
Expand Down Expand Up @@ -644,9 +650,12 @@ import FlutterMacOS
}) {
String castForceUnwrap(String value, TypeDeclaration type, Root root) {
if (isEnum(root, type)) {
assert(!type.isNullable,
'nullable enums require special code that this helper does not supply');
return '${_swiftTypeForDartType(type)}(rawValue: $value as! Int)!';
String output =
'${_swiftTypeForDartType(type)}(rawValue: $value as! Int)!';
if (type.isNullable) {
output = '$value is NSNull ? nil : $output';
}
return output;
} else if (type.baseName == 'Object') {
return value + (type.isNullable ? '' : '!');
} else if (type.baseName == 'int') {
Expand Down
6 changes: 3 additions & 3 deletions packages/pigeon/pigeons/core_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ abstract class HostIntegrationCoreApi {
@SwiftFunction('echoNullable(_:)')
Map<String?, Object?>? echoNullableMap(Map<String?, Object?>? aNullableMap);

// @ObjCSelector('echoNullableEnum:')
// @SwiftFunction('echoNullable(_:)')
// AnEnum? echoNullableEnum(AnEnum? anEnum);
@ObjCSelector('echoNullableEnum:')
@SwiftFunction('echoNullable(_:)')
AnEnum? echoNullableEnum(AnEnum? anEnum);

// ========== Asynchronous method tests ==========

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ public void throwErrorFromVoid() {
return aNullableMap;
}

@Override
public @Nullable AnEnum echoNullableEnum(@Nullable AnEnum anEnum) {
return anEnum;
}

@Override
public void noopAsync(@NonNull Result<Void> result) {
result.success(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,9 @@ AllNullableTypes sendMultipleNullableTypes(
/** Returns the passed map, to test serialization and deserialization. */
@Nullable
Map<String, Object> echoNullableMap(@Nullable Map<String, Object> aNullableMap);

@Nullable
AnEnum echoNullableEnum(@Nullable AnEnum anEnum);
/**
* A no-op function taking no arguments and returning no value, to sanity test basic
* asynchronous calling.
Expand Down Expand Up @@ -1843,6 +1846,31 @@ static void setup(
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
binaryMessenger,
"dev.flutter.pigeon.pigeon_integration_tests.HostIntegrationCoreApi.echoNullableEnum",
getCodec());
if (api != null) {
channel.setMessageHandler(
(message, reply) -> {
ArrayList<Object> wrapped = new ArrayList<Object>();
ArrayList<Object> args = (ArrayList<Object>) message;
AnEnum anEnumArg = args.get(0) == null ? null : AnEnum.values()[(int) args.get(0)];
try {
AnEnum output = api.echoNullableEnum(anEnumArg);
wrapped.add(0, output == null ? null : output.index);
} catch (Throwable exception) {
ArrayList<Object> wrappedError = wrapError(exception);
wrapped = wrappedError;
}
reply.reply(wrapped);
});
} else {
channel.setMessageHandler(null);
}
}
{
BasicMessageChannel<Object> channel =
new BasicMessageChannel<>(
Expand Down Expand Up @@ -2135,7 +2163,7 @@ public void error(Throwable error) {
Result<AnEnum> resultCallback =
new Result<AnEnum>() {
public void success(AnEnum result) {
wrapped.add(0, result);
wrapped.add(0, result.index);
reply.reply(wrapped);
}

Expand Down
Loading

0 comments on commit 6958a07

Please sign in to comment.