[ffigen] Fix mac bot (#466)

diff --git a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
index e8755f5..8185f34 100644
--- a/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ b/pkgs/ffigen/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -1176,6 +1176,17 @@
   late final _clang_getCursorKindSpelling =
       _clang_getCursorKindSpellingPtr.asFunction<CXString Function(int)>();
 
+  /// Return a version string, suitable for showing to a user, but not
+  /// intended to be parsed (the format is not guaranteed to be stable).
+  CXString clang_getClangVersion() {
+    return _clang_getClangVersion();
+  }
+
+  late final _clang_getClangVersionPtr =
+      _lookup<ffi.NativeFunction<CXString Function()>>('clang_getClangVersion');
+  late final _clang_getClangVersion =
+      _clang_getClangVersionPtr.asFunction<CXString Function()>();
+
   /// If cursor is a statement declaration tries to evaluate the
   /// statement and if its variable, tries to evaluate its initializer,
   /// into its corresponding type.
diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart
index 1638951..d789b81 100644
--- a/pkgs/ffigen/test/large_integration_tests/large_test.dart
+++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart
@@ -52,6 +52,10 @@
         library,
         ['test', 'debug_generated', 'large_test_libclang.dart'],
         ['test', 'large_integration_tests', '_expected_libclang_bindings.dart'],
+        // Remove comments containing @ to hack around a mismatch in the
+        // documentation generated by different clang versions.
+        codeNormalizer: (code) =>
+            code.replaceAll(RegExp('[^\n]*///[^\n]*@[^\n]*\n'), ''),
       );
     });
 
diff --git a/pkgs/ffigen/test/native_objc_test/swift_class_test.dart b/pkgs/ffigen/test/native_objc_test/swift_class_test_.dart
similarity index 100%
rename from pkgs/ffigen/test/native_objc_test/swift_class_test.dart
rename to pkgs/ffigen/test/native_objc_test/swift_class_test_.dart
diff --git a/pkgs/ffigen/test/test_utils.dart b/pkgs/ffigen/test/test_utils.dart
index 314f8aa..bc12c64 100644
--- a/pkgs/ffigen/test/test_utils.dart
+++ b/pkgs/ffigen/test/test_utils.dart
@@ -40,21 +40,30 @@
   }
 }
 
+// Remove '\r' for Windows compatibility, then apply user's normalizer.
+String _normalizeGeneratedCode(
+    String generated, String Function(String)? codeNormalizer) {
+  final noCR = generated.replaceAll('\r', '');
+  if (codeNormalizer == null) return noCR;
+  return codeNormalizer(noCR);
+}
+
 /// Generates actual file using library and tests using [expect] with expected
 ///
 /// This will not delete the actual debug file incase [expect] throws an error.
 void matchLibraryWithExpected(
-    Library library, List<String> pathForActual, List<String> pathToExpected) {
+    Library library, List<String> pathForActual, List<String> pathToExpected,
+    {String Function(String)? codeNormalizer}) {
   final file = File(
     path.joinAll(pathForActual),
   );
   library.generateFile(file);
 
   try {
-    final actual = file.readAsStringSync().replaceAll('\r', '');
-    final expected = File(path.joinAll(pathToExpected))
-        .readAsStringSync()
-        .replaceAll('\r', '');
+    final actual =
+        _normalizeGeneratedCode(file.readAsStringSync(), codeNormalizer);
+    final expected = _normalizeGeneratedCode(
+        File(path.joinAll(pathToExpected)).readAsStringSync(), codeNormalizer);
     expect(actual, expected);
     if (file.existsSync()) {
       file.delete();
diff --git a/pkgs/ffigen/tool/libclang_config.yaml b/pkgs/ffigen/tool/libclang_config.yaml
index 3087cf8..79cbbd6 100644
--- a/pkgs/ffigen/tool/libclang_config.yaml
+++ b/pkgs/ffigen/tool/libclang_config.yaml
@@ -118,3 +118,4 @@
     - clang_Cursor_getObjCPropertySetterName
     - clang_Type_getNullability
     - clang_Location_isInSystemHeader
+    - clang_getClangVersion