[ffigen] Skip inline functions (#147) (#167)

diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md
index e877eb7..9a3cbb6 100644
--- a/pkgs/ffigen/CHANGELOG.md
+++ b/pkgs/ffigen/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 2.0.0-dev.6
+- Functions marked `inline` are now skipped.
+
 # 2.0.0-dev.5
 - Use `Opaque` for representing empty `Struct`s.
 
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 a68621e..b834217 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
@@ -510,6 +510,21 @@
 
   _dart_clang_Cursor_isMacroBuiltin? _clang_Cursor_isMacroBuiltin;
 
+  /// Determine whether a  CXCursor that is a function declaration, is an
+  /// inline declaration.
+  int clang_Cursor_isFunctionInlined(
+    CXCursor C,
+  ) {
+    return (_clang_Cursor_isFunctionInlined ??= _dylib.lookupFunction<
+            _c_clang_Cursor_isFunctionInlined,
+            _dart_clang_Cursor_isFunctionInlined>(
+        'clang_Cursor_isFunctionInlined'))(
+      C,
+    );
+  }
+
+  _dart_clang_Cursor_isFunctionInlined? _clang_Cursor_isFunctionInlined;
+
   /// For pointer types, returns the type of the pointee.
   CXType clang_getPointeeType(
     CXType T,
@@ -2563,6 +2578,14 @@
   CXCursor C,
 );
 
+typedef _c_clang_Cursor_isFunctionInlined = ffi.Uint32 Function(
+  CXCursor C,
+);
+
+typedef _dart_clang_Cursor_isFunctionInlined = int Function(
+  CXCursor C,
+);
+
 typedef _c_clang_getPointeeType = CXType Function(
   CXType T,
 );
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
index 7bf089a..ccfcb21 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/functiondecl_parser.dart
@@ -35,6 +35,16 @@
     final rt = _getFunctionReturnType(cursor);
     final parameters = _getParameters(cursor, funcName);
 
+    if (clang.clang_Cursor_isFunctionInlined(cursor) != 0) {
+      _logger.fine(
+          '---- Removed Function, reason: inline function: ${cursor.completeStringRepr()}');
+      _logger.warning(
+          "Skipped Function '$funcName', inline functions are not supported.");
+      return _stack
+          .pop()
+          .func; // Returning null so that [addToBindings] function excludes this.
+    }
+
     if (rt.isIncompleteStruct || _stack.top.incompleteStructParameter) {
       _logger.fine(
           '---- Removed Function, reason: Incomplete struct pass/return by value: ${cursor.completeStringRepr()}');
diff --git a/pkgs/ffigen/pubspec.yaml b/pkgs/ffigen/pubspec.yaml
index cb13584..e8501c0 100644
--- a/pkgs/ffigen/pubspec.yaml
+++ b/pkgs/ffigen/pubspec.yaml
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: ffigen
-version: 2.0.0-dev.5
+version: 2.0.0-dev.6
 homepage: https://github.com/dart-lang/ffigen
 description: Experimental generator for FFI bindings, using LibClang to parse C header files.
 
diff --git a/pkgs/ffigen/test/header_parser_tests/functions.h b/pkgs/ffigen/test/header_parser_tests/functions.h
index 5c00b33..56ec2be 100644
--- a/pkgs/ffigen/test/header_parser_tests/functions.h
+++ b/pkgs/ffigen/test/header_parser_tests/functions.h
@@ -16,3 +16,6 @@
 typedef void shortHand(void(b)());
 // Would be treated as `void func5(shortHand *a, void (*b)())`.
 void func5(shortHand a, void(b)());
+
+// Should be skipped as inline functions are not supported.
+static inline void inlineFunc();
diff --git a/pkgs/ffigen/test/header_parser_tests/functions_test.dart b/pkgs/ffigen/test/header_parser_tests/functions_test.dart
index 31e0506..c02905d 100644
--- a/pkgs/ffigen/test/header_parser_tests/functions_test.dart
+++ b/pkgs/ffigen/test/header_parser_tests/functions_test.dart
@@ -58,6 +58,11 @@
       expect(actual.getBindingAsString('func5'),
           expected.getBindingAsString('func5'));
     });
+
+    test('Skip inline functions', () {
+      expect(() => actual.getBindingAsString('inlineFunc'),
+          throwsA(TypeMatcher<NotFoundException>()));
+    });
   });
 }
 
diff --git a/pkgs/ffigen/tool/libclang_config.yaml b/pkgs/ffigen/tool/libclang_config.yaml
index 2a059dd..c27f17c 100644
--- a/pkgs/ffigen/tool/libclang_config.yaml
+++ b/pkgs/ffigen/tool/libclang_config.yaml
@@ -101,3 +101,4 @@
     - clang_Cursor_isAnonymousRecordDecl
     - clang_getCursorUSR
     - clang_getFieldDeclBitWidth
+    - clang_Cursor_isFunctionInlined