Skip to content

Commit 9dffa39

Browse files
[pigeon] Adds platform for imports that aren't support on a platform (#8338)
While working on updating `webview_flutter_wkwebview` to use ProxyApis, the `UIKit` import would be invalid on macOS. This PR now surrounds `ProxyApi` imports with a check if every class of an import excludes a platform.
1 parent 2d5e714 commit 9dffa39

File tree

5 files changed

+176
-11
lines changed

5 files changed

+176
-11
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 22.7.1
22

3+
* [swift] Adds support for platform checks of imports of ProxyApis.
34
* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
45

56
## 22.7.0

packages/pigeon/lib/generator_tools.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import 'ast.dart';
1414
/// The current version of pigeon.
1515
///
1616
/// This must match the version in pubspec.yaml.
17-
const String pigeonVersion = '22.7.0';
17+
const String pigeonVersion = '22.7.1';
1818

1919
/// Read all the content from [stdin] to a String.
2020
String readStdin() {

packages/pigeon/lib/swift_generator.dart

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,7 @@ class SwiftGenerator extends StructuredGenerator<SwiftOptions> {
154154
}) {
155155
indent.writeln('import Foundation');
156156

157-
final Iterable<String> proxyApiImports = root.apis
158-
.whereType<AstProxyApi>()
159-
.map((AstProxyApi proxyApi) => proxyApi.swiftOptions?.import)
160-
.nonNulls
161-
.toSet();
162-
for (final String import in proxyApiImports) {
163-
indent.writeln('import $import');
164-
}
157+
_writeProxyApiImports(indent, root.apis.whereType<AstProxyApi>());
165158
indent.newln();
166159

167160
indent.format('''
@@ -2487,6 +2480,42 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
24872480
});
24882481
});
24892482
}
2483+
2484+
void _writeProxyApiImports(Indent indent, Iterable<AstProxyApi> apis) {
2485+
final Map<String, List<AstProxyApi>> apisOfImports =
2486+
<String, List<AstProxyApi>>{};
2487+
for (final AstProxyApi proxyApi in apis) {
2488+
final String? import = proxyApi.swiftOptions?.import;
2489+
if (import != null) {
2490+
if (apisOfImports.containsKey(import)) {
2491+
apisOfImports[import]!.add(proxyApi);
2492+
} else {
2493+
apisOfImports[import] = <AstProxyApi>[proxyApi];
2494+
}
2495+
}
2496+
}
2497+
2498+
for (final String import in apisOfImports.keys) {
2499+
// If every ProxyApi that shares an import excludes a platform for
2500+
// support, surround the import with `#if !os(...) #endif`.
2501+
final List<String> unsupportedPlatforms = <String>[
2502+
if (!apisOfImports[import]!
2503+
.any((AstProxyApi api) => api.swiftOptions?.supportsIos ?? true))
2504+
'!os(iOS)',
2505+
if (!apisOfImports[import]!
2506+
.any((AstProxyApi api) => api.swiftOptions?.supportsMacos ?? true))
2507+
'!os(macOS)',
2508+
];
2509+
2510+
if (unsupportedPlatforms.isNotEmpty) {
2511+
indent.writeln('#if ${unsupportedPlatforms.join(' || ')}');
2512+
}
2513+
indent.writeln('import $import');
2514+
if (unsupportedPlatforms.isNotEmpty) {
2515+
indent.writeln('#endif');
2516+
}
2517+
}
2518+
}
24902519
}
24912520

24922521
typedef _VersionRequirement = ({TypeDeclaration type, Version version});

packages/pigeon/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: pigeon
22
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
33
repository: https://github.com/flutter/packages/tree/main/packages/pigeon
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22
5-
version: 22.7.0 # This must match the version in lib/generator_tools.dart
5+
version: 22.7.1 # This must match the version in lib/generator_tools.dart
66

77
environment:
88
sdk: ^3.4.0

packages/pigeon/test/swift/proxy_api_test.dart

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,141 @@ void main() {
187187
);
188188
});
189189

190+
group('imports', () {
191+
test('add check if every class does not support iOS', () {
192+
final Root root = Root(
193+
apis: <Api>[
194+
AstProxyApi(
195+
name: 'Api',
196+
swiftOptions: const SwiftProxyApiOptions(
197+
import: 'MyImport',
198+
supportsIos: false,
199+
),
200+
constructors: <Constructor>[],
201+
fields: <ApiField>[],
202+
methods: <Method>[],
203+
),
204+
],
205+
classes: <Class>[],
206+
enums: <Enum>[],
207+
);
208+
final StringBuffer sink = StringBuffer();
209+
const SwiftGenerator generator = SwiftGenerator();
210+
generator.generate(
211+
const SwiftOptions(),
212+
root,
213+
sink,
214+
dartPackageName: DEFAULT_PACKAGE_NAME,
215+
);
216+
final String code = sink.toString();
217+
218+
expect(code, contains('#if !os(iOS)\nimport MyImport\n#endif'));
219+
});
220+
221+
test('add check if every class does not support macOS', () {
222+
final Root root = Root(
223+
apis: <Api>[
224+
AstProxyApi(
225+
name: 'Api',
226+
swiftOptions: const SwiftProxyApiOptions(
227+
import: 'MyImport',
228+
supportsMacos: false,
229+
),
230+
constructors: <Constructor>[],
231+
fields: <ApiField>[],
232+
methods: <Method>[],
233+
),
234+
],
235+
classes: <Class>[],
236+
enums: <Enum>[],
237+
);
238+
final StringBuffer sink = StringBuffer();
239+
const SwiftGenerator generator = SwiftGenerator();
240+
generator.generate(
241+
const SwiftOptions(),
242+
root,
243+
sink,
244+
dartPackageName: DEFAULT_PACKAGE_NAME,
245+
);
246+
final String code = sink.toString();
247+
248+
expect(code, contains('#if !os(macOS)\nimport MyImport\n#endif'));
249+
});
250+
251+
test('add check if for multiple unsupported platforms', () {
252+
final Root root = Root(
253+
apis: <Api>[
254+
AstProxyApi(
255+
name: 'Api',
256+
swiftOptions: const SwiftProxyApiOptions(
257+
import: 'MyImport',
258+
supportsIos: false,
259+
supportsMacos: false,
260+
),
261+
constructors: <Constructor>[],
262+
fields: <ApiField>[],
263+
methods: <Method>[],
264+
),
265+
],
266+
classes: <Class>[],
267+
enums: <Enum>[],
268+
);
269+
final StringBuffer sink = StringBuffer();
270+
const SwiftGenerator generator = SwiftGenerator();
271+
generator.generate(
272+
const SwiftOptions(),
273+
root,
274+
sink,
275+
dartPackageName: DEFAULT_PACKAGE_NAME,
276+
);
277+
final String code = sink.toString();
278+
279+
expect(
280+
code,
281+
contains('#if !os(iOS) || !os(macOS)\nimport MyImport\n#endif'),
282+
);
283+
});
284+
285+
test('do not add check if at least one class is supported', () {
286+
final Root root = Root(
287+
apis: <Api>[
288+
AstProxyApi(
289+
name: 'Api',
290+
swiftOptions: const SwiftProxyApiOptions(
291+
import: 'MyImport',
292+
supportsIos: false,
293+
),
294+
constructors: <Constructor>[],
295+
fields: <ApiField>[],
296+
methods: <Method>[],
297+
),
298+
AstProxyApi(
299+
name: 'Api2',
300+
swiftOptions: const SwiftProxyApiOptions(
301+
import: 'MyImport',
302+
),
303+
constructors: <Constructor>[],
304+
fields: <ApiField>[],
305+
methods: <Method>[],
306+
),
307+
],
308+
classes: <Class>[],
309+
enums: <Enum>[],
310+
);
311+
final StringBuffer sink = StringBuffer();
312+
const SwiftGenerator generator = SwiftGenerator();
313+
generator.generate(
314+
const SwiftOptions(),
315+
root,
316+
sink,
317+
dartPackageName: DEFAULT_PACKAGE_NAME,
318+
);
319+
final String code = sink.toString();
320+
321+
expect(code, isNot(contains('#if !os(iOS)\nimport MyImport')));
322+
});
323+
});
324+
190325
group('inheritance', () {
191326
test('extends', () {
192327
final AstProxyApi api2 = AstProxyApi(

0 commit comments

Comments
 (0)