Fix missing typedef dependencies (#90)
* Fix missing typedef dependencies of func and struct
* added tests
* update version, changelog
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f496c70..5db8023 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 0.2.3+1
+- Fixed missing typedefs of nested function pointers.
+
# 0.2.3
- Fixed parsing structs with bitfields, all members of structs with bit field members will now be removed. See [#84](https://github.com/dart-lang/ffigen/issues/84)
diff --git a/lib/src/code_generator/binding.dart b/lib/src/code_generator/binding.dart
index b4267b8..4f24d58 100644
--- a/lib/src/code_generator/binding.dart
+++ b/lib/src/code_generator/binding.dart
@@ -31,7 +31,7 @@
});
/// Return typedef dependencies.
- List<Typedef> getTypedefDependencies(Writer w);
+ List<Typedef> getTypedefDependencies(Writer w) => const [];
/// Converts a Binding to its actual string representation.
///
diff --git a/lib/src/code_generator/constant.dart b/lib/src/code_generator/constant.dart
index 41572ab..617f2d7 100644
--- a/lib/src/code_generator/constant.dart
+++ b/lib/src/code_generator/constant.dart
@@ -2,7 +2,6 @@
// for details. 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:ffigen/src/code_generator/typedef.dart';
import 'package:meta/meta.dart';
import 'binding.dart';
@@ -58,7 +57,4 @@
return BindingString(
type: BindingStringType.constant, string: s.toString());
}
-
- @override
- List<Typedef> getTypedefDependencies(Writer w) => const [];
}
diff --git a/lib/src/code_generator/enum_class.dart b/lib/src/code_generator/enum_class.dart
index 9404c4b..867133a 100644
--- a/lib/src/code_generator/enum_class.dart
+++ b/lib/src/code_generator/enum_class.dart
@@ -2,7 +2,6 @@
// for details. 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:ffigen/src/code_generator/typedef.dart';
import 'package:meta/meta.dart';
import 'binding.dart';
@@ -71,9 +70,6 @@
return BindingString(
type: BindingStringType.enumClass, string: s.toString());
}
-
- @override
- List<Typedef> getTypedefDependencies(Writer w) => const [];
}
/// Represents a single value in an enum.
diff --git a/lib/src/code_generator/func.dart b/lib/src/code_generator/func.dart
index d29abcb..c1f444b 100644
--- a/lib/src/code_generator/func.dart
+++ b/lib/src/code_generator/func.dart
@@ -66,14 +66,15 @@
// Add typedef's required by return type.
final returnTypeBase = returnType.getBaseType();
if (returnTypeBase.broadType == BroadType.NativeFunction) {
- _typedefDependencies.add(returnTypeBase.nativeFunc);
+ _typedefDependencies
+ .addAll(returnTypeBase.nativeFunc.getDependencies());
}
// Add typedef's required by parameters.
for (final p in parameters) {
final base = p.type.getBaseType();
if (base.broadType == BroadType.NativeFunction) {
- _typedefDependencies.add(base.nativeFunc);
+ _typedefDependencies.addAll(base.nativeFunc.getDependencies());
}
}
// Add C function typedef.
diff --git a/lib/src/code_generator/global.dart b/lib/src/code_generator/global.dart
index 79478fa..817844d 100644
--- a/lib/src/code_generator/global.dart
+++ b/lib/src/code_generator/global.dart
@@ -2,7 +2,6 @@
// for details. 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:ffigen/src/code_generator/typedef.dart';
import 'package:meta/meta.dart';
import 'binding.dart';
@@ -54,7 +53,4 @@
return BindingString(type: BindingStringType.global, string: s.toString());
}
-
- @override
- List<Typedef> getTypedefDependencies(Writer w) => const [];
}
diff --git a/lib/src/code_generator/struc.dart b/lib/src/code_generator/struc.dart
index 8cd6df3..a17649b 100644
--- a/lib/src/code_generator/struc.dart
+++ b/lib/src/code_generator/struc.dart
@@ -72,7 +72,7 @@
for (final m in members) {
final base = m.type.getBaseType();
if (base.broadType == BroadType.NativeFunction) {
- _typedefDependencies.add(base.nativeFunc);
+ _typedefDependencies.addAll(base.nativeFunc.getDependencies());
}
}
}
diff --git a/lib/src/code_generator/typedef.dart b/lib/src/code_generator/typedef.dart
index 0cf7f84..e0c3c7a 100644
--- a/lib/src/code_generator/typedef.dart
+++ b/lib/src/code_generator/typedef.dart
@@ -38,6 +38,19 @@
List<Parameter> parameters,
}) : parameters = parameters ?? [];
+ /// Returns the [Typedef] dependencies required by this typedef including itself.
+ List<Typedef> getDependencies() {
+ final dep = <Typedef>[];
+ for (final p in parameters) {
+ final base = p.type.getBaseType();
+ if (base.broadType == BroadType.NativeFunction) {
+ dep.addAll(base.nativeFunc.getDependencies());
+ }
+ }
+ dep.add(this);
+ return dep;
+ }
+
String toTypedefString(Writer w) {
final s = StringBuffer();
if (dartDoc != null) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 9695da5..f87d8eb 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
name: ffigen
-version: 0.2.3
+version: 0.2.3+1
homepage: https://github.com/dart-lang/ffigen
description: Experimental generator for FFI bindings, using LibClang to parse C/C++ header files.
diff --git a/test/header_parser_tests/native_func_typedef.h b/test/header_parser_tests/native_func_typedef.h
new file mode 100644
index 0000000..38551e9
--- /dev/null
+++ b/test/header_parser_tests/native_func_typedef.h
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+struct struc
+{
+ void (*unnamed1)(void (*unnamed2)());
+};
+
+void func(void (*unnamed1)(void (*unnamed2)()));
diff --git a/test/header_parser_tests/native_func_typedef_test.dart b/test/header_parser_tests/native_func_typedef_test.dart
new file mode 100644
index 0000000..c2826d4
--- /dev/null
+++ b/test/header_parser_tests/native_func_typedef_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser.dart' as parser;
+import 'package:ffigen/src/config_provider.dart';
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart' as yaml;
+import 'package:ffigen/src/strings.dart' as strings;
+
+import '../test_utils.dart';
+
+Library actual;
+void main() {
+ group('unnamed_enums_test', () {
+ setUpAll(() {
+ logWarnings();
+ actual = parser.parse(
+ Config.fromYaml(yaml.loadYaml('''
+${strings.name}: 'NativeLibrary'
+${strings.description}: 'Unnamed Enums Test'
+${strings.output}: 'unused'
+${strings.headers}:
+ ${strings.entryPoints}:
+ - 'test/header_parser_tests/native_func_typedef.h'
+ ''') as yaml.YamlMap),
+ );
+ });
+
+ test('Expected bindings', () {
+ final gen = actual.generate();
+ // Writing to file for debug purpose.
+ final file =
+ File('test/debug_generated/native_func_typedef_test-output.dart');
+
+ try {
+ expect(gen, '''// AUTO GENERATED FILE, DO NOT EDIT.
+//
+// Generated by `package:ffigen`.
+import 'dart:ffi' as ffi;
+
+/// Unnamed Enums Test
+class NativeLibrary{
+/// Holds the Dynamic library.
+final ffi.DynamicLibrary _dylib;
+
+/// The symbols are looked up in [dynamicLibrary].
+NativeLibrary(ffi.DynamicLibrary dynamicLibrary): _dylib = dynamicLibrary;
+
+void func(
+ ffi.Pointer<ffi.NativeFunction<_typedefC_4>> unnamed1,
+) {
+_func ??= _dylib.lookupFunction<_c_func,_dart_func>('func');
+ return _func(
+ unnamed1,
+ );
+}
+_dart_func _func;
+
+}
+
+class struc extends ffi.Struct{
+ ffi.Pointer<ffi.NativeFunction<_typedefC_2>> unnamed1;
+
+}
+
+typedef _typedefC_3 = ffi.Void Function(
+);
+
+typedef _typedefC_4 = ffi.Void Function(
+ ffi.Pointer<ffi.NativeFunction<_typedefC_3>> ,
+);
+
+typedef _c_func = ffi.Void Function(
+ ffi.Pointer<ffi.NativeFunction<_typedefC_4>> unnamed1,
+);
+
+typedef _dart_func = void Function(
+ ffi.Pointer<ffi.NativeFunction<_typedefC_4>> unnamed1,
+);
+
+typedef _typedefC_1 = ffi.Void Function(
+);
+
+typedef _typedefC_2 = ffi.Void Function(
+ ffi.Pointer<ffi.NativeFunction<_typedefC_1>> ,
+);
+
+''');
+ if (file.existsSync()) {
+ file.delete();
+ }
+ } catch (e) {
+ file.writeAsStringSync(gen);
+ print('Failed test, Debug output: ${file.absolute?.path}');
+ rethrow;
+ }
+ });
+ });
+}