[ffigen] Added support for including/excluding/renaming unnamed_enums (#96)
* added support for including/excluding/renaming unnamed_enums
added faq, update version, changelog, update test
* fix typo
diff --git a/pkgs/ffigen/CHANGELOG.md b/pkgs/ffigen/CHANGELOG.md
index 95e0eff..6d143e5 100644
--- a/pkgs/ffigen/CHANGELOG.md
+++ b/pkgs/ffigen/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 0.3.0
+- Added support for including/excluding/renaming _un-named enums_ using key `unnamed_enums`.
+
# 0.2.4+1
- Minor changes to dylib creation error log.
diff --git a/pkgs/ffigen/README.md b/pkgs/ffigen/README.md
index 7fa1a1b..4309bfc 100644
--- a/pkgs/ffigen/README.md
+++ b/pkgs/ffigen/README.md
@@ -112,7 +112,7 @@
<td><pre lang="yaml">compiler-opts: '-I/usr/lib/llvm-9/include/'</pre></td>
</tr>
<tr>
- <td>functions<br>structs<br>enums<br>macros</td>
+ <td>functions<br>structs<br>enums<br>unnamed-enums<br>macros</td>
<td>Filters for declarations.<br><b>Default: all are included</b></td>
<td><pre lang="yaml">
functions:
@@ -181,13 +181,6 @@
</td>
<td><pre lang="yaml">dart-bool: true</pre></td>
</tr>
- <tr>
- <td>unnamed-enums</td>
- <td>Should generate constants for anonymous unnamed enums.<br>
- <b>Default: true</b>
- </td>
- <td><pre lang="yaml">unnamed-enums: true</pre></td>
- </tr>
<tr>
<td>preamble</td>
<td>Raw header of the file, pasted as-it-is.</td>
@@ -367,3 +360,23 @@
Although `dart:ffi` doesn't have a NativeType for `bool`, they can be implemented as `Uint8`.
Ffigen generates dart `bool` for function parameters and return type by default.
To disable this, and use `int` instead, set `dart-bool: false` in configurations.
+
+### How are unnamed enums handled?
+
+Unnamed enums are handled separately, under the key `unnamed-enums`, and are generated as top level constants.
+
+Here's an example that shows how to include/exclude/rename unnamed enums
+```yaml
+unnamed-enums:
+ include:
+ - 'CX_.*'
+ exclude:
+ - '.*Flag'
+ rename:
+ 'CXType_(.*)': '$1'
+```
+
+### Why are some struct declarations generated even after excluded them in config?
+
+This happens when an excluded struct is a dependency to some included declaration.
+(A dependency means a struct is being passed/returned by a function or is member of another struct in some way)
diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart
index 55ff570..ad8db21 100644
--- a/pkgs/ffigen/lib/src/config_provider/config.dart
+++ b/pkgs/ffigen/lib/src/config_provider/config.dart
@@ -43,7 +43,11 @@
Declaration get enumClassDecl => _enumClassDecl;
Declaration _enumClassDecl;
- /// Declaration config for Enums.
+ /// Declaration config for Unnamed enum constants.
+ Declaration get unnamedEnumConstants => _unnamedEnumConstants;
+ Declaration _unnamedEnumConstants;
+
+ /// Declaration config for Macro constants.
Declaration get macroDecl => _macroDecl;
Declaration _macroDecl;
@@ -66,10 +70,6 @@
bool get arrayWorkaround => _arrayWorkaround;
bool _arrayWorkaround;
- /// If constants should be generated for unnamed enums.
- bool get unnamedEnums => _unnamedEnums;
- bool _unnamedEnums;
-
/// If dart bool should be generated for C booleans.
bool get dartBool => _dartBool;
bool _dartBool;
@@ -193,6 +193,14 @@
_enumClassDecl = result as Declaration;
},
),
+ strings.unnamedEnums: Specification<Declaration>(
+ requirement: Requirement.no,
+ validator: declarationConfigValidator,
+ extractor: declarationConfigExtractor,
+ defaultValue: () => Declaration(),
+ extractedResult: (dynamic result) =>
+ _unnamedEnumConstants = result as Declaration,
+ ),
strings.macros: Specification<Declaration>(
requirement: Requirement.no,
validator: declarationConfigValidator,
@@ -245,13 +253,6 @@
defaultValue: () => false,
extractedResult: (dynamic result) => _arrayWorkaround = result as bool,
),
- strings.unnamedEnums: Specification<bool>(
- requirement: Requirement.no,
- validator: booleanValidator,
- extractor: booleanExtractor,
- defaultValue: () => true,
- extractedResult: (dynamic result) => _unnamedEnums = result as bool,
- ),
strings.dartBool: Specification<bool>(
requirement: Requirement.no,
validator: booleanValidator,
diff --git a/pkgs/ffigen/lib/src/header_parser/includer.dart b/pkgs/ffigen/lib/src/header_parser/includer.dart
index 5c534a7..5c8775b 100644
--- a/pkgs/ffigen/lib/src/header_parser/includer.dart
+++ b/pkgs/ffigen/lib/src/header_parser/includer.dart
@@ -40,6 +40,17 @@
}
}
+bool shouldIncludeUnnamedEnumConstant(String usr, String name) {
+ if (bindingsIndex.isSeenUnnamedEnumConstant(usr) || name == '') {
+ return false;
+ } else if (config.unnamedEnumConstants == null ||
+ config.unnamedEnumConstants.shouldInclude(name)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
bool shouldIncludeMacro(String usr, String name) {
if (bindingsIndex.isSeenMacro(usr) || name == '') {
return false;
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
index 49e4b1a..06ce225 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -36,8 +36,7 @@
final enumName = name ?? cursor.spelling();
if (enumName == '') {
// Save this unnamed enum if it is anonymous (therefore not in a typedef).
- if (config.unnamedEnums &&
- clang.clang_Cursor_isAnonymous_wrap(cursor) != 0) {
+ if (clang.clang_Cursor_isAnonymous_wrap(cursor) != 0) {
_logger.fine('Saving anonymous enum.');
saveUnNamedEnum(cursor);
} else {
diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
index 729f791..4c1e244 100644
--- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
+++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -6,6 +6,7 @@
import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/header_parser/data.dart';
+import 'package:ffigen/src/header_parser/includer.dart';
import 'package:logging/logging.dart';
import '../clang_bindings/clang_bindings.dart' as clang_types;
@@ -37,7 +38,9 @@
.finest(' unnamedenumCursorVisitor: ${cursor.completeStringRepr()}');
switch (clang.clang_getCursorKind_wrap(cursor)) {
case clang_types.CXCursorKind.CXCursor_EnumConstantDecl:
- _addUnNamedEnumConstant(cursor);
+ if (shouldIncludeUnnamedEnumConstant(cursor.usr(), cursor.spelling())) {
+ _addUnNamedEnumConstant(cursor);
+ }
break;
default:
_logger.severe('Invalid enum constant.');
@@ -58,8 +61,7 @@
Constant(
usr: cursor.usr(),
originalName: cursor.spelling(),
- name: config.enumClassDecl.renameMemberUsingConfig(
- '', // Un-named enum constants have an empty declaration name.
+ name: config.unnamedEnumConstants.renameUsingConfig(
cursor.spelling(),
),
rawType: 'int',
diff --git a/pkgs/ffigen/lib/src/header_parser/utils.dart b/pkgs/ffigen/lib/src/header_parser/utils.dart
index d578b00..171113d 100644
--- a/pkgs/ffigen/lib/src/header_parser/utils.dart
+++ b/pkgs/ffigen/lib/src/header_parser/utils.dart
@@ -340,6 +340,7 @@
final Map<String, Struc> _structs = {};
final Map<String, Func> _functions = {};
final Map<String, EnumClass> _enumClass = {};
+ final Map<String, Constant> _unnamedEnumConstants = {};
final Map<String, String> _macros = {};
// Stores only named typedefC used in NativeFunc.
final Map<String, Typedef> _functionTypedefs = {};
@@ -380,6 +381,18 @@
return _enumClass[usr];
}
+ bool isSeenUnnamedEnumConstant(String usr) {
+ return _unnamedEnumConstants.containsKey(usr);
+ }
+
+ void addUnnamedEnumConstantToSeen(String usr, Constant enumConstant) {
+ _unnamedEnumConstants[usr] = enumConstant;
+ }
+
+ Constant getSeenUnnamedEnumConstant(String usr) {
+ return _unnamedEnumConstants[usr];
+ }
+
bool isSeenMacro(String usr) {
return _macros.containsKey(usr);
}
diff --git a/pkgs/ffigen/lib/src/strings.dart b/pkgs/ffigen/lib/src/strings.dart
index 0749dbe..2cd2697 100644
--- a/pkgs/ffigen/lib/src/strings.dart
+++ b/pkgs/ffigen/lib/src/strings.dart
@@ -40,6 +40,7 @@
const functions = 'functions';
const structs = 'structs';
const enums = 'enums';
+const unnamedEnums = 'unnamed-enums';
const macros = 'macros';
// Sub-fields of Declarations.
@@ -82,7 +83,6 @@
const useSupportedTypedefs = 'use-supported-typedefs';
const warnWhenRemoving = 'warn-when-removing';
const arrayWorkaround = 'array-workaround';
-const unnamedEnums = 'unnamed-enums';
const dartBool = 'dart-bool';
const comments = 'comments';
diff --git a/pkgs/ffigen/pubspec.yaml b/pkgs/ffigen/pubspec.yaml
index ae53603..7aa1133 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: 0.2.4+1
+version: 0.3.0
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/unnamed_enums.h b/pkgs/ffigen/test/header_parser_tests/unnamed_enums.h
index ecb4a85..8b64555 100644
--- a/pkgs/ffigen/test/header_parser_tests/unnamed_enums.h
+++ b/pkgs/ffigen/test/header_parser_tests/unnamed_enums.h
@@ -1,7 +1,7 @@
// Only this should be parsed.
enum{
A=1,
- B=2,
+ B=2, // This will be excluded by config.
C=3
};
diff --git a/pkgs/ffigen/test/header_parser_tests/unnamed_enums_test.dart b/pkgs/ffigen/test/header_parser_tests/unnamed_enums_test.dart
index 99456f3..fa75392 100644
--- a/pkgs/ffigen/test/header_parser_tests/unnamed_enums_test.dart
+++ b/pkgs/ffigen/test/header_parser_tests/unnamed_enums_test.dart
@@ -29,6 +29,9 @@
${strings.enums}:
${strings.exclude}:
- Named
+${strings.unnamedEnums}:
+ ${strings.exclude}:
+ - B
''') as yaml.YamlMap),
);
});
@@ -39,7 +42,6 @@
test('Parse unnamed enum Values', () {
expect(actual.getBindingAsString('A'), expected.getBindingAsString('A'));
- expect(actual.getBindingAsString('B'), expected.getBindingAsString('B'));
expect(actual.getBindingAsString('C'), expected.getBindingAsString('C'));
});
@@ -64,11 +66,6 @@
rawValue: '1',
),
Constant(
- name: 'B',
- rawType: 'int',
- rawValue: '2',
- ),
- Constant(
name: 'C',
rawType: 'int',
rawValue: '3',
diff --git a/pkgs/ffigen/test/rename_tests/rename_test.dart b/pkgs/ffigen/test/rename_tests/rename_test.dart
index c3425cc..962e545 100644
--- a/pkgs/ffigen/test/rename_tests/rename_test.dart
+++ b/pkgs/ffigen/test/rename_tests/rename_test.dart
@@ -63,9 +63,11 @@
'MemberRenameEnum4':
'_(.*)': '\$1'
'fullMatch': 'fullMatchSuccess'
- '':
- '_(.*)': '\$1'
- 'unnamedFullMatch': 'unnamedFullMatchSuccess'
+
+unnamed-enums:
+ ${strings.rename}:
+ '_(.*)': '\$1'
+ 'unnamedFullMatch': 'unnamedFullMatchSuccess'
macros:
${strings.rename}: