Skip to content

Commit 3210a79

Browse files
authored
[swift2objc] Support the async annotation (#1779)
1 parent 4b03d95 commit 3210a79

19 files changed

+249
-21
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// An interface to describe a Swift entity's ability to be annotated
6+
/// with `async`.
7+
abstract interface class CanAsync {
8+
abstract final bool async;
9+
}

pkgs/swift2objc/lib/src/ast/_core/interfaces/function_declaration.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import '../shared/referred_type.dart';
6+
import 'can_async.dart';
67
import 'can_throw.dart';
78
import 'declaration.dart';
89
import 'executable.dart';
@@ -16,6 +17,7 @@ abstract interface class FunctionDeclaration
1617
Parameterizable,
1718
Executable,
1819
TypeParameterizable,
19-
CanThrow {
20+
CanThrow,
21+
CanAsync {
2022
abstract final ReferredType returnType;
2123
}

pkgs/swift2objc/lib/src/ast/_core/interfaces/variable_declaration.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import '../shared/referred_type.dart';
6+
import 'can_async.dart';
67
import 'can_throw.dart';
78
import 'declaration.dart';
89

910
/// Describes a variable-like entity.
1011
///
11-
/// This declaration [CanThrow] because Swift variables can have explicit
12-
/// getters, which can be marked with `throws`. Such variables may not have a
13-
/// setter.
14-
abstract interface class VariableDeclaration implements Declaration, CanThrow {
12+
/// This declaration implements [CanThrow] and [CanAsync] because Swift
13+
/// variables can have explicit getters, which can be marked with `throws` and
14+
/// `async`. Such variables may not have a setter.
15+
abstract interface class VariableDeclaration
16+
implements Declaration, CanThrow, CanAsync {
1517
abstract final bool isConstant;
1618
abstract final ReferredType type;
1719
}

pkgs/swift2objc/lib/src/ast/declarations/compounds/members/initializer_declaration.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import '../../../_core/interfaces/can_async.dart';
56
import '../../../_core/interfaces/can_throw.dart';
67
import '../../../_core/interfaces/declaration.dart';
78
import '../../../_core/interfaces/executable.dart';
@@ -18,7 +19,8 @@ class InitializerDeclaration
1819
Parameterizable,
1920
ObjCAnnotatable,
2021
Overridable,
21-
CanThrow {
22+
CanThrow,
23+
CanAsync {
2224
@override
2325
String id;
2426

@@ -34,6 +36,9 @@ class InitializerDeclaration
3436
@override
3537
bool throws;
3638

39+
@override
40+
bool async;
41+
3742
bool isFailable;
3843

3944
@override
@@ -54,6 +59,7 @@ class InitializerDeclaration
5459
required this.hasObjCAnnotation,
5560
required this.isOverriding,
5661
required this.throws,
62+
required this.async,
5763
required this.isFailable,
5864
});
5965
}

pkgs/swift2objc/lib/src/ast/declarations/compounds/members/method_declaration.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class MethodDeclaration
3333
@override
3434
bool throws;
3535

36+
@override
37+
bool async;
38+
3639
@override
3740
List<String> statements;
3841

@@ -57,5 +60,6 @@ class MethodDeclaration
5760
this.isStatic = false,
5861
this.isOverriding = false,
5962
this.throws = false,
63+
this.async = false,
6064
}) : assert(!isStatic || !isOverriding);
6165
}

pkgs/swift2objc/lib/src/ast/declarations/compounds/members/property_declaration.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable {
2828
@override
2929
bool throws;
3030

31+
@override
32+
bool async;
33+
3134
bool hasSetter;
3235

3336
PropertyStatements? getter;
@@ -46,6 +49,7 @@ class PropertyDeclaration implements VariableDeclaration, ObjCAnnotatable {
4649
this.setter,
4750
this.isStatic = false,
4851
this.throws = false,
52+
this.async = false,
4953
}) : assert(!(isConstant && hasSetter)),
5054
assert(!(hasSetter && throws));
5155
}

pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ class GlobalFunctionDeclaration implements FunctionDeclaration {
3636
@override
3737
bool throws;
3838

39+
@override
40+
bool async;
41+
3942
@override
4043
ReferredType returnType;
4144

@@ -50,6 +53,7 @@ class GlobalFunctionDeclaration implements FunctionDeclaration {
5053
this.typeParams = const [],
5154
this.statements = const [],
5255
this.throws = false,
56+
this.async = false,
5357
});
5458
}
5559

