From 07715cd8281388e493daea4402d67549c008888c Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Tue, 11 Nov 2025 14:13:17 +1100 Subject: [PATCH] [ffigen] Improve docs of config API Fixes https://github.com/dart-lang/native/issues/2769 --- .../lib/src/config_provider/config.dart | 91 +++++++++++++++---- .../lib/src/config_provider/config_types.dart | 19 ++++ 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 6afc39538..5dff06d75 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -139,7 +139,7 @@ final class Headers { static bool _includeDefault(Uri header) => true; - /// CommandLine Arguments to pass to clang_compiler. + /// Command line arguments to pass to clang_compiler. final List? compilerOptions; /// Where to ignore compiler warnings/errors in source header files. @@ -155,30 +155,66 @@ final class Headers { /// Configuration for declarations. final class Declarations { - /// Checks if a name is allowed by a filter. + /// Whether to include the given declaration. + /// + /// ```dart + /// // This includes `Foo`, and nothing else: + /// include: (Declaration decl) => decl.originalName == 'Foo' + /// ``` final bool Function(Declaration declaration) include; - /// Whether a member of a declaration should be included. + /// Whether the member of the declaration should be included. /// /// Only used for [Categories], [Interfaces], and [Protocols] methods and - /// properties. + /// properties. For Objective-C methods, this is the method selector, eg + /// `"arrayWithObjects:count:"`. + /// + /// Note that using [includeMember] to include a member of a class doesn't + /// affect whether the class is included. You'll also need to set [include] + /// for the class (this will be fixed in a future version of the API). + /// + /// ```dart + /// // This includes `Foo.bar`, and no other methods of `Foo`: + /// includeMember: (Declaration declaration, String member) => + /// ``` + // TODO(https://github.com/dart-lang/native/issues/2770): Merge with include. final bool Function(Declaration declaration, String member) includeMember; static bool _includeAllMembers(Declaration declaration, String member) => true; - /// Checks if the symbol address should be included for this name. + /// Whether the symbol address should be exposed for this declaration. + /// + /// The address is exposed as an FFI pointer. final bool Function(Declaration declaration) includeSymbolAddress; - /// Applies renaming and returns the result. + /// Returns a new name for the declaration, to replace its `originalName`. + /// + /// ```dart + /// // This renames `Foo` to `Bar`, and nothing else: + /// rename: (Declaration decl) => + /// decl.originalName == 'Foo' ? 'Bar' : decl.originalName + /// ``` final String Function(Declaration declaration) rename; static String _useOriginalName(Declaration declaration) => declaration.originalName; - /// Applies member renaming and returns the result. Used for struct/union - /// fields, enum elements, function params, and ObjC - /// interface/protocol/category methods/properties. + /// Returns a new name for the member of the declaration, to replace its + /// `originalName`. + /// + /// Used for struct/union fields, enum elements, function params, and + /// Objective-C interface/protocol/category methods/properties. + /// + /// ```dart + /// // This renames `Foo.bar` to `Foo.baz`, and nothing else: + /// rename: (Declaration decl, String member) { + /// if (decl.originalName == 'Foo' && member == 'baz') { + /// return 'baz'; + /// } + /// return member; + /// } + /// ``` final String Function(Declaration declaration, String member) renameMember; static String _useMemberOriginalName( @@ -200,8 +236,18 @@ final class Enums extends Declarations { /// The [EnumStyle] to use for the given enum declaration. /// /// The `suggestedStyle` is a suggested [EnumStyle] based on the declaration - /// of the enum, if any. For example, ObjC enums declared using NS_OPTIONS - /// are suggested to use [EnumStyle.intConstants]. + /// of the enum, if any. For example, Objective-C enums declared using + /// NS_OPTIONS are suggested to use [EnumStyle.intConstants]. + /// + /// ```dart + /// // This uses `intConstants` for `Foo`, and the default style otherwise: + /// style: (Declaration decl, EnumStyle? suggestedStyle) { + /// if (decl.originalName == 'Foo') { + /// return EnumStyle.intConstants; + /// } + /// return suggestedStyle ?? EnumStyle.dartEnum; + /// } + /// ``` final EnumStyle Function(Declaration declaration, EnumStyle? suggestedStyle) style; @@ -242,17 +288,26 @@ enum EnumStyle { /// Configuration for function declarations. final class Functions extends Declarations { - /// Whether to expose the function typedef for a given function. + /// Whether to generate a typedef for a given function's native type. final bool Function(Declaration declaration) includeTypedef; static bool _includeTypedefDefault(Declaration declaration) => false; /// Whether the given function is a leaf function. + /// + /// This corresponds to the `isLeaf` parameter of FFI's `lookupFunction`. + /// For more details, its documentation is here: + /// https://api.dart.dev/dart-ffi/DynamicLibraryExtension/lookupFunction.html final bool Function(Declaration declaration) isLeaf; static bool _isLeafDefault(Declaration declaration) => false; - /// VarArg function handling. + /// Map from function's original name to [VarArgFunction]s. + /// + /// Dart doesn't support variadic functions. Instead, variadic functions are + /// handled by generating multiple versions of the same function, with + /// different signatures. Each [VarArgFunction] represents one of those + /// signatures. final Map> varArgs; const Functions({ @@ -448,11 +503,11 @@ final class ObjectiveC { /// Declaration filters for Objective-C protocols. final Protocols protocols; - /// Undocumented option that changes code generation for package:objective_c. - /// The main difference is whether NSObject etc are imported from - /// package:objective_c (the default) or code genned like any other class. - /// This is necessary because package:objective_c can't import NSObject from - /// itself. + // Undocumented option that changes code generation for package:objective_c. + // The main difference is whether NSObject etc are imported from + // package:objective_c (the default) or code genned like any other class. + // This is necessary because package:objective_c can't import NSObject from + // itself. @Deprecated('Only for internal use.') final bool generateForPackageObjectiveC; diff --git a/pkgs/ffigen/lib/src/config_provider/config_types.dart b/pkgs/ffigen/lib/src/config_provider/config_types.dart index ac61da7f9..ac60f4e5a 100644 --- a/pkgs/ffigen/lib/src/config_provider/config_types.dart +++ b/pkgs/ffigen/lib/src/config_provider/config_types.dart @@ -447,8 +447,13 @@ class RawVarArgFunction { RawVarArgFunction(this.postfix, this.rawTypeStrings); } +/// A specialization of a variadic function with specific argument types. class VarArgFunction { + /// A suffix to append to the function name for this variant. final String postfix; + + /// The types that will passed as the variadic parameters, replacing the + /// `...` in the original definition. final List types; VarArgFunction(this.postfix, this.types); @@ -459,9 +464,23 @@ class PackingValue { PackingValue(this.value); } +/// A declaration, such as a function or a class. class Declaration { + /// A unique identifier for the declaration. + /// + /// USR stands for Unified Symbol Resolution. It is an ID generated by clang + /// that is designed to be unique, and stable across compilations, but not + /// human readable. + /// + /// It's usually easiest to filter the declaration by the [originalName]. But + /// the name alone might not be unique. If you have two different declarations + /// with the same [originalName], log their [usr]s, and use that to make your + /// filtering more specific. final String usr; + + /// The original name of the declaration in source code, before any renaming. final String originalName; + Declaration({required this.usr, required this.originalName}); }