diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index e8226fe9856..71b33fa7441 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 22.7.1 +* [swift] Adds support for platform checks of imports of ProxyApis. * Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. ## 22.7.0 diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index e5a943bdcb9..c23817ad617 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -14,7 +14,7 @@ import 'ast.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '22.7.0'; +const String pigeonVersion = '22.7.1'; /// Read all the content from [stdin] to a String. String readStdin() { diff --git a/packages/pigeon/lib/swift_generator.dart b/packages/pigeon/lib/swift_generator.dart index 4962774c9a0..d5c09d4ec17 100644 --- a/packages/pigeon/lib/swift_generator.dart +++ b/packages/pigeon/lib/swift_generator.dart @@ -154,14 +154,7 @@ class SwiftGenerator extends StructuredGenerator { }) { indent.writeln('import Foundation'); - final Iterable proxyApiImports = root.apis - .whereType() - .map((AstProxyApi proxyApi) => proxyApi.swiftOptions?.import) - .nonNulls - .toSet(); - for (final String import in proxyApiImports) { - indent.writeln('import $import'); - } + _writeProxyApiImports(indent, root.apis.whereType()); indent.newln(); indent.format(''' @@ -2487,6 +2480,42 @@ private func nilOrValue(_ value: Any?) -> T? { }); }); } + + void _writeProxyApiImports(Indent indent, Iterable apis) { + final Map> apisOfImports = + >{}; + for (final AstProxyApi proxyApi in apis) { + final String? import = proxyApi.swiftOptions?.import; + if (import != null) { + if (apisOfImports.containsKey(import)) { + apisOfImports[import]!.add(proxyApi); + } else { + apisOfImports[import] = [proxyApi]; + } + } + } + + for (final String import in apisOfImports.keys) { + // If every ProxyApi that shares an import excludes a platform for + // support, surround the import with `#if !os(...) #endif`. + final List unsupportedPlatforms = [ + if (!apisOfImports[import]! + .any((AstProxyApi api) => api.swiftOptions?.supportsIos ?? true)) + '!os(iOS)', + if (!apisOfImports[import]! + .any((AstProxyApi api) => api.swiftOptions?.supportsMacos ?? true)) + '!os(macOS)', + ]; + + if (unsupportedPlatforms.isNotEmpty) { + indent.writeln('#if ${unsupportedPlatforms.join(' || ')}'); + } + indent.writeln('import $import'); + if (unsupportedPlatforms.isNotEmpty) { + indent.writeln('#endif'); + } + } + } } typedef _VersionRequirement = ({TypeDeclaration type, Version version}); diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index d525aba2f22..6e5378a2624 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/main/packages/pigeon issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22 -version: 22.7.0 # This must match the version in lib/generator_tools.dart +version: 22.7.1 # This must match the version in lib/generator_tools.dart environment: sdk: ^3.4.0 diff --git a/packages/pigeon/test/swift/proxy_api_test.dart b/packages/pigeon/test/swift/proxy_api_test.dart index 3c9cb12c756..d149d5d0102 100644 --- a/packages/pigeon/test/swift/proxy_api_test.dart +++ b/packages/pigeon/test/swift/proxy_api_test.dart @@ -187,6 +187,141 @@ void main() { ); }); + group('imports', () { + test('add check if every class does not support iOS', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + swiftOptions: const SwiftProxyApiOptions( + import: 'MyImport', + supportsIos: false, + ), + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const SwiftGenerator generator = SwiftGenerator(); + generator.generate( + const SwiftOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + + expect(code, contains('#if !os(iOS)\nimport MyImport\n#endif')); + }); + + test('add check if every class does not support macOS', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + swiftOptions: const SwiftProxyApiOptions( + import: 'MyImport', + supportsMacos: false, + ), + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const SwiftGenerator generator = SwiftGenerator(); + generator.generate( + const SwiftOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + + expect(code, contains('#if !os(macOS)\nimport MyImport\n#endif')); + }); + + test('add check if for multiple unsupported platforms', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + swiftOptions: const SwiftProxyApiOptions( + import: 'MyImport', + supportsIos: false, + supportsMacos: false, + ), + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const SwiftGenerator generator = SwiftGenerator(); + generator.generate( + const SwiftOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + + expect( + code, + contains('#if !os(iOS) || !os(macOS)\nimport MyImport\n#endif'), + ); + }); + + test('do not add check if at least one class is supported', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + swiftOptions: const SwiftProxyApiOptions( + import: 'MyImport', + supportsIos: false, + ), + constructors: [], + fields: [], + methods: [], + ), + AstProxyApi( + name: 'Api2', + swiftOptions: const SwiftProxyApiOptions( + import: 'MyImport', + ), + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const SwiftGenerator generator = SwiftGenerator(); + generator.generate( + const SwiftOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + + expect(code, isNot(contains('#if !os(iOS)\nimport MyImport'))); + }); + }); + group('inheritance', () { test('extends', () { final AstProxyApi api2 = AstProxyApi(