@@ -70,11 +74,15 @@ class GlobalVariableDeclaration implements VariableDeclaration {
7074
@override
7175
bool throws;
7276

77+
@override
78+
bool async;
79+
7380
GlobalVariableDeclaration({
7481
required this.id,
7582
required this.name,
7683
required this.type,
7784
required this.isConstant,
7885
required this.throws,
86+
required this.async,
7987
}) : assert(!(throws && !isConstant));
8088
}

pkgs/swift2objc/lib/src/generator/_core/utils.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import 'dart:io';
22
import 'package:path/path.dart' as path;
3+
import '../../ast/_core/interfaces/can_async.dart';
4+
import '../../ast/_core/interfaces/can_throw.dart';
5+
import '../../ast/_core/interfaces/declaration.dart';
36
import '../../ast/_core/shared/parameter.dart';
47

58
String generateParameters(List<Parameter> params) {
@@ -34,3 +37,14 @@ void outputNextToFile({
3437

3538
File(outputPath).writeAsStringSync(content);
3639
}
40+
41+
String generateAnnotations(Declaration decl) {
42+
final annotations = StringBuffer();
43+
if (decl is CanAsync && (decl as CanAsync).async) {
44+
annotations.write('async ');
45+
}
46+
if (decl is CanThrow && (decl as CanThrow).throws) {
47+
annotations.write('throws ');
48+
}
49+
return annotations.toString();
50+
}

pkgs/swift2objc/lib/src/generator/generators/class_generator.dart

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,8 @@ List<String> _generateInitializer(InitializerDeclaration initializer) {
8787

8888
header.write('(${generateParameters(initializer.params)})');
8989

90-
if (initializer.throws) {
91-
header.write(' throws');
92-
}
93-
9490
return [
95-
'$header {',
91+
'$header ${generateAnnotations(initializer)}{',
9692
...initializer.statements.indent(),
9793
'}\n',
9894
];
@@ -117,19 +113,17 @@ List<String> _generateClassMethod(MethodDeclaration method) {
117113
}
118114

119115
header.write(
120-
'public func ${method.name}(${generateParameters(method.params)})',
116+
'public func ${method.name}(${generateParameters(method.params)}) ',
121117
);
122118

123-
if (method.throws) {
124-
header.write(' throws');
125-
}
119+
header.write(generateAnnotations(method));
126120

127121
if (!method.returnType.sameAs(voidType)) {
128-
header.write(' -> ${method.returnType.swiftType}');
122+
header.write('-> ${method.returnType.swiftType} ');
129123
}
130124

131125
return [
132-
'$header {',
126+
'$header{',
133127
...method.statements.indent(),
134128
'}\n',
135129
];
@@ -154,7 +148,7 @@ List<String> _generateClassProperty(PropertyDeclaration property) {
154148
header.write('public var ${property.name}: ${property.type.swiftType} {');
155149

156150
final getterLines = [
157-
'get {',
151+
'get ${generateAnnotations(property)}{',
158152
...(property.getter?.statements.indent() ?? <String>[]),
159153
'}'
160154
];

pkgs/swift2objc/lib/src/parser/parsers/declaration_parsers/parse_function_declaration.dart

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ GlobalFunctionDeclaration parseGlobalFunctionDeclaration(
2424
returnType: _parseFunctionReturnType(globalFunctionSymbolJson, symbolgraph),
2525
params: info.params,
2626
throws: info.throws,
27+
async: info.async,
2728
);
2829
}
2930

@@ -42,12 +43,14 @@ MethodDeclaration parseMethodDeclaration(
4243
hasObjCAnnotation: parseSymbolHasObjcAnnotation(methodSymbolJson),
4344
isStatic: isStatic,
4445
throws: info.throws,
46+
async: info.async,
4547
);
4648
}
4749

4850
typedef ParsedFunctionInfo = ({
4951
List<Parameter> params,
5052
bool throws,
53+
bool async,
5154
});
5255

5356
ParsedFunctionInfo parseFunctionInfo(
@@ -120,17 +123,22 @@ ParsedFunctionInfo parseFunctionInfo(
120123
}
121124
}
122125

123-
// Parse annotations until we run out.
126+
// Parse annotations until we run out. The annotations are keywords separated
127+
// by whitespace tokens.
124128
final annotations = <String>{};
125129
while (true) {
126130
final keyword = maybeConsume('keyword');
127-
if (keyword == null) break;
128-
annotations.add(keyword);
131+
if (keyword == null) {
132+
if (maybeConsume('text') != '') break;
133+
} else {
134+
annotations.add(keyword);
135+
}
129136
}
130137

131138
return (
132139
params: parameters,
133140
throws: annotations.contains('throws'),
141+
async: annotations.contains('async'),
134142
);
135143
}
136144

0 commit comments

Comments
 (0)