[pigeon] added macos swift support (#2587)

diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index 057857e..71f7162 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.0.3
+
+* [swift] Makes swift output work on macOS.
+
 ## 4.0.2
 
 * Fixes lint warnings.
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index 3c89473..a0607a9 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -9,7 +9,7 @@
 import 'ast.dart';
 
 /// The current version of pigeon. This must match the version in pubspec.yaml.
-const String pigeonVersion = '4.0.2';
+const String pigeonVersion = '4.0.3';
 
 /// 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 43e2eef..aaff9ee 100644
--- a/packages/pigeon/lib/swift_generator.dart
+++ b/packages/pigeon/lib/swift_generator.dart
@@ -421,7 +421,15 @@
 
   void writeImports() {
     indent.writeln('import Foundation');
-    indent.writeln('import Flutter');
+    indent.format('''
+#if os(iOS)
+import Flutter
+#elseif os(macOS)
+import FlutterMacOS
+#else
+#error("Unsupported platform.")
+#endif
+''');
   }
 
   void writeEnum(Enum anEnum) {
diff --git a/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Classes/MacosSwiftUnitTestsPlugin.swift b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Classes/MacosSwiftUnitTestsPlugin.swift
new file mode 100644
index 0000000..640df72
--- /dev/null
+++ b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Classes/MacosSwiftUnitTestsPlugin.swift
@@ -0,0 +1,19 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import Cocoa
+import FlutterMacOS
+
+public class MyApi: Api {
+  public init() {}
+  func getPlatform() -> String {
+    return "macOS " + ProcessInfo.processInfo.operatingSystemVersionString
+  }
+}
+
+public class MacosSwiftUnitTestsPlugin: NSObject, FlutterPlugin {
+  public static func register(with registrar: FlutterPluginRegistrar) {
+    ApiSetup.setUp(binaryMessenger: registrar.messenger, api: MyApi())
+  }
+}
diff --git a/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Tests/MessagesTest.swift b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Tests/MessagesTest.swift
new file mode 100644
index 0000000..d877c0b
--- /dev/null
+++ b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/Tests/MessagesTest.swift
@@ -0,0 +1,13 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import XCTest
+import macos_swift_unit_tests
+
+class MessagesTest: XCTestCase {
+   func testMakeApi() {
+    let api = MyApi()
+    XCTAssertNotNil(api)
+   }
+}
diff --git a/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/macos_swift_unit_tests.podspec b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/macos_swift_unit_tests.podspec
new file mode 100644
index 0000000..bfecf1f
--- /dev/null
+++ b/packages/pigeon/platform_tests/macos_swift_unit_tests/macos/macos_swift_unit_tests.podspec
@@ -0,0 +1,29 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
+# Run `pod lib lint macos_swift_unit_tests.podspec` to validate before publishing.
+#
+Pod::Spec.new do |s|
+  s.name             = 'macos_swift_unit_tests'
+  s.version          = '0.0.1'
+  s.summary          = 'Fake library that uses pigeon for macos for testing.'
+  s.description      = <<-DESC
+Fake library that uses pigeon for macos for testing.
+
+Use `pod lib lint` to run the tests.
+                       DESC
+  s.homepage         = 'http://example.com'
+  s.license          = { :type => 'Flutter', :file => '../../../LICENSE' }
+  s.author           = { 'Your Company' => 'email@example.com' }
+
+  s.source           = { :http => 'https://github.com/flutter/packages' }
+  s.source_files     = 'Classes/**/*'
+  s.dependency 'FlutterMacOS'
+
+  s.platform = :osx, '10.11'
+  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
+  s.swift_version = '5.0'
+
+  s.test_spec 'Tests' do |test_spec|
+    test_spec.source_files = 'Tests/*.{swift}'
+  end
+end
diff --git a/packages/pigeon/platform_tests/macos_swift_unit_tests/pigeons/messages.dart b/packages/pigeon/platform_tests/macos_swift_unit_tests/pigeons/messages.dart
new file mode 100644
index 0000000..4fe745f
--- /dev/null
+++ b/packages/pigeon/platform_tests/macos_swift_unit_tests/pigeons/messages.dart
@@ -0,0 +1,10 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:pigeon/pigeon.dart';
+
+@HostApi()
+abstract class Api {
+  String getPlatform();
+}
diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml
index 984a5e7..d677d9e 100644
--- a/packages/pigeon/pubspec.yaml
+++ b/packages/pigeon/pubspec.yaml
@@ -2,7 +2,7 @@
 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%3Apigeon
-version: 4.0.2 # This must match the version in lib/generator_tools.dart
+version: 4.0.3 # This must match the version in lib/generator_tools.dart
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/pigeon/run_tests.sh b/packages/pigeon/run_tests.sh
index 2b575f6..1df123b 100755
--- a/packages/pigeon/run_tests.sh
+++ b/packages/pigeon/run_tests.sh
@@ -191,6 +191,10 @@
   dart run tool/run_tests.dart -t mock_handler_tests
 }
 
+run_macos_swift_unittests() {
+  dart run tool/run_tests.dart -t mac_swift_unittests
+}
+
 run_dart_compilation_tests() {
   local temp_dir=$(mktmpdir)
   local flutter_project_dir=$temp_dir/project
@@ -311,6 +315,7 @@
 should_run_ios_e2e_tests=true
 should_run_ios_unittests=true
 should_run_mock_handler_tests=true
+should_run_macos_swift_unittests=true
 while getopts "t:l?h" opt; do
   case $opt in
   t)
@@ -321,6 +326,7 @@
     should_run_ios_e2e_tests=false
     should_run_ios_unittests=false
     should_run_mock_handler_tests=false
+    should_run_macos_swift_unittests=false
     case $OPTARG in
     android_unittests) should_run_android_unittests=true ;;
     dart_compilation_tests) should_run_dart_compilation_tests=true ;;
@@ -329,6 +335,7 @@
     ios_e2e_tests) should_run_ios_e2e_tests=true ;;
     ios_unittests) should_run_ios_unittests=true ;;
     mock_handler_tests) should_run_mock_handler_tests=true ;;
+    macos_swift_unittests) should_run_macos_swift_unittests=true ;;
     *)
       echo "unrecognized test: $OPTARG"
       exit 1
@@ -344,6 +351,7 @@
   ios_e2e_tests          - End-to-end objc tests run on iOS Simulator
   ios_unittests          - Unit tests on generated Objc code.
   mock_handler_tests     - Unit tests on generated Dart mock handler code.
+  macos_swift_unittests  - Unit tests on generated Swift code on macOS.
   "
     exit 1
     ;;
@@ -390,3 +398,6 @@
 if [ "$should_run_android_unittests" = true ]; then
   run_android_unittests
 fi
+if [ "$should_run_macos_swift_unittests" = true ]; then
+  run_macos_swift_unittests
+fi
diff --git a/packages/pigeon/tool/run_tests.dart b/packages/pigeon/tool/run_tests.dart
index cfb742b..3eb5833 100644
--- a/packages/pigeon/tool/run_tests.dart
+++ b/packages/pigeon/tool/run_tests.dart
@@ -9,7 +9,16 @@
 ///
 /// usage: dart run tool/run_tests.dart
 ////////////////////////////////////////////////////////////////////////////////
-import 'dart:io' show File, Platform, Process, exit, stderr, stdout;
+import 'dart:io'
+    show
+        Directory,
+        File,
+        Platform,
+        Process,
+        ProcessResult,
+        exit,
+        stderr,
+        stdout;
 import 'package:args/args.dart';
 import 'package:meta/meta.dart';
 import 'package:pigeon/functional.dart';
@@ -49,6 +58,9 @@
   'ios_swift_unittests': _TestInfo(
       function: _runIosSwiftUnitTests,
       description: 'Unit tests on generated Swift code.'),
+  'mac_swift_unittests': _TestInfo(
+      function: _runMacOSSwiftUnitTests,
+      description: 'Unit tests on generated Swift code on macOS.'),
   'mock_handler_tests': _TestInfo(
       function: _runMockHandlerTests,
       description: 'Unit tests on generated Dart mock handler code.'),
@@ -190,6 +202,31 @@
   throw UnimplementedError('See run_tests.sh.');
 }
 
+Future<int> _runMacOSSwiftUnitTests() async {
+  const String macosSwiftUnitTestsPath =
+      './platform_tests/macos_swift_unit_tests';
+  final int generateCode = await _runPigeon(
+    input: '$macosSwiftUnitTestsPath/pigeons/messages.dart',
+    iosSwiftOut: '$macosSwiftUnitTestsPath/macos/Classes/messages.g.swift',
+  );
+  if (generateCode != 0) {
+    return generateCode;
+  }
+  final Directory oldCwd = Directory.current;
+  try {
+    Directory.current = Directory('$macosSwiftUnitTestsPath/macos');
+    final ProcessResult lintResult =
+        Process.runSync('pod', <String>['lib', 'lint']);
+    if (lintResult.exitCode != 0) {
+      return lintResult.exitCode;
+    }
+  } finally {
+    Directory.current = oldCwd;
+  }
+
+  return 0;
+}
+
 Future<int> _runIosSwiftUnitTests() async {
   const String iosSwiftUnitTestsPath = './platform_tests/ios_swift_unit_tests';
   const List<String> tests = <String>[