From 71a5ef1aedb1342950c276a9ae709249c96ce2c0 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 10:56:38 +1000 Subject: [PATCH 01/19] Headers -> Input --- pkgs/code_assets/example/host_name/tool/ffigen.dart | 4 ++-- pkgs/code_assets/example/mini_audio/tool/ffigen.dart | 4 +--- pkgs/code_assets/example/sqlite/tool/ffigen.dart | 2 +- pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart | 2 +- pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart | 2 +- pkgs/code_assets/example/stb_image/tool/ffigen.dart | 4 +--- pkgs/ffigen/README.md | 2 +- pkgs/ffigen/example/add/tool/ffigen.dart | 2 +- pkgs/ffigen/example/objective_c/generate_code.dart | 2 +- pkgs/ffigen/lib/ffigen.dart | 2 +- pkgs/ffigen/lib/src/code_generator/library.dart | 2 +- .../lib/src/code_generator/objc_built_in_functions.dart | 2 +- pkgs/ffigen/lib/src/code_generator/writer.dart | 2 +- pkgs/ffigen/lib/src/config_provider/config.dart | 8 ++++---- pkgs/ffigen/lib/src/config_provider/yaml_config.dart | 2 +- pkgs/ffigen/lib/src/context.dart | 2 +- pkgs/ffigen/lib/src/header_parser/parser.dart | 6 +++--- .../lib/src/header_parser/sub_parsers/macro_parser.dart | 2 +- .../lib/src/header_parser/translation_unit_parser.dart | 2 +- .../collision_tests/reserved_keyword_collision_test.dart | 2 +- pkgs/ffigen/test/config_tests/compiler_opts_test.dart | 2 +- pkgs/ffigen/test/example_tests/libclang_example_test.dart | 2 +- pkgs/ffigen/test/header_parser_tests/record_use_test.dart | 2 +- pkgs/ffigen/test/header_parser_tests/sort_test.dart | 2 +- .../test/large_integration_tests/large_objc_test.dart | 2 +- pkgs/ffigen/test/large_integration_tests/large_test.dart | 6 +++--- .../ffigen/test/native_cpp_test/verify_bindings_test.dart | 4 ++-- pkgs/ffigen/test/native_objc_test/deprecated_test.dart | 2 +- pkgs/ffigen/test/native_objc_test/ns_range_test.dart | 2 +- .../test/native_objc_test/swift_unavailable_test.dart | 2 +- pkgs/ffigen/test/native_objc_test/transitive_test.dart | 2 +- .../treeshaking_dylib_record_use/tool/ffigen.dart | 4 ++-- pkgs/swiftgen/lib/src/generator.dart | 2 +- 33 files changed, 43 insertions(+), 47 deletions(-) diff --git a/pkgs/code_assets/example/host_name/tool/ffigen.dart b/pkgs/code_assets/example/host_name/tool/ffigen.dart index 3d191a6305..f434f8488e 100644 --- a/pkgs/code_assets/example/host_name/tool/ffigen.dart +++ b/pkgs/code_assets/example/host_name/tool/ffigen.dart @@ -12,7 +12,7 @@ void main() { final FfiGenerator generator; if (Platform.isWindows) { generator = FfiGenerator( - headers: Headers(entryPoints: [packageRoot.resolve('src/windows.h')]), + input: Input(entryPoints: [packageRoot.resolve('src/windows.h')]), functions: functions, output: Output( dartFile: packageRoot.resolve('lib/src/third_party/windows.dart'), @@ -26,7 +26,7 @@ void main() { ); } else { generator = FfiGenerator( - headers: Headers(entryPoints: [packageRoot.resolve('src/unix.h')]), + input: Input(entryPoints: [packageRoot.resolve('src/unix.h')]), functions: functions, output: Output( dartFile: packageRoot.resolve('lib/src/third_party/unix.dart'), diff --git a/pkgs/code_assets/example/mini_audio/tool/ffigen.dart b/pkgs/code_assets/example/mini_audio/tool/ffigen.dart index 980d449568..a6d3a005dd 100644 --- a/pkgs/code_assets/example/mini_audio/tool/ffigen.dart +++ b/pkgs/code_assets/example/mini_audio/tool/ffigen.dart @@ -9,9 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - headers: Headers( - entryPoints: [packageRoot.resolve('third_party/miniaudio.h')], - ), + input: Input(entryPoints: [packageRoot.resolve('third_party/miniaudio.h')]), functions: Functions( include: (decl) => { 'ma_engine_init', diff --git a/pkgs/code_assets/example/sqlite/tool/ffigen.dart b/pkgs/code_assets/example/sqlite/tool/ffigen.dart index 034b15b38a..ec52a7bbcf 100644 --- a/pkgs/code_assets/example/sqlite/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - headers: Headers( + input: Input( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions( diff --git a/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart b/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart index 96e9d1a029..41f92e40a3 100644 --- a/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - headers: Headers( + input: Input( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions.includeSet({'sqlite3_libversion'}), diff --git a/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart b/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart index 96e9d1a029..41f92e40a3 100644 --- a/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - headers: Headers( + input: Input( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions.includeSet({'sqlite3_libversion'}), diff --git a/pkgs/code_assets/example/stb_image/tool/ffigen.dart b/pkgs/code_assets/example/stb_image/tool/ffigen.dart index a1ed4b0a3b..253397714b 100644 --- a/pkgs/code_assets/example/stb_image/tool/ffigen.dart +++ b/pkgs/code_assets/example/stb_image/tool/ffigen.dart @@ -9,9 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - headers: Headers( - entryPoints: [packageRoot.resolve('third_party/stb_image.h')], - ), + input: Input(entryPoints: [packageRoot.resolve('third_party/stb_image.h')]), functions: Functions( include: (decl) => {'stbi_info'}.contains(decl.originalName), recordUse: (_) => true, diff --git a/pkgs/ffigen/README.md b/pkgs/ffigen/README.md index 190f275cc4..5e237bf0a1 100644 --- a/pkgs/ffigen/README.md +++ b/pkgs/ffigen/README.md @@ -64,7 +64,7 @@ app has been created via `dart create ffigen_example`. // Required. Output path for the generated bindings. output: Output(dartFile: packageRoot.resolve('lib/add.g.dart')), // Optional. Where to look for header files. - headers: Headers(entryPoints: [packageRoot.resolve('src/add.h')]), + input: Input(entryPoints: [packageRoot.resolve('src/add.h')]), // Optional. What functions to generate bindings for. functions: Functions.includeSet({'add'}), ).generate(); diff --git a/pkgs/ffigen/example/add/tool/ffigen.dart b/pkgs/ffigen/example/add/tool/ffigen.dart index e87def4258..c8689b3166 100644 --- a/pkgs/ffigen/example/add/tool/ffigen.dart +++ b/pkgs/ffigen/example/add/tool/ffigen.dart @@ -8,7 +8,7 @@ import 'package:ffigen/ffigen.dart'; FfiGenerator getConfig(Uri packageRoot) { return FfiGenerator( output: Output(dartFile: packageRoot.resolve('lib/add.g.dart')), - headers: Headers(entryPoints: [packageRoot.resolve('src/add.h')]), + input: Input(entryPoints: [packageRoot.resolve('src/add.h')]), functions: Functions.includeSet({'add'}), ); } diff --git a/pkgs/ffigen/example/objective_c/generate_code.dart b/pkgs/ffigen/example/objective_c/generate_code.dart index f4091a58e9..6c729474d0 100644 --- a/pkgs/ffigen/example/objective_c/generate_code.dart +++ b/pkgs/ffigen/example/objective_c/generate_code.dart @@ -8,7 +8,7 @@ import 'package:ffigen/ffigen.dart'; import 'package:logging/logging.dart'; final config = FfiGenerator( - headers: Headers( + input: Input( // The entryPoints are the files that FFIgen should scan to find the APIs // you want to generate bindings for. You can use the macSdkPath or // iosSdkPath getters to find the Apple SDKs. diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index 77e8b50f35..aad3ad8098 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -31,7 +31,7 @@ export 'src/config_provider.dart' FfiGenerator, Functions, Globals, - Headers, + Input, Integers, Interfaces, Macros, diff --git a/pkgs/ffigen/lib/src/code_generator/library.dart b/pkgs/ffigen/lib/src/code_generator/library.dart index 126a389354..7d3c92294e 100644 --- a/pkgs/ffigen/lib/src/code_generator/library.dart +++ b/pkgs/ffigen/lib/src/code_generator/library.dart @@ -39,7 +39,7 @@ class Library { // ignore: deprecated_member_use_from_same_package libraryImports: context.config.libraryImports, silenceEnumWarning: context.config.enums.silenceWarning, - nativeEntryPoints: context.config.headers.entryPoints + nativeEntryPoints: context.config.input.entryPoints .map((uri) => uri.toFilePath()) .toList(), context: context, diff --git a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart index 3d2871b412..fb938f2848 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart @@ -239,7 +239,7 @@ class ObjCBuiltInFunctions { // a hash of parts of the config. static String _libraryIdFromConfigHash(Config config) => fnvHash32( [ - ...config.headers.entryPoints, + ...config.input.entryPoints, config.output.dartFile, config.output.objCFile, ].map((uri) => path.basename(uri.toFilePath())).join('\n'), diff --git a/pkgs/ffigen/lib/src/code_generator/writer.dart b/pkgs/ffigen/lib/src/code_generator/writer.dart index 6a957e6fb6..3b95cd981c 100644 --- a/pkgs/ffigen/lib/src/code_generator/writer.dart +++ b/pkgs/ffigen/lib/src/code_generator/writer.dart @@ -420,7 +420,7 @@ id objc_retainBlock(id); final s = StringBuffer(); final outDir = p.dirname(outFilename); // Emit each entry-point header exactly once. - for (final header in context.config.headers.entryPoints) { + for (final header in context.config.input.entryPoints) { s.write('#include "${p.relative(header.toFilePath(), from: outDir)}"\n'); } s.write(r''' diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index b45cac1199..e101d50e67 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -16,7 +16,7 @@ import 'config_types.dart'; // TODO: Add a code snippet example. final class FfiGenerator { /// The configuration for header parsing of [FfiGenerator]. - final Headers headers; + final Input input; /// Configuration for enums. final Enums enums; @@ -88,7 +88,7 @@ final class FfiGenerator { final Uri? libclangDylib; const FfiGenerator({ - this.headers = const Headers(), + this.input = const Input(), this.enums = Enums.excludeAll, this.functions = Functions.excludeAll, this.globals = Globals.excludeAll, @@ -126,7 +126,7 @@ final class FfiGenerator { } /// The configuration for header parsing of [FfiGenerator]. -final class Headers { +final class Input { /// Path to headers. May not contain globs. final List entryPoints; @@ -142,7 +142,7 @@ final class Headers { /// Where to ignore compiler warnings/errors in source header files. final bool ignoreSourceErrors; - const Headers({ + const Input({ this.entryPoints = const [], this.include = _includeDefault, this.compilerOptions, diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index f63ee2ff22..55faa8d29c 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1227,7 +1227,7 @@ final class YamlConfig { } FfiGenerator configAdapter() => FfiGenerator( - headers: Headers( + input: Input( compilerOptions: compilerOpts, entryPoints: entryPoints, include: shouldIncludeHeader, diff --git a/pkgs/ffigen/lib/src/context.dart b/pkgs/ffigen/lib/src/context.dart index 241c3a00f5..93b9bbb043 100644 --- a/pkgs/ffigen/lib/src/context.dart +++ b/pkgs/ffigen/lib/src/context.dart @@ -28,7 +28,7 @@ class Context { final reportedCommentRanges = <((String, int), (String, int))>{}; final libs = LibraryImports(); late final compilerOpts = - config.headers.compilerOptions ?? defaultCompilerOpts(logger); + config.input.compilerOptions ?? defaultCompilerOpts(logger); final Scope rootScope = Scope.createRoot('root'); final Scope rootObjCScope = Scope.createRoot('objc_root'); late final ExtraSymbols extraSymbols; diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 759dfb7761..985377976d 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -72,12 +72,12 @@ List parseToBindings(Context context) { final bindings = {}; // Log all headers for user. - context.logger.info('Input Headers: ${config.headers.entryPoints}'); + context.logger.info('Input Headers: ${config.input.entryPoints}'); final tuList = >[]; // Parse all translation units from entry points. - for (final headerLocationUri in config.headers.entryPoints) { + for (final headerLocationUri in config.input.entryPoints) { final headerLocation = headerLocationUri.toFilePath(); context.logger.fine('Creating TranslationUnit for header: $headerLocation'); @@ -114,7 +114,7 @@ List parseToBindings(Context context) { 'The compiler found warnings/errors in source files.', ); context.logger.warning('This will likely generate invalid bindings.'); - if (config.headers.ignoreSourceErrors) { + if (config.input.ignoreSourceErrors) { context.logger.warning( 'Ignored source errors. (User supplied --ignore-source-errors)', ); diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart index bc93a75224..e700f7330a 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart @@ -196,7 +196,7 @@ File createFileForMacros(Context context) { // Write file contents. final sb = StringBuffer(); - for (final h in context.config.headers.entryPoints) { + for (final h in context.config.input.entryPoints) { final fullHeaderPath = File(h.toFilePath()).absolute.path; sb.writeln('#include "$fullHeaderPath"'); } diff --git a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart index 8d4022f31d..36534af6e0 100644 --- a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart @@ -26,7 +26,7 @@ Set parseTranslationUnit( translationUnitCursor.visitChildren((cursor) { final file = cursor.sourceFileName(); if (file.isEmpty) return; - if (headers[file] ??= context.config.headers.include(Uri.file(file))) { + if (headers[file] ??= context.config.input.include(Uri.file(file))) { try { logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}'); switch (clang.clang_getCursorKind(cursor)) { diff --git a/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart b/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart index cc5e3a8195..2274be87c6 100644 --- a/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart +++ b/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart @@ -21,7 +21,7 @@ void main() { style: const DynamicLibraryBindings(), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/config_tests/compiler_opts_test.dart b/pkgs/ffigen/test/config_tests/compiler_opts_test.dart index d844f95412..8559faba45 100644 --- a/pkgs/ffigen/test/config_tests/compiler_opts_test.dart +++ b/pkgs/ffigen/test/config_tests/compiler_opts_test.dart @@ -37,7 +37,7 @@ ${strings.compilerOptsAuto}: ${strings.includeCStdLib}: false '''); expect( - config.headers.compilerOptions, + config.input.compilerOptions, equals([if (Platform.isMacOS) '-Wno-nullability-completeness']), ); }); diff --git a/pkgs/ffigen/test/example_tests/libclang_example_test.dart b/pkgs/ffigen/test/example_tests/libclang_example_test.dart index 22dd0a0c0e..6396f06945 100644 --- a/pkgs/ffigen/test/example_tests/libclang_example_test.dart +++ b/pkgs/ffigen/test/example_tests/libclang_example_test.dart @@ -28,7 +28,7 @@ void main() { // compiler options. It can't use absolute paths because it's checked in // yaml code. To support concurrent tests, we can't set Directory.current. // As a workaround, add an extra '-I' option that uses the absolute path. - generator.headers.compilerOptions!.add( + generator.input.compilerOptions!.add( '-I${path.join(packagePathForTests, 'third_party/libclang/include')}', ); diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index f0dfd22fac..bf0bc1ee13 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -16,7 +16,7 @@ void main() { p.join('test', 'header_parser_tests', 'record_use.h'), ); final generator = FfiGenerator( - headers: Headers(entryPoints: [Uri.file(headerFile)]), + input: Input(entryPoints: [Uri.file(headerFile)]), functions: Functions( include: (decl) => true, recordUse: (decl) => true, diff --git a/pkgs/ffigen/test/header_parser_tests/sort_test.dart b/pkgs/ffigen/test/header_parser_tests/sort_test.dart index 92a6c79023..437ef2f928 100644 --- a/pkgs/ffigen/test/header_parser_tests/sort_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/sort_test.dart @@ -19,7 +19,7 @@ void main() { testContext( FfiGenerator( output: Output(dartFile: Uri.file('unused')), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart index 1eb46cf241..24dbc4c571 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart @@ -72,7 +72,7 @@ void main() { const forceIncludedProtocols = {'NSTextLocation'}; final generator = FfiGenerator( - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index edf269adeb..f221f684e3 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart @@ -39,7 +39,7 @@ void main() { wrapperDocComment: 'Bindings to LibClang.', ), ), - headers: Headers( + input: Input( compilerOptions: [...defaultCompilerOpts(logger), '-I$includeDir'], entryPoints: [ Uri.file( @@ -135,7 +135,7 @@ void main() { wrapperDocComment: 'Bindings to Cjson.', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( @@ -176,7 +176,7 @@ void main() { ), commentType: const CommentType(CommentStyle.any, CommentLength.full), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart b/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart index 040580a872..67b05eab5e 100644 --- a/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart +++ b/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart @@ -37,7 +37,7 @@ void main() { assetId: 'package:ffigen/cpp_test', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file(path.join(testDir.path, 'cpp_class_test.h')), Uri.file(path.join(testDir.path, 'finalizer_test_subject.h')), @@ -55,7 +55,7 @@ void main() { assetId: 'package:ffigen/cpp_test', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file(path.join(testDir.path, 'memory_edge_cases.h')), ], diff --git a/pkgs/ffigen/test/native_objc_test/deprecated_test.dart b/pkgs/ffigen/test/native_objc_test/deprecated_test.dart index 2b86a6fc69..8ac506414a 100644 --- a/pkgs/ffigen/test/native_objc_test/deprecated_test.dart +++ b/pkgs/ffigen/test/native_objc_test/deprecated_test.dart @@ -32,7 +32,7 @@ String bindingsForVersion({Versions? iosVers, Versions? macosVers}) { wrapperDocComment: 'Tests API deprecation', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/ns_range_test.dart b/pkgs/ffigen/test/native_objc_test/ns_range_test.dart index 6db7b5b2af..5928169617 100644 --- a/pkgs/ffigen/test/native_objc_test/ns_range_test.dart +++ b/pkgs/ffigen/test/native_objc_test/ns_range_test.dart @@ -34,7 +34,7 @@ void main() { wrapperName: 'NSRangeTestObjCLibrary', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart b/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart index 84aa4a59b1..6e645c3f9c 100644 --- a/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart +++ b/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart @@ -35,7 +35,7 @@ void main() { wrapperDocComment: 'Tests SWIFT_UNAVAILABLE annotation', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/transitive_test.dart b/pkgs/ffigen/test/native_objc_test/transitive_test.dart index 371987996f..f247a964ac 100644 --- a/pkgs/ffigen/test/native_objc_test/transitive_test.dart +++ b/pkgs/ffigen/test/native_objc_test/transitive_test.dart @@ -35,7 +35,7 @@ String generate({ wrapperDocComment: 'Tests transitive inclusion', ), ), - headers: Headers( + input: Input( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart b/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart index 1d7b443338..f2b4d7873e 100644 --- a/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart +++ b/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart @@ -11,7 +11,7 @@ void main() { // 1. Generate bindings for add.c FfiGenerator( - headers: Headers( + input: Input( entryPoints: [packageRoot.resolve('src/add.c')], ), functions: Functions( @@ -36,7 +36,7 @@ void main() { // 2. Generate bindings for multiply.c FfiGenerator( - headers: Headers( + input: Input( entryPoints: [packageRoot.resolve('src/multiply.c')], ), functions: Functions( diff --git a/pkgs/swiftgen/lib/src/generator.dart b/pkgs/swiftgen/lib/src/generator.dart index 53f3a20b61..27bcce9a15 100644 --- a/pkgs/swiftgen/lib/src/generator.dart +++ b/pkgs/swiftgen/lib/src/generator.dart @@ -120,7 +120,7 @@ extension SwiftGenGenerator on SwiftGenerator { categories: ffigen.objectiveC.categories, externalVersions: ffigen.objectiveC.externalVersions, ), - headers: fg.Headers( + input: fg.Input( entryPoints: [Uri.file(objcHeader)], compilerOptions: [ ...fg.defaultCompilerOpts(logger), From 6290055cdb83f16e4e3a5dbe4068e33cb23cd1bc Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 11:52:11 +1000 Subject: [PATCH 02/19] Typedef.imported -> FfiGenerator.typedefImports --- .../lib/src/config_provider/config.dart | 23 ++++++++----------- .../lib/src/config_provider/yaml_config.dart | 4 ++-- .../large_integration_tests/large_test.dart | 8 +++---- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index e101d50e67..f2ec9c85cf 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -81,6 +81,13 @@ final class FfiGenerator { ) final List libraryImports; + /// Typedefs imported from other Dart files. + @Deprecated( + 'This field will change type. See ' + 'https://github.com/dart-lang/native/issues/2595.', + ) + final List typedefImports; + /// Path to the clang library. /// /// Only visible for YamlConfig plumbing. @@ -97,6 +104,7 @@ final class FfiGenerator { this.structs = Structs.excludeAll, this.cpp, this.typedefs = Typedefs.excludeAll, + this.typedefImports = const [], this.unions = Unions.excludeAll, this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, @@ -464,13 +472,6 @@ final class Structs extends Declarations { /// Configuration for typedefs. final class Typedefs extends Declarations { - /// Typedefs imported from other Dart files. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List imported; - /// If enabled, unused typedefs will also be generated. final bool includeUnused; @@ -480,11 +481,6 @@ final class Typedefs extends Declarations { const Typedefs({ super.rename, super.include, - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - this.imported = const [], this.includeUnused = false, this.useSupportedTypedefs = true, }); @@ -770,8 +766,7 @@ extension type Config(FfiGenerator ffiGen) implements FfiGenerator { // Override declarative user spec with what FFIgen internals expect. Map get typedefTypeMappings => Map.fromEntries( - // ignore: deprecated_member_use_from_same_package - ffiGen.typedefs.imported.map( + ffiGen.typedefImports.map( (import) => MapEntry(import.nativeType, import), ), ); diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 55faa8d29c..350604896c 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1302,9 +1302,9 @@ final class YamlConfig { rename: typedefs.rename, useSupportedTypedefs: useSupportedTypedefs, includeUnused: includeUnusedTypedefs, - // ignore: deprecated_member_use_from_same_package - imported: typedefTypeMappings.values.toList(), ), + // ignore: deprecated_member_use_from_same_package + typedefImports: typedefTypeMappings.values.toList(), objectiveC: language == Language.objc ? ObjectiveC( interfaces: Interfaces( diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index f221f684e3..215f0db2a1 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart @@ -67,11 +67,9 @@ void main() { structs: Structs.includeAll, enums: Enums.includeAll, macros: Macros.includeAll, - typedefs: Typedefs( - include: (_) => true, - // ignore: deprecated_member_use_from_same_package - imported: [ImportedType(ffiImport, 'Int64', 'int', 'time_t')], - ), + typedefs: Typedefs(include: (_) => true), + // ignore: deprecated_member_use_from_same_package + typedefImports: [ImportedType(ffiImport, 'Int64', 'int', 'time_t')], ); final library = parse(Context(logger, generator)); final context = testContext(); From cff41da6aa6793392b9e007b55f839a1a8406b6b Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 12:51:49 +1000 Subject: [PATCH 03/19] consolidate import fields --- pkgs/ffigen/lib/ffigen.dart | 1 - .../lib/src/config_provider/config.dart | 110 +++--------------- .../lib/src/config_provider/spec_utils.dart | 2 +- .../lib/src/config_provider/yaml_config.dart | 16 ++- .../type_extractor/extractor.dart | 4 +- .../lib/src/visitor/apply_config_filters.dart | 2 +- .../large_integration_tests/large_test.dart | 2 +- pkgs/swiftgen/lib/src/config.dart | 4 - pkgs/swiftgen/lib/src/generator.dart | 1 - 9 files changed, 28 insertions(+), 114 deletions(-) diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index aad3ad8098..da396ee043 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -32,7 +32,6 @@ export 'src/config_provider.dart' Functions, Globals, Input, - Integers, Interfaces, Macros, NativeExternalBindings, diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index f2ec9c85cf..27ccb0b5b1 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -27,9 +27,6 @@ final class FfiGenerator { /// Configuration for globals. final Globals globals; - /// Configuration for integer types. - final Integers integers; - /// Configuration for macro constants. final Macros macros; @@ -61,17 +58,6 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; - /// Types imported from other Dart files, specified via the - /// unique-resource-identifer used in Clang. - /// - /// Applies to all kinds of definitions. - // TODO(https://github.com/dart-lang/native/issues/2596): Remove this. - @Deprecated( - 'Will be folded into imported fields of the various declarations. See ' - 'https://github.com/dart-lang/native/issues/2596.', - ) - final Map importedTypesByUsr; - /// Stores all the library imports specified by user including those for ffi /// and pkg_ffi. // TODO(https://github.com/dart-lang/native/issues/2597): Remove this. @@ -86,7 +72,7 @@ final class FfiGenerator { 'This field will change type. See ' 'https://github.com/dart-lang/native/issues/2595.', ) - final List typedefImports; + final List importedTypes; /// Path to the clang library. /// @@ -99,21 +85,15 @@ final class FfiGenerator { this.enums = Enums.excludeAll, this.functions = Functions.excludeAll, this.globals = Globals.excludeAll, - this.integers = const Integers(), this.macros = Macros.excludeAll, this.structs = Structs.excludeAll, this.cpp, this.typedefs = Typedefs.excludeAll, - this.typedefImports = const [], + this.importedTypes = const [], this.unions = Unions.excludeAll, this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, - @Deprecated( - 'Will be folded into imported fields of the various declarations. See ' - 'https://github.com/dart-lang/native/issues/2596.', - ) - this.importedTypesByUsr = const {}, @Deprecated( 'In the future, this shoud be inferred from ImportedTypes. See ' 'https://github.com/dart-lang/native/issues/2597.', @@ -400,25 +380,6 @@ final class Globals extends Declarations { Globals(include: Declarations.includeSet(names)); } -/// Configuration for integer types. -final class Integers { - /// Integer types imported from other Dart files. - // TODO(https://github.com/dart-lang/native/issues/2595): Change type. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List imported; - - const Integers({ - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - this.imported = const [], - }); -} - /// Configuration for macros. final class Macros extends Declarations { const Macros({super.rename, super.include}); @@ -436,14 +397,6 @@ final class Structs extends Declarations { /// Whether structs that are dependencies should be included. final CompoundDependencies dependencies; - /// Structs imported from other Dart files. - // TODO(https://github.com/dart-lang/native/issues/2595): Change type. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List imported; - /// Whether, and how, to override struct packing for the given struct. final PackingValue? Function(Declaration declaration) packingOverride; @@ -454,11 +407,6 @@ final class Structs extends Declarations { super.rename, super.renameMember, this.dependencies = CompoundDependencies.opaque, - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - this.imported = const [], this.packingOverride = _packingOverrideDefault, }); @@ -517,23 +465,11 @@ final class Unions extends Declarations { /// Whether unions that are dependencies should be included. final CompoundDependencies dependencies; - /// Unions imported from other Dart files. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List imported; - const Unions({ super.include, super.rename, super.renameMember, this.dependencies = CompoundDependencies.opaque, - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - this.imported = const [], }); static const excludeAll = Unions(include: Declarations.excludeAll); @@ -760,40 +696,26 @@ final class DynamicLibraryBindings implements BindingStyle { } extension type Config(FfiGenerator ffiGen) implements FfiGenerator { - // ignore: deprecated_member_use_from_same_package - Map get importedTypesByUsr => ffiGen.importedTypesByUsr; - - // Override declarative user spec with what FFIgen internals expect. - Map get typedefTypeMappings => - Map.fromEntries( - ffiGen.typedefImports.map( - (import) => MapEntry(import.nativeType, import), - ), - ); - - Map get structTypeMappings => + Map get _nativeTypeToImportedType => Map.fromEntries( // ignore: deprecated_member_use_from_same_package - ffiGen.structs.imported.map( - (import) => MapEntry(import.nativeType, import), + ffiGen.importedTypes.expand( + (import) => [ + MapEntry(import.nativeType, import), + MapEntry(import.cType, import), + ], ), ); // Override declarative user spec with what FFIgen internals expect. - Map get unionTypeMappings => - Map.fromEntries( - // ignore: deprecated_member_use_from_same_package - ffiGen.unions.imported.map( - (import) => MapEntry(import.nativeType, import), - ), - ); + Map get typedefTypeMappings => + _nativeTypeToImportedType; + + Map get structTypeMappings => _nativeTypeToImportedType; // Override declarative user spec with what FFIgen internals expect. - Map get importedIntegers => - Map.fromEntries( - // ignore: deprecated_member_use_from_same_package - ffiGen.integers.imported.map( - (import) => MapEntry(import.nativeType, import), - ), - ); + Map get unionTypeMappings => _nativeTypeToImportedType; + + // Override declarative user spec with what FFIgen internals expect. + Map get importedIntegers => _nativeTypeToImportedType; } diff --git a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart index 10963e3006..33fdf7a7f1 100644 --- a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart +++ b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart @@ -46,7 +46,7 @@ void loadImportedTypes( libraryImport, name, dartName, - name, + usr, importedDartType: true, ); } diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 350604896c..8c600f9792 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1263,8 +1263,6 @@ final class YamlConfig { dependencies: _structDependencies, packingOverride: (decl) => _structPackingOverride.getOverridenPackValue(decl.originalName), - // ignore: deprecated_member_use_from_same_package - imported: structTypeMappings.values.toList(), ), enums: Enums( include: _enumClassDecl.shouldInclude, @@ -1284,8 +1282,6 @@ final class YamlConfig { rename: _unionDecl.rename, renameMember: _unionDecl.renameMember, dependencies: _unionDependencies, - // ignore: deprecated_member_use_from_same_package - imported: unionTypeMappings.values.toList(), ), unnamedEnums: UnnamedEnums( include: _unnamedEnumConstants.shouldInclude, @@ -1304,7 +1300,13 @@ final class YamlConfig { includeUnused: includeUnusedTypedefs, ), // ignore: deprecated_member_use_from_same_package - typedefImports: typedefTypeMappings.values.toList(), + importedTypes: [ + ...typedefTypeMappings.values, + ...structTypeMappings.values, + ...unionTypeMappings.values, + ...nativeTypeMappings.values, + ...usrTypeMappings.values, + ], objectiveC: language == Language.objc ? ObjectiveC( interfaces: Interfaces( @@ -1338,10 +1340,6 @@ final class YamlConfig { // ignore: deprecated_member_use_from_same_package libraryImports: libraryImports.values.toList(), // ignore: deprecated_member_use_from_same_package - importedTypesByUsr: usrTypeMappings, - // ignore: deprecated_member_use_from_same_package - integers: Integers(imported: nativeTypeMappings.values.toList()), - // ignore: deprecated_member_use_from_same_package libclangDylib: libclangDylib, ); } diff --git a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart index 60762f7516..4f810f4d62 100644 --- a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart +++ b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart @@ -172,9 +172,9 @@ Type? _createTypeFromCursor( final logger = context.logger; final config = context.config; final usr = cursor.usr(); - if (config.importedTypesByUsr.containsKey(usr)) { + if (config.typedefTypeMappings.containsKey(usr)) { logger.fine(' Type $usr mapped from usr'); - return config.importedTypesByUsr[usr]!; + return config.typedefTypeMappings[usr]!; } switch (cxtype.kind) { case clang_types.CXTypeKind.CXType_Typedef: diff --git a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart index d9f34e25bc..12db07274e 100644 --- a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart +++ b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart @@ -16,7 +16,7 @@ class ApplyConfigFiltersVisitation extends Visitation { void _visitImpl(Binding node, Declarations filters) { node.visitChildren(visitor); if (node.originalName == '') return; - if (config.importedTypesByUsr.containsKey(node.usr)) return; + if (config.typedefTypeMappings.containsKey(node.usr)) return; if (filters.include(node)) directlyIncluded.add(node); } diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index 215f0db2a1..359e3f5008 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart @@ -69,7 +69,7 @@ void main() { macros: Macros.includeAll, typedefs: Typedefs(include: (_) => true), // ignore: deprecated_member_use_from_same_package - typedefImports: [ImportedType(ffiImport, 'Int64', 'int', 'time_t')], + importedTypes: [ImportedType(ffiImport, 'Int64', 'int', 'time_t')], ); final library = parse(Context(logger, generator)); final context = testContext(); diff --git a/pkgs/swiftgen/lib/src/config.dart b/pkgs/swiftgen/lib/src/config.dart index d2ff5f86c0..62dfec8f01 100644 --- a/pkgs/swiftgen/lib/src/config.dart +++ b/pkgs/swiftgen/lib/src/config.dart @@ -234,9 +234,6 @@ class FfiGeneratorOptions { /// [ffigen.FfiGenerator.globals] final ffigen.Globals globals; - /// Configuration for integer types. - final ffigen.Integers integers; - /// [ffigen.FfiGenerator.macros] final ffigen.Macros macros; @@ -253,7 +250,6 @@ class FfiGeneratorOptions { this.enums = ffigen.Enums.excludeAll, this.unnamedEnums = ffigen.UnnamedEnums.excludeAll, this.globals = ffigen.Globals.excludeAll, - this.integers = const ffigen.Integers(), this.macros = ffigen.Macros.excludeAll, this.typedefs = ffigen.Typedefs.excludeAll, this.objectiveC = const ffigen.ObjectiveC(), diff --git a/pkgs/swiftgen/lib/src/generator.dart b/pkgs/swiftgen/lib/src/generator.dart index 27bcce9a15..b46119c2a3 100644 --- a/pkgs/swiftgen/lib/src/generator.dart +++ b/pkgs/swiftgen/lib/src/generator.dart @@ -93,7 +93,6 @@ extension SwiftGenGenerator on SwiftGenerator { enums: ffigen.enums, unnamedEnums: ffigen.unnamedEnums, globals: ffigen.globals, - integers: ffigen.integers, macros: ffigen.macros, typedefs: ffigen.typedefs, objectiveC: fg.ObjectiveC( From 0be46286e57db4524e7434af554261f4be7577a0 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 13:00:01 +1000 Subject: [PATCH 04/19] Remove library imports (dead code) --- pkgs/ffigen/lib/src/code_generator/library.dart | 4 ---- pkgs/ffigen/lib/src/code_generator/writer.dart | 1 - pkgs/ffigen/lib/src/config_provider/config.dart | 14 -------------- .../lib/src/config_provider/yaml_config.dart | 2 -- 4 files changed, 21 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/library.dart b/pkgs/ffigen/lib/src/code_generator/library.dart index 7d3c92294e..1397560478 100644 --- a/pkgs/ffigen/lib/src/code_generator/library.dart +++ b/pkgs/ffigen/lib/src/code_generator/library.dart @@ -36,8 +36,6 @@ class Library { generateForPackageObjectiveC: // ignore: deprecated_member_use_from_same_package context.config.objectiveC?.generateForPackageObjectiveC ?? false, - // ignore: deprecated_member_use_from_same_package - libraryImports: context.config.libraryImports, silenceEnumWarning: context.config.enums.silenceWarning, nativeEntryPoints: context.config.input.entryPoints .map((uri) => uri.toFilePath()) @@ -50,7 +48,6 @@ class Library { required List bindings, String? header, bool generateForPackageObjectiveC = false, - List libraryImports = const [], bool silenceEnumWarning = false, List nativeEntryPoints = const [], required Context context, @@ -88,7 +85,6 @@ class Library { noLookUpBindings: noLookUpBindings, classDocComment: description, header: header, - additionalImports: libraryImports.map(context.libs.canonicalize).toList(), generateForPackageObjectiveC: generateForPackageObjectiveC, silenceEnumWarning: silenceEnumWarning, nativeEntryPoints: nativeEntryPoints, diff --git a/pkgs/ffigen/lib/src/code_generator/writer.dart b/pkgs/ffigen/lib/src/code_generator/writer.dart index 3b95cd981c..b9c8f1e199 100644 --- a/pkgs/ffigen/lib/src/code_generator/writer.dart +++ b/pkgs/ffigen/lib/src/code_generator/writer.dart @@ -48,7 +48,6 @@ class Writer { required this.ffiNativeBindings, required this.noLookUpBindings, required this.nativeAssetId, - List additionalImports = const [], this.classDocComment, this.header, required this.generateForPackageObjectiveC, diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 27ccb0b5b1..dbc4380156 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -58,15 +58,6 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; - /// Stores all the library imports specified by user including those for ffi - /// and pkg_ffi. - // TODO(https://github.com/dart-lang/native/issues/2597): Remove this. - @Deprecated( - 'In the future, this shoud be inferred from ImportedTypes. See ' - 'https://github.com/dart-lang/native/issues/2597.', - ) - final List libraryImports; - /// Typedefs imported from other Dart files. @Deprecated( 'This field will change type. See ' @@ -94,11 +85,6 @@ final class FfiGenerator { this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, - @Deprecated( - 'In the future, this shoud be inferred from ImportedTypes. See ' - 'https://github.com/dart-lang/native/issues/2597.', - ) - this.libraryImports = const [], @Deprecated('Only visible for YamlConfig plumbing.') this.libclangDylib, }); diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 8c600f9792..f5941a6d4c 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1338,8 +1338,6 @@ final class YamlConfig { ) : null, // ignore: deprecated_member_use_from_same_package - libraryImports: libraryImports.values.toList(), - // ignore: deprecated_member_use_from_same_package libclangDylib: libclangDylib, ); } From 66321a9b195eeba86ae2f9d1dcd39efa8ca61be2 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 14:27:29 +1000 Subject: [PATCH 05/19] Remove extension type Config utils --- .../lib/src/code_generator/imports.dart | 2 ++ .../objc_built_in_functions.dart | 2 +- .../lib/src/config_provider/config.dart | 25 ------------- .../lib/src/config_provider/spec_utils.dart | 3 +- pkgs/ffigen/lib/src/context.dart | 31 +++++++++------- pkgs/ffigen/lib/src/ffigen.dart | 19 +++++----- pkgs/ffigen/lib/src/header_parser/parser.dart | 2 +- .../type_extractor/extractor.dart | 20 +++++------ .../lib/src/visitor/apply_config_filters.dart | 35 ++++++++++--------- .../lib/src/visitor/find_transitive_deps.dart | 4 +-- .../ffigen/lib/src/visitor/list_bindings.dart | 4 +-- .../lib/src/visitor/opaque_compounds.dart | 4 +-- 12 files changed, 67 insertions(+), 84 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/imports.dart b/pkgs/ffigen/lib/src/code_generator/imports.dart index 5805ff1819..52185caa91 100644 --- a/pkgs/ffigen/lib/src/code_generator/imports.dart +++ b/pkgs/ffigen/lib/src/code_generator/imports.dart @@ -52,6 +52,7 @@ class ImportedType extends Type { /// Whether the [dartType] is an import from the [libraryImport]. final bool importedDartType; + final String? usr; ImportedType( this.libraryImport, @@ -60,6 +61,7 @@ class ImportedType extends Type { this.nativeType, { this.defaultValue, this.importedDartType = false, + this.usr, }); @override diff --git a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart index fb938f2848..83a73067f8 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart @@ -237,7 +237,7 @@ class ObjCBuiltInFunctions { // A unique (but not human readable) ID for the generated library based on // a hash of parts of the config. - static String _libraryIdFromConfigHash(Config config) => fnvHash32( + static String _libraryIdFromConfigHash(FfiGenerator config) => fnvHash32( [ ...config.input.entryPoints, config.output.dartFile, diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index dbc4380156..032a9a6a33 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -680,28 +680,3 @@ final class DynamicLibraryBindings implements BindingStyle { this.wrapperDocComment, }); } - -extension type Config(FfiGenerator ffiGen) implements FfiGenerator { - Map get _nativeTypeToImportedType => - Map.fromEntries( - // ignore: deprecated_member_use_from_same_package - ffiGen.importedTypes.expand( - (import) => [ - MapEntry(import.nativeType, import), - MapEntry(import.cType, import), - ], - ), - ); - - // Override declarative user spec with what FFIgen internals expect. - Map get typedefTypeMappings => - _nativeTypeToImportedType; - - Map get structTypeMappings => _nativeTypeToImportedType; - - // Override declarative user spec with what FFIgen internals expect. - Map get unionTypeMappings => _nativeTypeToImportedType; - - // Override declarative user spec with what FFIgen internals expect. - Map get importedIntegers => _nativeTypeToImportedType; -} diff --git a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart index 33fdf7a7f1..1f7896f2f8 100644 --- a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart +++ b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart @@ -46,8 +46,9 @@ void loadImportedTypes( libraryImport, name, dartName, - usr, + name, importedDartType: true, + usr: usr, ); } } diff --git a/pkgs/ffigen/lib/src/context.dart b/pkgs/ffigen/lib/src/context.dart index 93b9bbb043..8a271883a9 100644 --- a/pkgs/ffigen/lib/src/context.dart +++ b/pkgs/ffigen/lib/src/context.dart @@ -18,7 +18,9 @@ import 'header_parser/utils.dart'; /// Wrapper around various FFIgen-wide variables. class Context { final Logger logger; - final Config config; + final FfiGenerator config; + final Map importedTypesByUsr; + final Map importedTypesByName; final CursorIndex cursorIndex; final bindingsIndex = BindingsIndex(); final savedMacros = {}; @@ -34,25 +36,28 @@ class Context { late final ExtraSymbols extraSymbols; final String tmpDir; - Context( - this.logger, - FfiGenerator generator, { - Uri? libclangDylib, - String? tmpDir, - }) : config = Config(generator), - cursorIndex = CursorIndex(logger), - tmpDir = - tmpDir ?? - Directory.systemTemp.createTempSync('ffigen temp dir ').path { + Context(this.logger, this.config, {Uri? libclangDylib, String? tmpDir}) + : importedTypesByUsr = { + for (final imported in config.importedTypes) + if (imported.usr != null) imported.usr!: imported, + }, + importedTypesByName = { + for (final imported in config.importedTypes) + imported.nativeType: imported, + }, + cursorIndex = CursorIndex(logger), + tmpDir = + tmpDir ?? + Directory.systemTemp.createTempSync('ffigen temp dir ').path { objCBuiltInFunctions = ObjCBuiltInFunctions( this, // ignore: deprecated_member_use_from_same_package - generator.objectiveC?.generateForPackageObjectiveC ?? false, + config.objectiveC?.generateForPackageObjectiveC ?? false, ); final libclangDylibPath = // ignore: deprecated_member_use_from_same_package - generator.libclangDylib?.toFilePath() ?? + config.libclangDylib?.toFilePath() ?? libclangDylib?.toFilePath() ?? findDylibAtDefaultLocations(logger); diff --git a/pkgs/ffigen/lib/src/ffigen.dart b/pkgs/ffigen/lib/src/ffigen.dart index 3ddd2a0a7c..ea881bc646 100644 --- a/pkgs/ffigen/lib/src/ffigen.dart +++ b/pkgs/ffigen/lib/src/ffigen.dart @@ -7,7 +7,7 @@ import 'dart:io'; import 'package:cli_util/cli_logging.dart' show Ansi; import 'package:logging/logging.dart'; -import 'config_provider.dart' show Config, FfiGenerator; +import 'config_provider.dart' show FfiGenerator; import 'context.dart'; import 'header_parser.dart' show parse; import 'logger.dart'; @@ -21,20 +21,19 @@ extension FfiGenGenerator on FfiGenerator { /// logger that streams [Level.WARNING] to stdout and higher levels to stderr. void generate({Logger? logger, Uri? libclangDylib}) { logger ??= createDefaultLogger(); - final config = Config(this); - final context = Context(logger, config, libclangDylib: libclangDylib); + final context = Context(logger, this, libclangDylib: libclangDylib); // Parse the bindings according to config object provided. final library = parse(context); // Generate files for the parsed bindings. - final gen = File(config.output.dartFile.toFilePath()); - library.generateFile(gen, format: config.ffiGen.output.format); + final gen = File(output.dartFile.toFilePath()); + library.generateFile(gen, format: output.format); logger.info( _successPen('Finished, Bindings generated in ${gen.absolute.path}'), ); - final objCGen = File(config.output.objCFile.toFilePath()); + final objCGen = File(output.objCFile.toFilePath()); if (library.generateObjCFile(objCGen)) { logger.info( _successPen( @@ -44,7 +43,7 @@ extension FfiGenGenerator on FfiGenerator { ); } - final cppGen = File(config.output.cppBindingsFile.toFilePath()); + final cppGen = File(output.cppBindingsFile.toFilePath()); if (library.generateCppFile(cppGen)) { logger.info( _successPen( @@ -53,12 +52,12 @@ extension FfiGenGenerator on FfiGenerator { ); } - final recordUseMappingFile = config.output.recordUseMapping; + final recordUseMappingFile = output.recordUseMapping; if (recordUseMappingFile != null) { final recordUseMappingGen = File(recordUseMappingFile.toFilePath()); if (library.generateRecordUseMappingFile( recordUseMappingGen, - format: config.output.format, + format: output.format, )) { logger.info( _successPen( @@ -69,7 +68,7 @@ extension FfiGenGenerator on FfiGenerator { } } - final symbolFile = config.output.symbolFile; + final symbolFile = output.symbolFile; if (symbolFile != null) { final symbolFileGen = File(symbolFile.output.toFilePath()); library.generateSymbolOutputFile( diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 985377976d..b4c5b60aac 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -176,7 +176,7 @@ List transformBindings(List rawBindings, Context context) { visit(context, CopyMethodsFromSuperTypesVisitation(), allBindings); visit(context, FixOverriddenMethodsVisitation(context), allBindings); - final applyConfigFiltersVisitation = ApplyConfigFiltersVisitation(config); + final applyConfigFiltersVisitation = ApplyConfigFiltersVisitation(context); visit(context, applyConfigFiltersVisitation, allBindings); final directlyIncluded = applyConfigFiltersVisitation.directlyIncluded; final included = directlyIncluded.union( diff --git a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart index 4f810f4d62..d596a73866 100644 --- a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart +++ b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart @@ -149,9 +149,9 @@ Type getCodeGenType( if (typeSpellKey.startsWith('const ')) { typeSpellKey = typeSpellKey.replaceFirst('const ', ''); } - if (context.config.importedIntegers.containsKey(typeSpellKey)) { + if (context.importedTypesByName.containsKey(typeSpellKey)) { context.logger.fine(' Type $typeSpellKey mapped from type-map.'); - return context.config.importedIntegers[typeSpellKey]!; + return context.importedTypesByName[typeSpellKey]!; } else if (cxTypeKindToImportedTypes.containsKey(typeSpellKey)) { return cxTypeKindToImportedTypes[typeSpellKey]!; } else { @@ -172,9 +172,9 @@ Type? _createTypeFromCursor( final logger = context.logger; final config = context.config; final usr = cursor.usr(); - if (config.typedefTypeMappings.containsKey(usr)) { + if (context.importedTypesByUsr.containsKey(usr)) { logger.fine(' Type $usr mapped from usr'); - return config.typedefTypeMappings[usr]!; + return context.importedTypesByUsr[usr]!; } switch (cxtype.kind) { case clang_types.CXTypeKind.CXType_Typedef: @@ -185,9 +185,9 @@ Type? _createTypeFromCursor( // those two types are ABI compatible, so just return bool regardless. return BooleanType(); } - if (config.typedefTypeMappings.containsKey(spelling)) { + if (context.importedTypesByName.containsKey(spelling)) { logger.fine(' Type $spelling mapped from type-map'); - return config.typedefTypeMappings[spelling]!; + return context.importedTypesByName[spelling]!; } // Get name from supported typedef name if config allows. if (config.typedefs.useSupportedTypedefs) { @@ -267,15 +267,15 @@ Type? _extractfromRecord( } if (cursorKind == clang_types.CXCursorKind.CXCursor_StructDecl) { - if (config.structTypeMappings.containsKey(declSpelling)) { + if (context.importedTypesByName.containsKey(declSpelling)) { logger.fine(' Type Mapped from type-map'); - return config.structTypeMappings[declSpelling]!; + return context.importedTypesByName[declSpelling]!; } return parseStructDeclaration(cursor, context); } else if (cursorKind == clang_types.CXCursorKind.CXCursor_UnionDecl) { - if (config.unionTypeMappings.containsKey(declSpelling)) { + if (context.importedTypesByName.containsKey(declSpelling)) { logger.fine(' Type Mapped from type-map'); - return config.unionTypeMappings[declSpelling]!; + return context.importedTypesByName[declSpelling]!; } return parseUnionDeclaration(cursor, context); } diff --git a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart index 12db07274e..d5e6dcef62 100644 --- a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart +++ b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart @@ -3,53 +3,54 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; -import '../config_provider/config.dart' show Config, Declarations; +import '../config_provider/config.dart' show Declarations; +import '../context.dart'; import 'ast.dart'; class ApplyConfigFiltersVisitation extends Visitation { - final Config config; + final Context context; final directlyIncluded = {}; final indirectlyIncluded = {}; - ApplyConfigFiltersVisitation(this.config); + ApplyConfigFiltersVisitation(this.context); void _visitImpl(Binding node, Declarations filters) { node.visitChildren(visitor); if (node.originalName == '') return; - if (config.typedefTypeMappings.containsKey(node.usr)) return; + if (context.importedTypesByUsr.containsKey(node.usr)) return; if (filters.include(node)) directlyIncluded.add(node); } @override - void visitStruct(Struct node) => _visitImpl(node, config.structs); + void visitStruct(Struct node) => _visitImpl(node, context.config.structs); @override - void visitUnion(Union node) => _visitImpl(node, config.unions); + void visitUnion(Union node) => _visitImpl(node, context.config.unions); @override void visitEnumClass(EnumClass node) { if (node.isAnonymous) return; - _visitImpl(node, config.enums); + _visitImpl(node, context.config.enums); } @override void visitCppClass(CppClass node) { - final cppClasses = config.cpp?.classes; + final cppClasses = context.config.cpp?.classes; if (cppClasses == null) return; _visitImpl(node, cppClasses); } @override - void visitFunc(Func node) => _visitImpl(node, config.functions); + void visitFunc(Func node) => _visitImpl(node, context.config.functions); @override void visitMacroConstant(MacroConstant node) => - _visitImpl(node, config.macros); + _visitImpl(node, context.config.macros); @override void visitObjCInterface(ObjCInterface node) { if (node.unavailable) return; - final objcInterfaces = config.objectiveC?.interfaces; + final objcInterfaces = context.config.objectiveC?.interfaces; if (objcInterfaces == null) return; if (!node.isInternal) { @@ -71,7 +72,7 @@ class ApplyConfigFiltersVisitation extends Visitation { @override void visitObjCCategory(ObjCCategory node) { - final objcCategories = config.objectiveC?.categories; + final objcCategories = context.config.objectiveC?.categories; if (objcCategories == null) return; node.filterMethods((m) { if (m.unavailable) return false; @@ -84,7 +85,7 @@ class ApplyConfigFiltersVisitation extends Visitation { @override void visitObjCProtocol(ObjCProtocol node) { if (node.unavailable) return; - final objcProtocols = config.objectiveC?.protocols; + final objcProtocols = context.config.objectiveC?.protocols; if (objcProtocols == null) return; node.filterMethods((m) { @@ -102,21 +103,21 @@ class ApplyConfigFiltersVisitation extends Visitation { @override void visitUnnamedEnumConstant(UnnamedEnumConstant node) => - _visitImpl(node, config.unnamedEnums); + _visitImpl(node, context.config.unnamedEnums); @override - void visitGlobal(Global node) => _visitImpl(node, config.globals); + void visitGlobal(Global node) => _visitImpl(node, context.config.globals); @override void visitConstant(Constant node) { // MacroConstant and UnnamedEnumConstant have their own overrides, so this // only applies to base Constants (e.g. from static const variables). - _visitImpl(node, config.globals); + _visitImpl(node, context.config.globals); } @override void visitTypealias(Typealias node) { if (node.isAnonymous) return; - _visitImpl(node, config.typedefs); + _visitImpl(node, context.config.typedefs); } } diff --git a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart index e251850ea5..236d65072c 100644 --- a/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart +++ b/pkgs/ffigen/lib/src/visitor/find_transitive_deps.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; -import '../config_provider/config.dart' show Config; +import '../config_provider/config.dart' show FfiGenerator; import 'ast.dart'; @@ -31,7 +31,7 @@ class FindTransitiveDepsVisitation extends Visitation { } class FindDirectTransitiveDepsVisitation extends Visitation { - final Config config; + final FfiGenerator config; final Set includes; final Set directIncludes; final directTransitives = {}; diff --git a/pkgs/ffigen/lib/src/visitor/list_bindings.dart b/pkgs/ffigen/lib/src/visitor/list_bindings.dart index ab07d88893..6f9bfa6888 100644 --- a/pkgs/ffigen/lib/src/visitor/list_bindings.dart +++ b/pkgs/ffigen/lib/src/visitor/list_bindings.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; -import '../config_provider/config.dart' show Config; +import '../config_provider/config.dart' show FfiGenerator; import '../strings.dart' as strings; import 'ast.dart'; @@ -17,7 +17,7 @@ enum _IncludeBehavior { } class ListBindingsVisitation extends Visitation { - final Config config; + final FfiGenerator config; final Set includes; final Set transitives; final Set directTransitives; diff --git a/pkgs/ffigen/lib/src/visitor/opaque_compounds.dart b/pkgs/ffigen/lib/src/visitor/opaque_compounds.dart index 7fa06bbabb..5f873e9574 100644 --- a/pkgs/ffigen/lib/src/visitor/opaque_compounds.dart +++ b/pkgs/ffigen/lib/src/visitor/opaque_compounds.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../code_generator.dart'; -import '../config_provider/config.dart' show Config; +import '../config_provider/config.dart' show FfiGenerator; import '../config_provider/config_types.dart' show CompoundDependencies; import 'ast.dart'; @@ -36,7 +36,7 @@ class FindByValueCompoundsVisitation extends Visitation { } class ClearOpaqueCompoundMembersVisitation extends Visitation { - final Config config; + final FfiGenerator config; final Set byValueCompounds; final Set included; From e46d542f6266dc8c24c4ede51576c76e345e7052 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 14:46:02 +1000 Subject: [PATCH 06/19] Revert "Headers -> Input" This reverts commit 71a5ef1aedb1342950c276a9ae709249c96ce2c0. --- pkgs/code_assets/example/host_name/tool/ffigen.dart | 4 ++-- pkgs/code_assets/example/mini_audio/tool/ffigen.dart | 4 +++- pkgs/code_assets/example/sqlite/tool/ffigen.dart | 2 +- pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart | 2 +- pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart | 2 +- pkgs/code_assets/example/stb_image/tool/ffigen.dart | 4 +++- pkgs/ffigen/README.md | 2 +- pkgs/ffigen/example/add/tool/ffigen.dart | 2 +- pkgs/ffigen/example/objective_c/generate_code.dart | 2 +- pkgs/ffigen/lib/ffigen.dart | 2 +- pkgs/ffigen/lib/src/code_generator/library.dart | 2 +- .../lib/src/code_generator/objc_built_in_functions.dart | 2 +- pkgs/ffigen/lib/src/code_generator/writer.dart | 2 +- pkgs/ffigen/lib/src/config_provider/config.dart | 8 ++++---- pkgs/ffigen/lib/src/config_provider/yaml_config.dart | 2 +- pkgs/ffigen/lib/src/context.dart | 2 +- pkgs/ffigen/lib/src/header_parser/parser.dart | 6 +++--- .../lib/src/header_parser/sub_parsers/macro_parser.dart | 2 +- .../lib/src/header_parser/translation_unit_parser.dart | 2 +- .../collision_tests/reserved_keyword_collision_test.dart | 2 +- pkgs/ffigen/test/config_tests/compiler_opts_test.dart | 2 +- pkgs/ffigen/test/example_tests/libclang_example_test.dart | 2 +- pkgs/ffigen/test/header_parser_tests/record_use_test.dart | 2 +- pkgs/ffigen/test/header_parser_tests/sort_test.dart | 2 +- .../test/large_integration_tests/large_objc_test.dart | 2 +- pkgs/ffigen/test/large_integration_tests/large_test.dart | 6 +++--- .../ffigen/test/native_cpp_test/verify_bindings_test.dart | 4 ++-- pkgs/ffigen/test/native_objc_test/deprecated_test.dart | 2 +- pkgs/ffigen/test/native_objc_test/ns_range_test.dart | 2 +- .../test/native_objc_test/swift_unavailable_test.dart | 2 +- pkgs/ffigen/test/native_objc_test/transitive_test.dart | 2 +- .../treeshaking_dylib_record_use/tool/ffigen.dart | 4 ++-- pkgs/swiftgen/lib/src/generator.dart | 2 +- 33 files changed, 47 insertions(+), 43 deletions(-) diff --git a/pkgs/code_assets/example/host_name/tool/ffigen.dart b/pkgs/code_assets/example/host_name/tool/ffigen.dart index f434f8488e..3d191a6305 100644 --- a/pkgs/code_assets/example/host_name/tool/ffigen.dart +++ b/pkgs/code_assets/example/host_name/tool/ffigen.dart @@ -12,7 +12,7 @@ void main() { final FfiGenerator generator; if (Platform.isWindows) { generator = FfiGenerator( - input: Input(entryPoints: [packageRoot.resolve('src/windows.h')]), + headers: Headers(entryPoints: [packageRoot.resolve('src/windows.h')]), functions: functions, output: Output( dartFile: packageRoot.resolve('lib/src/third_party/windows.dart'), @@ -26,7 +26,7 @@ void main() { ); } else { generator = FfiGenerator( - input: Input(entryPoints: [packageRoot.resolve('src/unix.h')]), + headers: Headers(entryPoints: [packageRoot.resolve('src/unix.h')]), functions: functions, output: Output( dartFile: packageRoot.resolve('lib/src/third_party/unix.dart'), diff --git a/pkgs/code_assets/example/mini_audio/tool/ffigen.dart b/pkgs/code_assets/example/mini_audio/tool/ffigen.dart index a6d3a005dd..980d449568 100644 --- a/pkgs/code_assets/example/mini_audio/tool/ffigen.dart +++ b/pkgs/code_assets/example/mini_audio/tool/ffigen.dart @@ -9,7 +9,9 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - input: Input(entryPoints: [packageRoot.resolve('third_party/miniaudio.h')]), + headers: Headers( + entryPoints: [packageRoot.resolve('third_party/miniaudio.h')], + ), functions: Functions( include: (decl) => { 'ma_engine_init', diff --git a/pkgs/code_assets/example/sqlite/tool/ffigen.dart b/pkgs/code_assets/example/sqlite/tool/ffigen.dart index ec52a7bbcf..034b15b38a 100644 --- a/pkgs/code_assets/example/sqlite/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - input: Input( + headers: Headers( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions( diff --git a/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart b/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart index 41f92e40a3..96e9d1a029 100644 --- a/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite_no_link/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - input: Input( + headers: Headers( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions.includeSet({'sqlite3_libversion'}), diff --git a/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart b/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart index 41f92e40a3..96e9d1a029 100644 --- a/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart +++ b/pkgs/code_assets/example/sqlite_prebuilt/tool/ffigen.dart @@ -9,7 +9,7 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - input: Input( + headers: Headers( entryPoints: [packageRoot.resolve('third_party/sqlite/sqlite3.h')], ), functions: Functions.includeSet({'sqlite3_libversion'}), diff --git a/pkgs/code_assets/example/stb_image/tool/ffigen.dart b/pkgs/code_assets/example/stb_image/tool/ffigen.dart index 253397714b..a1ed4b0a3b 100644 --- a/pkgs/code_assets/example/stb_image/tool/ffigen.dart +++ b/pkgs/code_assets/example/stb_image/tool/ffigen.dart @@ -9,7 +9,9 @@ import 'package:ffigen/ffigen.dart'; void main() { final packageRoot = Platform.script.resolve('../'); FfiGenerator( - input: Input(entryPoints: [packageRoot.resolve('third_party/stb_image.h')]), + headers: Headers( + entryPoints: [packageRoot.resolve('third_party/stb_image.h')], + ), functions: Functions( include: (decl) => {'stbi_info'}.contains(decl.originalName), recordUse: (_) => true, diff --git a/pkgs/ffigen/README.md b/pkgs/ffigen/README.md index 5e237bf0a1..190f275cc4 100644 --- a/pkgs/ffigen/README.md +++ b/pkgs/ffigen/README.md @@ -64,7 +64,7 @@ app has been created via `dart create ffigen_example`. // Required. Output path for the generated bindings. output: Output(dartFile: packageRoot.resolve('lib/add.g.dart')), // Optional. Where to look for header files. - input: Input(entryPoints: [packageRoot.resolve('src/add.h')]), + headers: Headers(entryPoints: [packageRoot.resolve('src/add.h')]), // Optional. What functions to generate bindings for. functions: Functions.includeSet({'add'}), ).generate(); diff --git a/pkgs/ffigen/example/add/tool/ffigen.dart b/pkgs/ffigen/example/add/tool/ffigen.dart index c8689b3166..e87def4258 100644 --- a/pkgs/ffigen/example/add/tool/ffigen.dart +++ b/pkgs/ffigen/example/add/tool/ffigen.dart @@ -8,7 +8,7 @@ import 'package:ffigen/ffigen.dart'; FfiGenerator getConfig(Uri packageRoot) { return FfiGenerator( output: Output(dartFile: packageRoot.resolve('lib/add.g.dart')), - input: Input(entryPoints: [packageRoot.resolve('src/add.h')]), + headers: Headers(entryPoints: [packageRoot.resolve('src/add.h')]), functions: Functions.includeSet({'add'}), ); } diff --git a/pkgs/ffigen/example/objective_c/generate_code.dart b/pkgs/ffigen/example/objective_c/generate_code.dart index 6c729474d0..f4091a58e9 100644 --- a/pkgs/ffigen/example/objective_c/generate_code.dart +++ b/pkgs/ffigen/example/objective_c/generate_code.dart @@ -8,7 +8,7 @@ import 'package:ffigen/ffigen.dart'; import 'package:logging/logging.dart'; final config = FfiGenerator( - input: Input( + headers: Headers( // The entryPoints are the files that FFIgen should scan to find the APIs // you want to generate bindings for. You can use the macSdkPath or // iosSdkPath getters to find the Apple SDKs. diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index da396ee043..05a0813cc3 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -31,7 +31,7 @@ export 'src/config_provider.dart' FfiGenerator, Functions, Globals, - Input, + Headers, Interfaces, Macros, NativeExternalBindings, diff --git a/pkgs/ffigen/lib/src/code_generator/library.dart b/pkgs/ffigen/lib/src/code_generator/library.dart index 1397560478..337f97a1b9 100644 --- a/pkgs/ffigen/lib/src/code_generator/library.dart +++ b/pkgs/ffigen/lib/src/code_generator/library.dart @@ -37,7 +37,7 @@ class Library { // ignore: deprecated_member_use_from_same_package context.config.objectiveC?.generateForPackageObjectiveC ?? false, silenceEnumWarning: context.config.enums.silenceWarning, - nativeEntryPoints: context.config.input.entryPoints + nativeEntryPoints: context.config.headers.entryPoints .map((uri) => uri.toFilePath()) .toList(), context: context, diff --git a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart index 83a73067f8..cb9b405afb 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_built_in_functions.dart @@ -239,7 +239,7 @@ class ObjCBuiltInFunctions { // a hash of parts of the config. static String _libraryIdFromConfigHash(FfiGenerator config) => fnvHash32( [ - ...config.input.entryPoints, + ...config.headers.entryPoints, config.output.dartFile, config.output.objCFile, ].map((uri) => path.basename(uri.toFilePath())).join('\n'), diff --git a/pkgs/ffigen/lib/src/code_generator/writer.dart b/pkgs/ffigen/lib/src/code_generator/writer.dart index b9c8f1e199..69cfaef49a 100644 --- a/pkgs/ffigen/lib/src/code_generator/writer.dart +++ b/pkgs/ffigen/lib/src/code_generator/writer.dart @@ -419,7 +419,7 @@ id objc_retainBlock(id); final s = StringBuffer(); final outDir = p.dirname(outFilename); // Emit each entry-point header exactly once. - for (final header in context.config.input.entryPoints) { + for (final header in context.config.headers.entryPoints) { s.write('#include "${p.relative(header.toFilePath(), from: outDir)}"\n'); } s.write(r''' diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 032a9a6a33..13dd1b2b2c 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -16,7 +16,7 @@ import 'config_types.dart'; // TODO: Add a code snippet example. final class FfiGenerator { /// The configuration for header parsing of [FfiGenerator]. - final Input input; + final Headers headers; /// Configuration for enums. final Enums enums; @@ -72,7 +72,7 @@ final class FfiGenerator { final Uri? libclangDylib; const FfiGenerator({ - this.input = const Input(), + this.headers = const Headers(), this.enums = Enums.excludeAll, this.functions = Functions.excludeAll, this.globals = Globals.excludeAll, @@ -100,7 +100,7 @@ final class FfiGenerator { } /// The configuration for header parsing of [FfiGenerator]. -final class Input { +final class Headers { /// Path to headers. May not contain globs. final List entryPoints; @@ -116,7 +116,7 @@ final class Input { /// Where to ignore compiler warnings/errors in source header files. final bool ignoreSourceErrors; - const Input({ + const Headers({ this.entryPoints = const [], this.include = _includeDefault, this.compilerOptions, diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index f5941a6d4c..9a338b1f4b 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1227,7 +1227,7 @@ final class YamlConfig { } FfiGenerator configAdapter() => FfiGenerator( - input: Input( + headers: Headers( compilerOptions: compilerOpts, entryPoints: entryPoints, include: shouldIncludeHeader, diff --git a/pkgs/ffigen/lib/src/context.dart b/pkgs/ffigen/lib/src/context.dart index 8a271883a9..f3c4aed542 100644 --- a/pkgs/ffigen/lib/src/context.dart +++ b/pkgs/ffigen/lib/src/context.dart @@ -30,7 +30,7 @@ class Context { final reportedCommentRanges = <((String, int), (String, int))>{}; final libs = LibraryImports(); late final compilerOpts = - config.input.compilerOptions ?? defaultCompilerOpts(logger); + config.headers.compilerOptions ?? defaultCompilerOpts(logger); final Scope rootScope = Scope.createRoot('root'); final Scope rootObjCScope = Scope.createRoot('objc_root'); late final ExtraSymbols extraSymbols; diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index b4c5b60aac..389917d687 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -72,12 +72,12 @@ List parseToBindings(Context context) { final bindings = {}; // Log all headers for user. - context.logger.info('Input Headers: ${config.input.entryPoints}'); + context.logger.info('Input Headers: ${config.headers.entryPoints}'); final tuList = >[]; // Parse all translation units from entry points. - for (final headerLocationUri in config.input.entryPoints) { + for (final headerLocationUri in config.headers.entryPoints) { final headerLocation = headerLocationUri.toFilePath(); context.logger.fine('Creating TranslationUnit for header: $headerLocation'); @@ -114,7 +114,7 @@ List parseToBindings(Context context) { 'The compiler found warnings/errors in source files.', ); context.logger.warning('This will likely generate invalid bindings.'); - if (config.input.ignoreSourceErrors) { + if (config.headers.ignoreSourceErrors) { context.logger.warning( 'Ignored source errors. (User supplied --ignore-source-errors)', ); diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart index e700f7330a..bc93a75224 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart @@ -196,7 +196,7 @@ File createFileForMacros(Context context) { // Write file contents. final sb = StringBuffer(); - for (final h in context.config.input.entryPoints) { + for (final h in context.config.headers.entryPoints) { final fullHeaderPath = File(h.toFilePath()).absolute.path; sb.writeln('#include "$fullHeaderPath"'); } diff --git a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart index 36534af6e0..8d4022f31d 100644 --- a/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/translation_unit_parser.dart @@ -26,7 +26,7 @@ Set parseTranslationUnit( translationUnitCursor.visitChildren((cursor) { final file = cursor.sourceFileName(); if (file.isEmpty) return; - if (headers[file] ??= context.config.input.include(Uri.file(file))) { + if (headers[file] ??= context.config.headers.include(Uri.file(file))) { try { logger.finest('rootCursorVisitor: ${cursor.completeStringRepr()}'); switch (clang.clang_getCursorKind(cursor)) { diff --git a/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart b/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart index 2274be87c6..cc5e3a8195 100644 --- a/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart +++ b/pkgs/ffigen/test/collision_tests/reserved_keyword_collision_test.dart @@ -21,7 +21,7 @@ void main() { style: const DynamicLibraryBindings(), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/config_tests/compiler_opts_test.dart b/pkgs/ffigen/test/config_tests/compiler_opts_test.dart index 8559faba45..d844f95412 100644 --- a/pkgs/ffigen/test/config_tests/compiler_opts_test.dart +++ b/pkgs/ffigen/test/config_tests/compiler_opts_test.dart @@ -37,7 +37,7 @@ ${strings.compilerOptsAuto}: ${strings.includeCStdLib}: false '''); expect( - config.input.compilerOptions, + config.headers.compilerOptions, equals([if (Platform.isMacOS) '-Wno-nullability-completeness']), ); }); diff --git a/pkgs/ffigen/test/example_tests/libclang_example_test.dart b/pkgs/ffigen/test/example_tests/libclang_example_test.dart index 6396f06945..22dd0a0c0e 100644 --- a/pkgs/ffigen/test/example_tests/libclang_example_test.dart +++ b/pkgs/ffigen/test/example_tests/libclang_example_test.dart @@ -28,7 +28,7 @@ void main() { // compiler options. It can't use absolute paths because it's checked in // yaml code. To support concurrent tests, we can't set Directory.current. // As a workaround, add an extra '-I' option that uses the absolute path. - generator.input.compilerOptions!.add( + generator.headers.compilerOptions!.add( '-I${path.join(packagePathForTests, 'third_party/libclang/include')}', ); diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index bf0bc1ee13..f0dfd22fac 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -16,7 +16,7 @@ void main() { p.join('test', 'header_parser_tests', 'record_use.h'), ); final generator = FfiGenerator( - input: Input(entryPoints: [Uri.file(headerFile)]), + headers: Headers(entryPoints: [Uri.file(headerFile)]), functions: Functions( include: (decl) => true, recordUse: (decl) => true, diff --git a/pkgs/ffigen/test/header_parser_tests/sort_test.dart b/pkgs/ffigen/test/header_parser_tests/sort_test.dart index 437ef2f928..92a6c79023 100644 --- a/pkgs/ffigen/test/header_parser_tests/sort_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/sort_test.dart @@ -19,7 +19,7 @@ void main() { testContext( FfiGenerator( output: Output(dartFile: Uri.file('unused')), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart index 24dbc4c571..1eb46cf241 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_objc_test.dart @@ -72,7 +72,7 @@ void main() { const forceIncludedProtocols = {'NSTextLocation'}; final generator = FfiGenerator( - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index 359e3f5008..af7a35a51f 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart @@ -39,7 +39,7 @@ void main() { wrapperDocComment: 'Bindings to LibClang.', ), ), - input: Input( + headers: Headers( compilerOptions: [...defaultCompilerOpts(logger), '-I$includeDir'], entryPoints: [ Uri.file( @@ -133,7 +133,7 @@ void main() { wrapperDocComment: 'Bindings to Cjson.', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( @@ -174,7 +174,7 @@ void main() { ), commentType: const CommentType(CommentStyle.any, CommentLength.full), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart b/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart index 67b05eab5e..040580a872 100644 --- a/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart +++ b/pkgs/ffigen/test/native_cpp_test/verify_bindings_test.dart @@ -37,7 +37,7 @@ void main() { assetId: 'package:ffigen/cpp_test', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file(path.join(testDir.path, 'cpp_class_test.h')), Uri.file(path.join(testDir.path, 'finalizer_test_subject.h')), @@ -55,7 +55,7 @@ void main() { assetId: 'package:ffigen/cpp_test', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file(path.join(testDir.path, 'memory_edge_cases.h')), ], diff --git a/pkgs/ffigen/test/native_objc_test/deprecated_test.dart b/pkgs/ffigen/test/native_objc_test/deprecated_test.dart index 8ac506414a..2b86a6fc69 100644 --- a/pkgs/ffigen/test/native_objc_test/deprecated_test.dart +++ b/pkgs/ffigen/test/native_objc_test/deprecated_test.dart @@ -32,7 +32,7 @@ String bindingsForVersion({Versions? iosVers, Versions? macosVers}) { wrapperDocComment: 'Tests API deprecation', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/ns_range_test.dart b/pkgs/ffigen/test/native_objc_test/ns_range_test.dart index 5928169617..6db7b5b2af 100644 --- a/pkgs/ffigen/test/native_objc_test/ns_range_test.dart +++ b/pkgs/ffigen/test/native_objc_test/ns_range_test.dart @@ -34,7 +34,7 @@ void main() { wrapperName: 'NSRangeTestObjCLibrary', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart b/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart index 6e645c3f9c..84aa4a59b1 100644 --- a/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart +++ b/pkgs/ffigen/test/native_objc_test/swift_unavailable_test.dart @@ -35,7 +35,7 @@ void main() { wrapperDocComment: 'Tests SWIFT_UNAVAILABLE annotation', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/ffigen/test/native_objc_test/transitive_test.dart b/pkgs/ffigen/test/native_objc_test/transitive_test.dart index f247a964ac..371987996f 100644 --- a/pkgs/ffigen/test/native_objc_test/transitive_test.dart +++ b/pkgs/ffigen/test/native_objc_test/transitive_test.dart @@ -35,7 +35,7 @@ String generate({ wrapperDocComment: 'Tests transitive inclusion', ), ), - input: Input( + headers: Headers( entryPoints: [ Uri.file( path.join( diff --git a/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart b/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart index f2b4d7873e..1d7b443338 100644 --- a/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart +++ b/pkgs/hooks_runner/test_data/treeshaking_dylib_record_use/tool/ffigen.dart @@ -11,7 +11,7 @@ void main() { // 1. Generate bindings for add.c FfiGenerator( - input: Input( + headers: Headers( entryPoints: [packageRoot.resolve('src/add.c')], ), functions: Functions( @@ -36,7 +36,7 @@ void main() { // 2. Generate bindings for multiply.c FfiGenerator( - input: Input( + headers: Headers( entryPoints: [packageRoot.resolve('src/multiply.c')], ), functions: Functions( diff --git a/pkgs/swiftgen/lib/src/generator.dart b/pkgs/swiftgen/lib/src/generator.dart index b46119c2a3..3baba45778 100644 --- a/pkgs/swiftgen/lib/src/generator.dart +++ b/pkgs/swiftgen/lib/src/generator.dart @@ -119,7 +119,7 @@ extension SwiftGenGenerator on SwiftGenerator { categories: ffigen.objectiveC.categories, externalVersions: ffigen.objectiveC.externalVersions, ), - input: fg.Input( + headers: fg.Headers( entryPoints: [Uri.file(objcHeader)], compilerOptions: [ ...fg.defaultCompilerOpts(logger), From ac40afe22b262893f6b2e8e6ee8e230a3fac5e85 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 14:46:19 +1000 Subject: [PATCH 07/19] Revert "Remove library imports (dead code)" This reverts commit 0be46286e57db4524e7434af554261f4be7577a0. --- pkgs/ffigen/lib/src/code_generator/library.dart | 4 ++++ pkgs/ffigen/lib/src/code_generator/writer.dart | 1 + pkgs/ffigen/lib/src/config_provider/config.dart | 14 ++++++++++++++ .../lib/src/config_provider/yaml_config.dart | 2 ++ 4 files changed, 21 insertions(+) diff --git a/pkgs/ffigen/lib/src/code_generator/library.dart b/pkgs/ffigen/lib/src/code_generator/library.dart index 337f97a1b9..126a389354 100644 --- a/pkgs/ffigen/lib/src/code_generator/library.dart +++ b/pkgs/ffigen/lib/src/code_generator/library.dart @@ -36,6 +36,8 @@ class Library { generateForPackageObjectiveC: // ignore: deprecated_member_use_from_same_package context.config.objectiveC?.generateForPackageObjectiveC ?? false, + // ignore: deprecated_member_use_from_same_package + libraryImports: context.config.libraryImports, silenceEnumWarning: context.config.enums.silenceWarning, nativeEntryPoints: context.config.headers.entryPoints .map((uri) => uri.toFilePath()) @@ -48,6 +50,7 @@ class Library { required List bindings, String? header, bool generateForPackageObjectiveC = false, + List libraryImports = const [], bool silenceEnumWarning = false, List nativeEntryPoints = const [], required Context context, @@ -85,6 +88,7 @@ class Library { noLookUpBindings: noLookUpBindings, classDocComment: description, header: header, + additionalImports: libraryImports.map(context.libs.canonicalize).toList(), generateForPackageObjectiveC: generateForPackageObjectiveC, silenceEnumWarning: silenceEnumWarning, nativeEntryPoints: nativeEntryPoints, diff --git a/pkgs/ffigen/lib/src/code_generator/writer.dart b/pkgs/ffigen/lib/src/code_generator/writer.dart index 69cfaef49a..6a957e6fb6 100644 --- a/pkgs/ffigen/lib/src/code_generator/writer.dart +++ b/pkgs/ffigen/lib/src/code_generator/writer.dart @@ -48,6 +48,7 @@ class Writer { required this.ffiNativeBindings, required this.noLookUpBindings, required this.nativeAssetId, + List additionalImports = const [], this.classDocComment, this.header, required this.generateForPackageObjectiveC, diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 13dd1b2b2c..61ada84dad 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -58,6 +58,15 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; + /// Stores all the library imports specified by user including those for ffi + /// and pkg_ffi. + // TODO(https://github.com/dart-lang/native/issues/2597): Remove this. + @Deprecated( + 'In the future, this shoud be inferred from ImportedTypes. See ' + 'https://github.com/dart-lang/native/issues/2597.', + ) + final List libraryImports; + /// Typedefs imported from other Dart files. @Deprecated( 'This field will change type. See ' @@ -85,6 +94,11 @@ final class FfiGenerator { this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, + @Deprecated( + 'In the future, this shoud be inferred from ImportedTypes. See ' + 'https://github.com/dart-lang/native/issues/2597.', + ) + this.libraryImports = const [], @Deprecated('Only visible for YamlConfig plumbing.') this.libclangDylib, }); diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 9a338b1f4b..dec394b4ba 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1338,6 +1338,8 @@ final class YamlConfig { ) : null, // ignore: deprecated_member_use_from_same_package + libraryImports: libraryImports.values.toList(), + // ignore: deprecated_member_use_from_same_package libclangDylib: libclangDylib, ); } From ed24f4c3f63d3d7d6bf235b569a5a0dee29b5c58 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 15:09:47 +1000 Subject: [PATCH 08/19] clean up --- pkgs/ffigen/lib/src/config_provider/config.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 61ada84dad..4967ebf401 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -58,6 +58,13 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; + /// Types imported from other Dart files. + @Deprecated( + 'This field will change type. See ' + 'https://github.com/dart-lang/native/issues/2595.', + ) + final List importedTypes; + /// Stores all the library imports specified by user including those for ffi /// and pkg_ffi. // TODO(https://github.com/dart-lang/native/issues/2597): Remove this. @@ -67,13 +74,6 @@ final class FfiGenerator { ) final List libraryImports; - /// Typedefs imported from other Dart files. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List importedTypes; - /// Path to the clang library. /// /// Only visible for YamlConfig plumbing. @@ -89,11 +89,11 @@ final class FfiGenerator { this.structs = Structs.excludeAll, this.cpp, this.typedefs = Typedefs.excludeAll, - this.importedTypes = const [], this.unions = Unions.excludeAll, this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, + this.importedTypes = const [], @Deprecated( 'In the future, this shoud be inferred from ImportedTypes. See ' 'https://github.com/dart-lang/native/issues/2597.', From ae82773f877f4b6ce89ae82397b28c9200502808 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 16:12:47 +1000 Subject: [PATCH 09/19] Switch to callbacks for imports --- .../lib/src/config_provider/config.dart | 13 +- .../lib/src/config_provider/yaml_config.dart | 241 +++++++++--------- pkgs/ffigen/lib/src/context.dart | 12 +- .../type_extractor/extractor.dart | 42 +-- .../lib/src/visitor/apply_config_filters.dart | 2 +- .../large_integration_tests/large_test.dart | 5 +- 6 files changed, 158 insertions(+), 157 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 4967ebf401..1601f0df6c 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -58,12 +58,11 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; - /// Types imported from other Dart files. - @Deprecated( - 'This field will change type. See ' - 'https://github.com/dart-lang/native/issues/2595.', - ) - final List importedTypes; + /// Returns an [ImportedType] if the given [Declaration] should be imported + /// from another Dart library, or `null` otherwise. + final ImportedType? Function(Declaration declaration) importType; + + static ImportedType? _defaultImportType(Declaration declaration) => null; /// Stores all the library imports specified by user including those for ffi /// and pkg_ffi. @@ -93,7 +92,7 @@ final class FfiGenerator { this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, - this.importedTypes = const [], + this.importType = _defaultImportType, @Deprecated( 'In the future, this shoud be inferred from ImportedTypes. See ' 'https://github.com/dart-lang/native/issues/2597.', diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index dec394b4ba..5fd8d53d17 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1226,120 +1226,129 @@ final class YamlConfig { ); } - FfiGenerator configAdapter() => FfiGenerator( - headers: Headers( - compilerOptions: compilerOpts, - entryPoints: entryPoints, - include: shouldIncludeHeader, - ignoreSourceErrors: ignoreSourceErrors, - ), - output: Output( - dartFile: output, - objectiveCFile: outputObjC, - symbolFile: symbolFile, - commentType: commentType, - preamble: preamble, - format: formatOutput, - style: ffiNativeConfig.enabled - ? NativeExternalBindings(assetId: ffiNativeConfig.assetId) - : DynamicLibraryBindings( - wrapperName: wrapperName, - wrapperDocComment: wrapperDocComment, - ), - ), - functions: Functions( - include: functionDecl.shouldInclude, - includeSymbolAddress: functionDecl.shouldIncludeSymbolAddress, - rename: functionDecl.rename, - renameMember: functionDecl.renameMember, - varArgs: varArgFunctions, - includeTypedef: shouldExposeFunctionTypedef, - isLeaf: isLeafFunction, - ), - structs: Structs( - include: _structDecl.shouldInclude, - rename: _structDecl.rename, - renameMember: _structDecl.renameMember, - dependencies: _structDependencies, - packingOverride: (decl) => - _structPackingOverride.getOverridenPackValue(decl.originalName), - ), - enums: Enums( - include: _enumClassDecl.shouldInclude, - rename: _enumClassDecl.rename, - renameMember: _enumClassDecl.renameMember, - silenceWarning: silenceEnumWarning, - style: (e, suggestedStyle) { - if (suggestedStyle != null) return suggestedStyle; - return switch (enumShouldBeInt(e)) { - true => EnumStyle.intConstants, - false => EnumStyle.dartEnum, - }; - }, - ), - unions: Unions( - include: _unionDecl.shouldInclude, - rename: _unionDecl.rename, - renameMember: _unionDecl.renameMember, - dependencies: _unionDependencies, - ), - unnamedEnums: UnnamedEnums( - include: _unnamedEnumConstants.shouldInclude, - rename: _unnamedEnumConstants.rename, - ), - globals: Globals( - include: globals.shouldInclude, - includeSymbolAddress: globals.shouldIncludeSymbolAddress, - rename: globals.rename, - ), - macros: Macros(include: macroDecl.shouldInclude, rename: macroDecl.rename), - typedefs: Typedefs( - include: typedefs.shouldInclude, - rename: typedefs.rename, - useSupportedTypedefs: useSupportedTypedefs, - includeUnused: includeUnusedTypedefs, - ), - // ignore: deprecated_member_use_from_same_package - importedTypes: [ - ...typedefTypeMappings.values, - ...structTypeMappings.values, - ...unionTypeMappings.values, - ...nativeTypeMappings.values, - ...usrTypeMappings.values, - ], - objectiveC: language == Language.objc - ? ObjectiveC( - interfaces: Interfaces( - include: objcInterfaces.shouldInclude, - includeMember: objcInterfaces.shouldIncludeMember, - rename: objcInterfaces.rename, - renameMember: objcInterfaces.renameMember, - includeTransitive: includeTransitiveObjCInterfaces, - module: interfaceModule, - ), - protocols: Protocols( - include: objcProtocols.shouldInclude, - includeMember: objcProtocols.shouldIncludeMember, - rename: objcProtocols.rename, - renameMember: objcProtocols.renameMember, - includeTransitive: includeTransitiveObjCProtocols, - module: protocolModule, - ), - categories: Categories( - include: objcCategories.shouldInclude, - includeMember: objcCategories.shouldIncludeMember, - rename: objcCategories.rename, - renameMember: objcCategories.renameMember, - includeTransitive: includeTransitiveObjCCategories, - ), - externalVersions: externalVersions, - // ignore: deprecated_member_use_from_same_package - generateForPackageObjectiveC: generateForPackageObjectiveC, - ) - : null, - // ignore: deprecated_member_use_from_same_package - libraryImports: libraryImports.values.toList(), - // ignore: deprecated_member_use_from_same_package - libclangDylib: libclangDylib, - ); + FfiGenerator configAdapter() { + ImportedType? importType(Declaration decl) { + if (decl.usr.isNotEmpty) { + final importedByUsr = usrTypeMappings[decl.usr]; + if (importedByUsr != null) return importedByUsr; + } + return typedefTypeMappings[decl.originalName] ?? + structTypeMappings[decl.originalName] ?? + unionTypeMappings[decl.originalName] ?? + nativeTypeMappings[decl.originalName]; + } + + return FfiGenerator( + headers: Headers( + compilerOptions: compilerOpts, + entryPoints: entryPoints, + include: shouldIncludeHeader, + ignoreSourceErrors: ignoreSourceErrors, + ), + output: Output( + dartFile: output, + objectiveCFile: outputObjC, + symbolFile: symbolFile, + commentType: commentType, + preamble: preamble, + format: formatOutput, + style: ffiNativeConfig.enabled + ? NativeExternalBindings(assetId: ffiNativeConfig.assetId) + : DynamicLibraryBindings( + wrapperName: wrapperName, + wrapperDocComment: wrapperDocComment, + ), + ), + functions: Functions( + include: functionDecl.shouldInclude, + includeSymbolAddress: functionDecl.shouldIncludeSymbolAddress, + rename: functionDecl.rename, + renameMember: functionDecl.renameMember, + varArgs: varArgFunctions, + includeTypedef: shouldExposeFunctionTypedef, + isLeaf: isLeafFunction, + ), + structs: Structs( + include: _structDecl.shouldInclude, + rename: _structDecl.rename, + renameMember: _structDecl.renameMember, + dependencies: _structDependencies, + packingOverride: (decl) => + _structPackingOverride.getOverridenPackValue(decl.originalName), + ), + enums: Enums( + include: _enumClassDecl.shouldInclude, + rename: _enumClassDecl.rename, + renameMember: _enumClassDecl.renameMember, + silenceWarning: silenceEnumWarning, + style: (e, suggestedStyle) { + if (suggestedStyle != null) return suggestedStyle; + return switch (enumShouldBeInt(e)) { + true => EnumStyle.intConstants, + false => EnumStyle.dartEnum, + }; + }, + ), + unions: Unions( + include: _unionDecl.shouldInclude, + rename: _unionDecl.rename, + renameMember: _unionDecl.renameMember, + dependencies: _unionDependencies, + ), + unnamedEnums: UnnamedEnums( + include: _unnamedEnumConstants.shouldInclude, + rename: _unnamedEnumConstants.rename, + ), + globals: Globals( + include: globals.shouldInclude, + includeSymbolAddress: globals.shouldIncludeSymbolAddress, + rename: globals.rename, + ), + macros: Macros( + include: macroDecl.shouldInclude, + rename: macroDecl.rename, + ), + typedefs: Typedefs( + include: typedefs.shouldInclude, + rename: typedefs.rename, + useSupportedTypedefs: useSupportedTypedefs, + includeUnused: includeUnusedTypedefs, + ), + importType: importType, + objectiveC: language == Language.objc + ? ObjectiveC( + interfaces: Interfaces( + include: objcInterfaces.shouldInclude, + includeMember: objcInterfaces.shouldIncludeMember, + rename: objcInterfaces.rename, + renameMember: objcInterfaces.renameMember, + includeTransitive: includeTransitiveObjCInterfaces, + module: interfaceModule, + ), + protocols: Protocols( + include: objcProtocols.shouldInclude, + includeMember: objcProtocols.shouldIncludeMember, + rename: objcProtocols.rename, + renameMember: objcProtocols.renameMember, + includeTransitive: includeTransitiveObjCProtocols, + module: protocolModule, + ), + categories: Categories( + include: objcCategories.shouldInclude, + includeMember: objcCategories.shouldIncludeMember, + rename: objcCategories.rename, + renameMember: objcCategories.renameMember, + includeTransitive: includeTransitiveObjCCategories, + ), + externalVersions: externalVersions, + // ignore: deprecated_member_use_from_same_package + generateForPackageObjectiveC: generateForPackageObjectiveC, + ) + : null, + // ignore: deprecated_member_use_from_same_package + libraryImports: libraryImports.values.toList(), + // ignore: deprecated_member_use_from_same_package + libclangDylib: libclangDylib, + ); + } } diff --git a/pkgs/ffigen/lib/src/context.dart b/pkgs/ffigen/lib/src/context.dart index f3c4aed542..d0103a1736 100644 --- a/pkgs/ffigen/lib/src/context.dart +++ b/pkgs/ffigen/lib/src/context.dart @@ -19,8 +19,6 @@ import 'header_parser/utils.dart'; class Context { final Logger logger; final FfiGenerator config; - final Map importedTypesByUsr; - final Map importedTypesByName; final CursorIndex cursorIndex; final bindingsIndex = BindingsIndex(); final savedMacros = {}; @@ -37,15 +35,7 @@ class Context { final String tmpDir; Context(this.logger, this.config, {Uri? libclangDylib, String? tmpDir}) - : importedTypesByUsr = { - for (final imported in config.importedTypes) - if (imported.usr != null) imported.usr!: imported, - }, - importedTypesByName = { - for (final imported in config.importedTypes) - imported.nativeType: imported, - }, - cursorIndex = CursorIndex(logger), + : cursorIndex = CursorIndex(logger), tmpDir = tmpDir ?? Directory.systemTemp.createTempSync('ffigen temp dir ').path { diff --git a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart index d596a73866..13cc157a00 100644 --- a/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart +++ b/pkgs/ffigen/lib/src/header_parser/type_extractor/extractor.dart @@ -6,6 +6,7 @@ library; import '../../code_generator.dart'; +import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../../strings.dart' as strings; import '../clang_bindings/clang_bindings.dart' as clang_types; @@ -149,10 +150,11 @@ Type getCodeGenType( if (typeSpellKey.startsWith('const ')) { typeSpellKey = typeSpellKey.replaceFirst('const ', ''); } - if (context.importedTypesByName.containsKey(typeSpellKey)) { - context.logger.fine(' Type $typeSpellKey mapped from type-map.'); - return context.importedTypesByName[typeSpellKey]!; - } else if (cxTypeKindToImportedTypes.containsKey(typeSpellKey)) { + final imported = context.config.importType( + Declaration(usr: '', originalName: typeSpellKey), + ); + if (imported != null) return imported; + if (cxTypeKindToImportedTypes.containsKey(typeSpellKey)) { return cxTypeKindToImportedTypes[typeSpellKey]!; } else { context.logger.fine( @@ -172,10 +174,10 @@ Type? _createTypeFromCursor( final logger = context.logger; final config = context.config; final usr = cursor.usr(); - if (context.importedTypesByUsr.containsKey(usr)) { - logger.fine(' Type $usr mapped from usr'); - return context.importedTypesByUsr[usr]!; - } + final imported = context.config.importType( + Declaration(usr: usr, originalName: cursor.spelling()), + ); + if (imported != null) return imported; switch (cxtype.kind) { case clang_types.CXTypeKind.CXType_Typedef: final spelling = clang.clang_getTypedefName(cxtype).toStringAndDispose(); @@ -185,10 +187,10 @@ Type? _createTypeFromCursor( // those two types are ABI compatible, so just return bool regardless. return BooleanType(); } - if (context.importedTypesByName.containsKey(spelling)) { - logger.fine(' Type $spelling mapped from type-map'); - return context.importedTypesByName[spelling]!; - } + final importedTypedef = context.config.importType( + Declaration(usr: usr, originalName: spelling), + ); + if (importedTypedef != null) return importedTypedef; // Get name from supported typedef name if config allows. if (config.typedefs.useSupportedTypedefs) { if (suportedTypedefToSuportedNativeType.containsKey(spelling)) { @@ -267,16 +269,16 @@ Type? _extractfromRecord( } if (cursorKind == clang_types.CXCursorKind.CXCursor_StructDecl) { - if (context.importedTypesByName.containsKey(declSpelling)) { - logger.fine(' Type Mapped from type-map'); - return context.importedTypesByName[declSpelling]!; - } + final imported = context.config.importType( + Declaration(usr: cursor.usr(), originalName: declSpelling), + ); + if (imported != null) return imported; return parseStructDeclaration(cursor, context); } else if (cursorKind == clang_types.CXCursorKind.CXCursor_UnionDecl) { - if (context.importedTypesByName.containsKey(declSpelling)) { - logger.fine(' Type Mapped from type-map'); - return context.importedTypesByName[declSpelling]!; - } + final imported = context.config.importType( + Declaration(usr: cursor.usr(), originalName: declSpelling), + ); + if (imported != null) return imported; return parseUnionDeclaration(cursor, context); } diff --git a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart index d5e6dcef62..345f28d390 100644 --- a/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart +++ b/pkgs/ffigen/lib/src/visitor/apply_config_filters.dart @@ -17,7 +17,7 @@ class ApplyConfigFiltersVisitation extends Visitation { void _visitImpl(Binding node, Declarations filters) { node.visitChildren(visitor); if (node.originalName == '') return; - if (context.importedTypesByUsr.containsKey(node.usr)) return; + if (context.config.importType(node) != null) return; if (filters.include(node)) directlyIncluded.add(node); } diff --git a/pkgs/ffigen/test/large_integration_tests/large_test.dart b/pkgs/ffigen/test/large_integration_tests/large_test.dart index af7a35a51f..1b5bca17fd 100644 --- a/pkgs/ffigen/test/large_integration_tests/large_test.dart +++ b/pkgs/ffigen/test/large_integration_tests/large_test.dart @@ -68,8 +68,9 @@ void main() { enums: Enums.includeAll, macros: Macros.includeAll, typedefs: Typedefs(include: (_) => true), - // ignore: deprecated_member_use_from_same_package - importedTypes: [ImportedType(ffiImport, 'Int64', 'int', 'time_t')], + importType: (decl) => decl.originalName == 'time_t' + ? ImportedType(ffiImport, 'Int64', 'int', 'time_t') + : null, ); final library = parse(Context(logger, generator)); final context = testContext(); From e210b54f8e724ccf7af6208b30223b888320f497 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Wed, 5 Aug 2026 16:37:00 +1000 Subject: [PATCH 10/19] revert unnecessary ImportedType.usr field --- pkgs/ffigen/lib/src/code_generator/imports.dart | 2 -- pkgs/ffigen/lib/src/config_provider/spec_utils.dart | 1 - 2 files changed, 3 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/imports.dart b/pkgs/ffigen/lib/src/code_generator/imports.dart index 52185caa91..5805ff1819 100644 --- a/pkgs/ffigen/lib/src/code_generator/imports.dart +++ b/pkgs/ffigen/lib/src/code_generator/imports.dart @@ -52,7 +52,6 @@ class ImportedType extends Type { /// Whether the [dartType] is an import from the [libraryImport]. final bool importedDartType; - final String? usr; ImportedType( this.libraryImport, @@ -61,7 +60,6 @@ class ImportedType extends Type { this.nativeType, { this.defaultValue, this.importedDartType = false, - this.usr, }); @override diff --git a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart index 1f7896f2f8..10963e3006 100644 --- a/pkgs/ffigen/lib/src/config_provider/spec_utils.dart +++ b/pkgs/ffigen/lib/src/config_provider/spec_utils.dart @@ -48,7 +48,6 @@ void loadImportedTypes( dartName, name, importedDartType: true, - usr: usr, ); } } From 60caeb86ddd791e93cd4fd4aef420f96499cd88c Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 13:55:54 +1000 Subject: [PATCH 11/19] Renaming AST --- pkgs/ffigen/lib/ffigen.dart | 1 + .../lib/src/code_generator/binding.dart | 3 + .../lib/src/code_generator/compound.dart | 8 +- .../lib/src/code_generator/constant.dart | 7 + .../lib/src/code_generator/cpp_class.dart | 4 + .../lib/src/code_generator/enum_class.dart | 12 +- pkgs/ffigen/lib/src/code_generator/func.dart | 4 + .../ffigen/lib/src/code_generator/global.dart | 4 + .../lib/src/code_generator/objc_category.dart | 4 + .../src/code_generator/objc_interface.dart | 6 +- .../lib/src/code_generator/objc_protocol.dart | 4 + .../ffigen/lib/src/code_generator/struct.dart | 4 + .../lib/src/code_generator/typealias.dart | 4 + pkgs/ffigen/lib/src/code_generator/union.dart | 4 + .../lib/src/config_provider/config.dart | 87 +--- .../lib/src/config_provider/config_types.dart | 2 - .../lib/src/config_provider/yaml_config.dart | 206 +++++++-- pkgs/ffigen/lib/src/header_parser/parser.dart | 6 + .../sub_parsers/classdecl_parser.dart | 11 +- .../sub_parsers/compounddecl_parser.dart | 16 +- .../sub_parsers/enumdecl_parser.dart | 4 +- .../sub_parsers/functiondecl_parser.dart | 19 +- .../sub_parsers/macro_parser.dart | 4 +- .../sub_parsers/objccategorydecl_parser.dart | 13 +- .../sub_parsers/objcinterfacedecl_parser.dart | 20 +- .../sub_parsers/objcprotocoldecl_parser.dart | 13 +- .../sub_parsers/typedefdecl_parser.dart | 5 +- .../sub_parsers/unnamed_enumdecl_parser.dart | 6 +- .../header_parser/sub_parsers/var_parser.dart | 8 +- pkgs/ffigen/lib/src/public_ast.dart | 404 ++++++++++++++++++ .../header_parser_tests/record_use_test.dart | 17 +- .../test/unit_tests/config_util_test.dart | 19 - .../unit_tests/renaming_visitor_test.dart | 301 +++++++++++++ 33 files changed, 1008 insertions(+), 222 deletions(-) create mode 100644 pkgs/ffigen/lib/src/public_ast.dart create mode 100644 pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index da396ee043..b6c3be87d8 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -55,3 +55,4 @@ export 'src/config_provider.dart' macSdkUri, xcodePath, xcodeUri; +export 'src/public_ast.dart' hide PublicAst; diff --git a/pkgs/ffigen/lib/src/code_generator/binding.dart b/pkgs/ffigen/lib/src/code_generator/binding.dart index 5b52c350b1..b9e567cdb6 100644 --- a/pkgs/ffigen/lib/src/code_generator/binding.dart +++ b/pkgs/ffigen/lib/src/code_generator/binding.dart @@ -61,6 +61,9 @@ abstract class Binding extends AstNode implements Declaration { /// Returns the Cpp glue code for this binding, if any. String? toCppBindingString(Writer w) => null; + /// Returns the public AST node wrapper for this binding, or null. + Object? toPublicAstNode() => null; + @override void visit(Visitation visitation) => visitation.visitBinding(this); diff --git a/pkgs/ffigen/lib/src/code_generator/compound.dart b/pkgs/ffigen/lib/src/code_generator/compound.dart index bc13331cac..451c322156 100644 --- a/pkgs/ffigen/lib/src/code_generator/compound.dart +++ b/pkgs/ffigen/lib/src/code_generator/compound.dart @@ -252,8 +252,8 @@ class CompoundMember extends AstNode { final String originalName; final Type type; - final Symbol _symbol; - String get name => _symbol.name; + final Symbol symbol; + String get name => symbol.name; CompoundMember({ String? originalName, @@ -261,12 +261,12 @@ class CompoundMember extends AstNode { required this.type, this.dartDoc, }) : originalName = originalName ?? name, - _symbol = Symbol(name, SymbolKind.field); + symbol = Symbol(name, SymbolKind.field); @override void visitChildren(Visitor visitor) { super.visitChildren(visitor); - visitor.visit(_symbol); + visitor.visit(symbol); visitor.visit(type); } } diff --git a/pkgs/ffigen/lib/src/code_generator/constant.dart b/pkgs/ffigen/lib/src/code_generator/constant.dart index 2bae25cbc0..6f4955b315 100644 --- a/pkgs/ffigen/lib/src/code_generator/constant.dart +++ b/pkgs/ffigen/lib/src/code_generator/constant.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding.dart'; import 'binding_string.dart'; @@ -76,6 +77,9 @@ class UnnamedEnumConstant extends Constant { super.apiAvailability, }); + @override + Object? toPublicAstNode() => public_ast.UnnamedEnumConstant(this); + @override void visit(Visitation visitation) => visitation.visitUnnamedEnumConstant(this); @@ -93,6 +97,9 @@ class MacroConstant extends Constant { super.apiAvailability, }); + @override + Object? toPublicAstNode() => public_ast.MacroConstant(this); + @override void visit(Visitation visitation) => visitation.visitMacroConstant(this); } diff --git a/pkgs/ffigen/lib/src/code_generator/cpp_class.dart b/pkgs/ffigen/lib/src/code_generator/cpp_class.dart index a2e6cb13d8..1366ae0e1a 100644 --- a/pkgs/ffigen/lib/src/code_generator/cpp_class.dart +++ b/pkgs/ffigen/lib/src/code_generator/cpp_class.dart @@ -4,6 +4,7 @@ import '../code_generator.dart'; import '../context.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; @@ -80,6 +81,9 @@ class CppClass extends BindingType with HasLocalScope { required this.fields, }); + @override + Object? toPublicAstNode() => public_ast.CppClass(this); + @override void visit(Visitation visitation) => visitation.visitCppClass(this); diff --git a/pkgs/ffigen/lib/src/code_generator/enum_class.dart b/pkgs/ffigen/lib/src/code_generator/enum_class.dart index ab87bafb05..1dd378a177 100644 --- a/pkgs/ffigen/lib/src/code_generator/enum_class.dart +++ b/pkgs/ffigen/lib/src/code_generator/enum_class.dart @@ -7,6 +7,7 @@ import 'package:collection/collection.dart'; import '../config_provider.dart'; import '../context.dart'; import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'imports.dart'; @@ -72,6 +73,9 @@ class EnumClass extends BindingType with HasLocalScope { }) : nativeType = nativeType ?? intType, enumConstants = enumConstants ?? []; + @override + Object? toPublicAstNode() => isAnonymous ? null : public_ast.EnumClass(this); + /// Returns a string to declare the enum member and any documentation it may /// have had. String _formatValue(EnumConstant ec, {bool asInt = false}) { @@ -300,8 +304,8 @@ class EnumConstant extends AstNode { final String? dartDoc; final int value; - final Symbol _symbol; - String get name => _symbol.name; + final Symbol symbol; + String get name => symbol.name; EnumConstant({ String? originalName, @@ -309,11 +313,11 @@ class EnumConstant extends AstNode { required this.value, this.dartDoc, }) : originalName = originalName ?? name, - _symbol = Symbol(name, SymbolKind.field); + symbol = Symbol(name, SymbolKind.field); @override void visitChildren(Visitor visitor) { super.visitChildren(visitor); - visitor.visit(_symbol); + visitor.visit(symbol); } } diff --git a/pkgs/ffigen/lib/src/code_generator/func.dart b/pkgs/ffigen/lib/src/code_generator/func.dart index 81104a2bf0..39e5c424d5 100644 --- a/pkgs/ffigen/lib/src/code_generator/func.dart +++ b/pkgs/ffigen/lib/src/code_generator/func.dart @@ -5,6 +5,7 @@ import '../code_generator.dart'; import '../context.dart'; import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'local_variables.dart'; @@ -107,6 +108,9 @@ class Func extends LookUpBinding with HasLocalScope { } } + @override + Object? toPublicAstNode() => public_ast.Func(this); + @override BindingString toBindingString(Writer w) { final s = StringBuffer(); diff --git a/pkgs/ffigen/lib/src/code_generator/global.dart b/pkgs/ffigen/lib/src/code_generator/global.dart index 594077eaeb..6e4dc5b31d 100644 --- a/pkgs/ffigen/lib/src/code_generator/global.dart +++ b/pkgs/ffigen/lib/src/code_generator/global.dart @@ -2,6 +2,7 @@ // 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 '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding.dart'; import 'binding_string.dart'; @@ -43,6 +44,9 @@ class Global extends LookUpBinding with HasLocalScope { this.loadFromNativeAsset = false, }) : super(symbol: Symbol(name, SymbolKind.field)); + @override + Object? toPublicAstNode() => public_ast.Global(this); + @override BindingString toBindingString(Writer w) { final s = StringBuffer(); diff --git a/pkgs/ffigen/lib/src/code_generator/objc_category.dart b/pkgs/ffigen/lib/src/code_generator/objc_category.dart index 9dc5235389..b5359f019f 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_category.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_category.dart @@ -5,6 +5,7 @@ import '../code_generator.dart'; import '../context.dart'; import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'scope.dart'; @@ -45,6 +46,9 @@ class ObjCCategory extends NoLookUpBinding with ObjCMethods, HasLocalScope { bool get isObjCImport => context.objCBuiltInFunctions.isBuiltInCategory(originalName); + @override + Object? toPublicAstNode() => public_ast.ObjCCategory(this); + @override BindingString toBindingString(Writer w) { final s = StringBuffer(); diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index 7aca79873c..a450dd6f0c 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -5,6 +5,7 @@ import '../code_generator.dart'; import '../context.dart'; import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'local_variables.dart'; @@ -19,7 +20,7 @@ class ObjCInterface extends BindingType with ObjCMethods, HasLocalScope { bool filled = false; final String? module; - late final NoLookUpBinding classObject; + late final ObjCClassGlobal classObject; late final ObjCInternalGlobal _isKindOfClass; late final ObjCMsgSendFunc _isKindOfClassMsgSend; final protocols = []; @@ -108,6 +109,9 @@ class ObjCInterface extends BindingType with ObjCMethods, HasLocalScope { bool get unavailable => apiAvailability.availability == Availability.none; + @override + Object? toPublicAstNode() => public_ast.ObjCInterface(this); + @override BindingString toBindingString(Writer w) { final context = w.context; diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index 456922be6b..ac6d5d3be6 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -5,6 +5,7 @@ import '../code_generator.dart'; import '../context.dart'; import '../header_parser/sub_parsers/api_availability.dart'; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'local_variables.dart'; @@ -71,6 +72,9 @@ class ObjCProtocol extends BindingType with ObjCMethods, HasLocalScope { bool get unavailable => apiAvailability.availability == Availability.none; + @override + Object? toPublicAstNode() => public_ast.ObjCProtocol(this); + @override BindingString toBindingString(Writer w) { final protocolClass = ObjCBuiltInFunctions.protocolClass.gen(context); diff --git a/pkgs/ffigen/lib/src/code_generator/struct.dart b/pkgs/ffigen/lib/src/code_generator/struct.dart index bf3c3059b6..56941d797d 100644 --- a/pkgs/ffigen/lib/src/code_generator/struct.dart +++ b/pkgs/ffigen/lib/src/code_generator/struct.dart @@ -2,6 +2,7 @@ // 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 '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'compound.dart'; @@ -48,6 +49,9 @@ class Struct extends Compound { @override int? pack; + @override + Object? toPublicAstNode() => public_ast.Struct(this); + @override void visit(Visitation visitation) => visitation.visitStruct(this); } diff --git a/pkgs/ffigen/lib/src/code_generator/typealias.dart b/pkgs/ffigen/lib/src/code_generator/typealias.dart index dbd3687156..602a3e4a21 100644 --- a/pkgs/ffigen/lib/src/code_generator/typealias.dart +++ b/pkgs/ffigen/lib/src/code_generator/typealias.dart @@ -4,6 +4,7 @@ import '../code_generator.dart'; import '../context.dart'; +import '../public_ast.dart' as public_ast; import '../strings.dart' as strings; import '../visitor/ast.dart'; import 'binding_string.dart'; @@ -106,6 +107,9 @@ class Typealias extends BindingType { return pointee.type; } + @override + Object? toPublicAstNode() => public_ast.Typealias(this); + @override BindingString toBindingString(Writer w) { assert(!isAnonymous); diff --git a/pkgs/ffigen/lib/src/code_generator/union.dart b/pkgs/ffigen/lib/src/code_generator/union.dart index 478132431f..7d5c92734f 100644 --- a/pkgs/ffigen/lib/src/code_generator/union.dart +++ b/pkgs/ffigen/lib/src/code_generator/union.dart @@ -2,6 +2,7 @@ // 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 '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'compound.dart'; @@ -45,6 +46,9 @@ class Union extends Compound { @override int? get pack => null; + @override + Object? toPublicAstNode() => public_ast.Union(this); + @override void visit(Visitation visitation) => visitation.visitUnion(this); } diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index 7559ca9ae3..c7bd6eca2d 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -9,6 +9,7 @@ import 'package:meta/meta.dart'; import '../code_generator.dart'; import '../ffigen.dart'; +import '../public_ast.dart'; import 'config_types.dart'; /// The generator that generates bindings for `dart:ffi` from C and Objective-C @@ -58,6 +59,9 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; + /// AST visitors to run on the generated bindings. + final List visitors; + /// Returns an [ImportedType] if the given [Declaration] should be imported /// from another Dart library, or `null` otherwise. final ImportedType? Function(Declaration declaration) importType; @@ -83,6 +87,7 @@ final class FfiGenerator { this.unnamedEnums = UnnamedEnums.excludeAll, this.objectiveC, required this.output, + this.visitors = const [], this.importType = _defaultImportType, @Deprecated('Only visible for YamlConfig plumbing.') this.libclangDylib, }); @@ -181,69 +186,10 @@ final class Declarations { /// The address is exposed as an FFI pointer. final bool Function(Declaration declaration) includeSymbolAddress; - /// 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; - - /// A function to pass to [rename] that doesn't rename the declaration. - static String useOriginalName(Declaration declaration) => - declaration.originalName; - - /// A function to pass to [rename] that applies a rename map. - /// - /// The key of the map is the declaration's `originalName`, and the value is - /// the new name to use. If the declaration is not in the map, it is not - /// renamed. - static String Function(Declaration) renameWithMap( - Map renames, - ) => - (Declaration declaration) => - renames[declaration.originalName] ?? declaration.originalName; - - /// 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; - - /// A function to pass to [renameMember] that doesn't rename the member. - static String useMemberOriginalName(Declaration declaration, String member) => - member; - - /// A function to pass to [renameMember] that applies a rename map. - /// - /// The key of the map is the declaration's `originalName`, and the value is - /// a map from member name to renamed member name. If the declaration is not - /// in the map, or the member isn't in the declaration's map, the member is - /// not renamed. - static String Function(Declaration, String) renameMemberWithMap( - Map> renames, - ) => - (Declaration declaration, String member) => - renames[declaration.originalName]?[member] ?? member; - const Declarations({ this.include = excludeAll, this.includeMember = includeAllMembers, this.includeSymbolAddress = excludeAll, - this.rename = useOriginalName, - this.renameMember = useMemberOriginalName, }); } @@ -277,8 +223,6 @@ final class Enums extends Declarations { const Enums({ super.include, - super.rename, - super.renameMember, this.style = _styleDefault, this.silenceWarning = false, }); @@ -337,8 +281,6 @@ final class Functions extends Declarations { const Functions({ super.include, super.includeSymbolAddress, - super.rename, - super.renameMember, this.includeTypedef = _includeTypedefDefault, this.isLeaf = _isLeafDefault, this.recordUse = _recordUseDefault, @@ -355,7 +297,7 @@ final class Functions extends Declarations { /// Configuration for globals. final class Globals extends Declarations { - const Globals({super.rename, super.include, super.includeSymbolAddress}); + const Globals({super.include, super.includeSymbolAddress}); static const excludeAll = Globals(include: Declarations.excludeAll); @@ -367,7 +309,7 @@ final class Globals extends Declarations { /// Configuration for macros. final class Macros extends Declarations { - const Macros({super.rename, super.include}); + const Macros({super.include}); static const excludeAll = Macros(include: Declarations.excludeAll); @@ -389,8 +331,6 @@ final class Structs extends Declarations { const Structs({ super.include, - super.rename, - super.renameMember, this.dependencies = CompoundDependencies.opaque, this.packingOverride = _packingOverrideDefault, }); @@ -413,7 +353,6 @@ final class Typedefs extends Declarations { final bool useSupportedTypedefs; const Typedefs({ - super.rename, super.include, this.useSupportedTypedefs = true, this.includeUnused = false, @@ -429,7 +368,7 @@ final class Typedefs extends Declarations { /// Configuration for C++ class declarations. final class CppClasses extends Declarations { - const CppClasses({super.include, super.rename, super.renameMember}); + const CppClasses({super.include}); static const excludeAll = CppClasses(include: Declarations.excludeAll); static const includeAll = CppClasses(include: Declarations.includeAll); @@ -453,8 +392,6 @@ final class Unions extends Declarations { const Unions({ super.include, - super.rename, - super.renameMember, this.dependencies = CompoundDependencies.opaque, }); @@ -468,7 +405,7 @@ final class Unions extends Declarations { /// Configuration for unnamed enum constants. final class UnnamedEnums extends Declarations { - const UnnamedEnums({super.include, super.rename, super.renameMember}); + const UnnamedEnums({super.include}); static const excludeAll = UnnamedEnums(include: Declarations.excludeAll); @@ -522,8 +459,6 @@ final class Categories extends Declarations { const Categories({ super.include, super.includeMember, - super.rename, - super.renameMember, this.includeTransitive = true, }); @@ -549,8 +484,6 @@ final class Interfaces extends Declarations { const Interfaces({ super.include, super.includeMember, - super.rename, - super.renameMember, this.includeTransitive = false, this.module = noModule, }); @@ -579,8 +512,6 @@ final class Protocols extends Declarations { const Protocols({ super.include, super.includeMember, - super.rename, - super.renameMember, this.includeTransitive = false, this.module = noModule, }); diff --git a/pkgs/ffigen/lib/src/config_provider/config_types.dart b/pkgs/ffigen/lib/src/config_provider/config_types.dart index 0d356ac7a0..b0179ada00 100644 --- a/pkgs/ffigen/lib/src/config_provider/config_types.dart +++ b/pkgs/ffigen/lib/src/config_provider/config_types.dart @@ -151,8 +151,6 @@ final class YamlDeclarationFilters { include: shouldInclude, includeSymbolAddress: shouldIncludeSymbolAddress, includeMember: shouldIncludeMember, - rename: rename, - renameMember: renameMember, ); } } diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 5a63d0edcb..e28095001a 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -12,6 +12,7 @@ import 'package:package_config/package_config_types.dart'; import 'package:yaml/yaml.dart'; import '../code_generator.dart'; +import '../public_ast.dart' as public_ast; import '../strings.dart' as strings; import 'config.dart'; import 'config_spec.dart'; @@ -1240,6 +1241,7 @@ final class YamlConfig { } return FfiGenerator( + visitors: [YamlConfigAstVisitor(this)], input: Input( compilerOptions: compilerOpts, entryPoints: entryPoints, @@ -1263,24 +1265,18 @@ final class YamlConfig { functions: Functions( include: functionDecl.shouldInclude, includeSymbolAddress: functionDecl.shouldIncludeSymbolAddress, - rename: functionDecl.rename, - renameMember: functionDecl.renameMember, varArgs: varArgFunctions, includeTypedef: shouldExposeFunctionTypedef, isLeaf: isLeafFunction, ), structs: Structs( include: _structDecl.shouldInclude, - rename: _structDecl.rename, - renameMember: _structDecl.renameMember, dependencies: _structDependencies, packingOverride: (decl) => _structPackingOverride.getOverridenPackValue(decl.originalName), ), enums: Enums( include: _enumClassDecl.shouldInclude, - rename: _enumClassDecl.rename, - renameMember: _enumClassDecl.renameMember, silenceWarning: silenceEnumWarning, style: (e, suggestedStyle) { if (suggestedStyle != null) return suggestedStyle; @@ -1292,26 +1288,16 @@ final class YamlConfig { ), unions: Unions( include: _unionDecl.shouldInclude, - rename: _unionDecl.rename, - renameMember: _unionDecl.renameMember, dependencies: _unionDependencies, ), - unnamedEnums: UnnamedEnums( - include: _unnamedEnumConstants.shouldInclude, - rename: _unnamedEnumConstants.rename, - ), + unnamedEnums: UnnamedEnums(include: _unnamedEnumConstants.shouldInclude), globals: Globals( include: globals.shouldInclude, includeSymbolAddress: globals.shouldIncludeSymbolAddress, - rename: globals.rename, - ), - macros: Macros( - include: macroDecl.shouldInclude, - rename: macroDecl.rename, ), + macros: Macros(include: macroDecl.shouldInclude), typedefs: Typedefs( include: typedefs.shouldInclude, - rename: typedefs.rename, useSupportedTypedefs: useSupportedTypedefs, includeUnused: includeUnusedTypedefs, ), @@ -1321,24 +1307,18 @@ final class YamlConfig { interfaces: Interfaces( include: objcInterfaces.shouldInclude, includeMember: objcInterfaces.shouldIncludeMember, - rename: objcInterfaces.rename, - renameMember: objcInterfaces.renameMember, includeTransitive: includeTransitiveObjCInterfaces, module: interfaceModule, ), protocols: Protocols( include: objcProtocols.shouldInclude, includeMember: objcProtocols.shouldIncludeMember, - rename: objcProtocols.rename, - renameMember: objcProtocols.renameMember, includeTransitive: includeTransitiveObjCProtocols, module: protocolModule, ), categories: Categories( include: objcCategories.shouldInclude, includeMember: objcCategories.shouldIncludeMember, - rename: objcCategories.rename, - renameMember: objcCategories.renameMember, includeTransitive: includeTransitiveObjCCategories, ), externalVersions: externalVersions, @@ -1351,3 +1331,181 @@ final class YamlConfig { ); } } + +/// AST Visitor that applies renames configured in [YamlConfig]. +class YamlConfigAstVisitor extends public_ast.Visitor { + final YamlConfig config; + + const YamlConfigAstVisitor(this.config); + + Declaration _decl(String originalName) => + Declaration(usr: '', originalName: originalName); + + @override + void visitFunc(public_ast.Func node) { + final renamed = config.functionDecl.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + final postfix = node.name.startsWith(node.originalName) + ? node.name.substring(node.originalName.length) + : ''; + node.name = renamed + postfix; + } + for (final param in node.params) { + final renamedParam = config.functionDecl.renameMember( + _decl(node.originalName), + param.originalName, + ); + if (renamedParam != param.originalName && renamedParam.isNotEmpty) { + param.name = renamedParam; + } + } + } + + @override + void visitUnnamedEnumConstant(public_ast.UnnamedEnumConstant node) { + final renamed = config.unnamedEnumConstants.rename( + _decl(node.originalName), + ); + if (renamed != node.originalName) { + node.name = renamed; + } + } + + @override + void visitStruct(public_ast.Struct node) { + final renamed = config.structDecl.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final member in node.members) { + final renamedMember = config.structDecl.renameMember( + _decl(node.originalName), + member.originalName, + ); + if (renamedMember != member.originalName) { + member.name = renamedMember; + } + } + } + + @override + void visitUnion(public_ast.Union node) { + final renamed = config.unionDecl.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final member in node.members) { + final renamedMember = config.unionDecl.renameMember( + _decl(node.originalName), + member.originalName, + ); + if (renamedMember != member.originalName) { + member.name = renamedMember; + } + } + } + + @override + void visitEnum(public_ast.EnumClass node) { + final renamed = config.enumClassDecl.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final constant in node.constants) { + final renamedMember = config.enumClassDecl.renameMember( + _decl(node.originalName), + constant.originalName, + ); + if (renamedMember != constant.originalName) { + constant.name = renamedMember; + } + } + } + + @override + void visitGlobal(public_ast.Global node) { + final renamed = config.globals.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + } + + @override + void visitMacro(public_ast.MacroConstant node) { + final renamed = config.macroDecl.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + } + + @override + void visitTypealias(public_ast.Typealias node) { + final renamed = config.typedefs.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + } + + @override + void visitObjCInterface(public_ast.ObjCInterface node) { + final renamed = config.objcInterfaces.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final method in node.methods) { + _renameObjCMethod(method, node.originalName, config.objcInterfaces); + } + } + + @override + void visitObjCProtocol(public_ast.ObjCProtocol node) { + final renamed = config.objcProtocols.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final method in node.methods) { + _renameObjCMethod(method, node.originalName, config.objcProtocols); + } + } + + @override + void visitObjCCategory(public_ast.ObjCCategory node) { + final renamed = config.objcCategories.rename(_decl(node.originalName)); + if (renamed != node.originalName) { + node.name = renamed; + } + for (final method in node.methods) { + _renameObjCMethod(method, node.originalName, config.objcCategories); + } + } + + void _renameObjCMethod( + public_ast.ObjCMethod method, + String declOriginalName, + YamlDeclarationFilters filters, + ) { + if (method.isPropertySetter) return; + + final renamedSelector = filters.renameMember( + _decl(declOriginalName), + method.selector, + ); + + if (renamedSelector == method.selector) return; + + final chunks = renamedSelector.split(':'); + final correctNumParams = chunks.length == method.params.length + 1; + final lastChunkIsEmpty = chunks.length == 1 || chunks.last.isEmpty; + if (correctNumParams && lastChunkIsEmpty) { + method.name = chunks[0]; + for (var i = 1; i < method.params.length; ++i) { + method.params[i].name = chunks[i]; + } + } else { + method.name = renamedSelector.replaceAll(':', '_'); + for (var i = 1; i < method.params.length; ++i) { + method.params[i].name = method.params[i].originalName; + } + } + } +} diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index b4c5b60aac..9de28cfc79 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -14,6 +14,7 @@ import '../code_generator/scope.dart'; import '../config_provider.dart'; import '../config_provider/utils.dart'; import '../context.dart'; +import '../public_ast.dart' show PublicAst; import '../strings.dart' as strings; import '../visitor/apply_config_filters.dart'; import '../visitor/ast.dart'; @@ -167,6 +168,11 @@ List _findObjectiveCSysroot() => [ List transformBindings(List rawBindings, Context context) { final config = context.config; + final publicAst = PublicAst(rawBindings); + for (final visitor in context.config.visitors) { + publicAst.accept(visitor); + } + final allBindings = visit( context, FindTransitiveDepsVisitation(), diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/classdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/classdecl_parser.dart index 64d9f92041..bbf538ee49 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/classdecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/classdecl_parser.dart @@ -72,7 +72,7 @@ CppClass? parseClassDeclaration(Context context, clang_types.CXCursor cursor) { availability: apiAvailability.dartDoc, ), originalName: className, - name: cppClasses.rename(decl), + name: className, context: context, methods: methods, fields: [], @@ -107,7 +107,7 @@ void _parseAnyMethod( return; } - final className = context.config.cpp!.classes.rename(classDecl); + final className = classDecl.originalName; final symbol = switch (kind) { CppMethodKind.constructor => '${className}_new', CppMethodKind.method => '${className}_$methodName', @@ -135,12 +135,7 @@ List? _parseParameters( Declaration classDecl, ) { final logger = context.logger; - var i = 0; - final parsed = parseParameters( - context, - cursor, - renameFn: (paramName) => paramName.isEmpty ? 'arg${i++}' : paramName, - ); + final parsed = parseParameters(context, cursor); if (parsed.hasIncompleteStruct || parsed.hasUnimplementedType) { logger.fine(' Unsupported parameter type'); return null; diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart index 23e01f33b1..3bd22b2c04 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/compounddecl_parser.dart @@ -4,7 +4,6 @@ import '../../code_generator.dart'; import '../../config_provider/config.dart'; -import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../../strings.dart' as strings; import '../clang_bindings/clang_bindings.dart' as clang_types; @@ -71,9 +70,6 @@ class _ParsedCompound { return maxChildAlignment > alignment; } - Declarations get compoundConfig => - compound is Struct ? context.config.structs : context.config.unions; - /// Returns pack value of a struct depending on config, returns null for no /// packing. int? get packValue { @@ -136,7 +132,6 @@ Compound? _parseCompoundDeclaration( return null; } - final decl = Declaration(usr: usr, originalName: declName); final Compound compound; if (declName.isEmpty) { cursor = context.cursorIndex.getDefinition(cursor); @@ -160,7 +155,7 @@ Compound? _parseCompoundDeclaration( compound = constructor( usr: usr, originalName: declName, - name: configDecl.rename(decl), + name: declName, dartDoc: getCursorDocComment( context, cursor, @@ -271,11 +266,6 @@ void _compoundMembersVisitor( _ParsedCompound parsed, ) { final context = parsed.context; - final compoundConf = parsed.compoundConfig; - final decl = Declaration( - usr: parsed.compound.usr, - originalName: parsed.compound.originalName, - ); try { switch (cursor.kind) { case clang_types.CXCursorKind.CXCursor_FieldDecl: @@ -315,7 +305,7 @@ void _compoundMembersVisitor( indent: nesting.length + commentPrefix.length, ), originalName: cursor.spelling(), - name: compoundConf.renameMember(decl, cursor.spelling()), + name: cursor.spelling(), type: mt, ), ); @@ -350,7 +340,7 @@ void _compoundMembersVisitor( indent: nesting.length + commentPrefix.length, ), originalName: spelling, - name: compoundConf.renameMember(decl, spelling), + name: spelling, type: mt, ), ); 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 ffd58fa9c5..a8494cb5e6 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 @@ -65,7 +65,7 @@ EnumClass parseEnumDeclaration(clang_types.CXCursor cursor, Context context) { availability: apiAvailability.dartDoc, ), originalName: enumName, - name: config.enums.rename(decl), + name: enumName, nativeType: nativeType, context: context, apiAvailability: apiAvailability, @@ -84,7 +84,7 @@ EnumClass parseEnumDeclaration(clang_types.CXCursor cursor, Context context) { indent: nesting.length + commentPrefix.length, ), originalName: child.spelling(), - name: config.enums.renameMember(decl, child.spelling()), + name: child.spelling(), value: enumIntValue, ), ); 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 e5b91200ed..25393c413a 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 @@ -41,15 +41,8 @@ List parseFunctionDeclaration( final returnType = cursor.returnType().toCodeGenType(context); - final ( - :parameters, - :hasIncompleteStruct, - :hasUnimplementedType, - ) = parseParameters( - context, - cursor, - renameFn: (paramName) => config.functions.renameMember(decl, paramName), - ); + final (:parameters, :hasIncompleteStruct, :hasUnimplementedType) = + parseParameters(context, cursor); if (clang.clang_Cursor_isFunctionInlined(cursor) != 0 && clang.clang_Cursor_getStorageClass(cursor) != @@ -120,7 +113,7 @@ List parseFunctionDeclaration( availability: apiAvailability.dartDoc, ), usr: usr, - name: config.functions.rename(decl) + (vaFunc?.postfix ?? ''), + name: funcName + (vaFunc?.postfix ?? ''), originalName: funcName, returnType: returnType, parameters: parameters.map((p) => p.clone()).toList(), @@ -170,14 +163,14 @@ parseParameters( context.logger.finer('Unimplemented type: ${paramType.baseType}'); unimplementedParameterType = true; } - final paramName = paramCursor.spelling(); - final name = renameFn != null ? renameFn(paramName) : paramName; + final spelling = paramCursor.spelling(); + final name = spelling.isEmpty ? 'arg$i' : spelling; final objCConsumed = paramCursor.hasChildWithKind( clang_types.CXCursorKind.CXCursor_NSConsumed, ); parameters.add( Parameter( - originalName: paramName, + originalName: spelling, name: name, type: paramType, objCConsumed: objCConsumed, diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart index e700f7330a..d9930d377b 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/macro_parser.dart @@ -10,7 +10,6 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import '../../code_generator.dart'; -import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; import '../utils.dart'; @@ -23,7 +22,6 @@ void saveMacroDefinition(Context context, clang_types.CXCursor cursor) { return; } final originalMacroName = cursor.spelling(); - final decl = Declaration(usr: macroUsr, originalName: originalMacroName); if (clang.clang_Cursor_isMacroBuiltin(cursor) == 0 && clang.clang_Cursor_isMacroFunctionLike(cursor) == 0) { // Parse macro only if it's not builtin or function-like. @@ -31,7 +29,7 @@ void saveMacroDefinition(Context context, clang_types.CXCursor cursor) { "++++ Saved Macro '$originalMacroName' for later : " '${cursor.completeStringRepr()}', ); - final prefixedName = context.config.macros.rename(decl); + final prefixedName = originalMacroName; bindingsIndex.addMacroToSeen(macroUsr, prefixedName); _saveMacro(prefixedName, macroUsr, originalMacroName, context); } diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objccategorydecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objccategorydecl_parser.dart index 2c44e46d83..0a33b64454 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objccategorydecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objccategorydecl_parser.dart @@ -62,7 +62,7 @@ ObjCCategory? parseObjCCategoryDeclaration( final category = ObjCCategory( usr: usr, originalName: name, - name: objcCategories.rename(decl), + name: name, parent: parentInterface, dartDoc: getCursorDocComment( context, @@ -85,20 +85,13 @@ ObjCCategory? parseObjCCategoryDeclaration( ); break; case clang_types.CXCursorKind.CXCursor_ObjCPropertyDecl: - final (getter, setter) = parseObjCProperty( - context, - child, - decl, - objcCategories, - ); + final (getter, setter) = parseObjCProperty(context, child, decl); category.addMethod(getter); category.addMethod(setter); break; case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl: case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl: - category.addMethod( - parseObjCMethod(context, child, decl, objcCategories), - ); + category.addMethod(parseObjCMethod(context, child, decl)); break; } }); diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart index a6b668add7..603102a4dd 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcinterfacedecl_parser.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import '../../code_generator.dart'; -import '../../config_provider/config.dart'; import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; @@ -39,7 +38,7 @@ Type? parseObjCInterfaceDeclaration( context: context, usr: usr, originalName: name, - name: objcInterfaces.rename(decl), + name: name, module: objcInterfaces.module(decl), dartDoc: getCursorDocComment( context, @@ -67,8 +66,6 @@ void fillObjCInterfaceMethodsIfNeeded( if (itf.filled) return; itf.filled = true; // Break cycles. - final objcInterfaces = context.config.objectiveC!.interfaces; - context.logger.fine( '++++ Filling ObjC interface: ' 'Name: ${itf.originalName}, ${cursor.completeStringRepr()}', @@ -85,18 +82,13 @@ void fillObjCInterfaceMethodsIfNeeded( itf.addProtocol(parseObjCProtocolDeclaration(context, protoCursor)); break; case clang_types.CXCursorKind.CXCursor_ObjCPropertyDecl: - final (getter, setter) = parseObjCProperty( - context, - child, - itfDecl, - objcInterfaces, - ); + final (getter, setter) = parseObjCProperty(context, child, itfDecl); itf.addMethod(getter); itf.addMethod(setter); break; case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl: case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl: - itf.addMethod(parseObjCMethod(context, child, itfDecl, objcInterfaces)); + itf.addMethod(parseObjCMethod(context, child, itfDecl)); break; } }); @@ -144,7 +136,6 @@ void _parseSuperType( Context context, clang_types.CXCursor cursor, Declaration decl, - Declarations filters, ) { final fieldName = cursor.spelling(); final fieldType = cursor.type().toCodeGenType(context); @@ -190,7 +181,7 @@ void _parseSuperType( final getter = ObjCMethod( context: context, originalName: getterName, - name: filters.renameMember(decl, getterName), + name: getterName, dartDoc: dartDoc ?? getterName, kind: ObjCMethodKind.propertyGetter, isClassMethod: isClassMethod, @@ -233,7 +224,6 @@ ObjCMethod? parseObjCMethod( Context context, clang_types.CXCursor cursor, Declaration itfDecl, - Declarations filters, ) { final logger = context.logger; final methodName = cursor.spelling(); @@ -299,7 +289,7 @@ ObjCMethod? parseObjCMethod( return ObjCMethod( context: context, originalName: methodName, - name: filters.renameMember(itfDecl, methodName), + name: methodName, dartDoc: getCursorDocComment( context, cursor, diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart index b5c1f22c33..a618a30f27 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/objcprotocoldecl_parser.dart @@ -63,7 +63,7 @@ ObjCProtocol? parseObjCProtocolDeclaration( context: context, usr: usr, originalName: name, - name: objcProtocols.rename(decl), + name: name, module: objcProtocols.module(decl), dartDoc: getCursorDocComment( context, @@ -91,20 +91,13 @@ ObjCProtocol? parseObjCProtocolDeclaration( } break; case clang_types.CXCursorKind.CXCursor_ObjCPropertyDecl: - final (getter, setter) = parseObjCProperty( - context, - child, - decl, - objcProtocols, - ); + final (getter, setter) = parseObjCProperty(context, child, decl); protocol.addMethod(getter); protocol.addMethod(setter); break; case clang_types.CXCursorKind.CXCursor_ObjCInstanceMethodDecl: case clang_types.CXCursorKind.CXCursor_ObjCClassMethodDecl: - protocol.addMethod( - parseObjCMethod(context, child, decl, objcProtocols), - ); + protocol.addMethod(parseObjCMethod(context, child, decl)); break; } }); diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart index 5b6c40693b..52c8591f31 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/typedefdecl_parser.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import '../../code_generator.dart'; -import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; import '../type_extractor/extractor.dart'; @@ -30,7 +29,6 @@ Typealias parseTypedefDeclaration( clang_types.CXCursor cursor, ) { final logger = context.logger; - final config = context.config; final bindingsIndex = context.bindingsIndex; final name = cursor.spelling(); final usr = cursor.usr(); @@ -38,7 +36,6 @@ Typealias parseTypedefDeclaration( final cachedType = bindingsIndex.getSeenTypealias(usr); if (cachedType != null) return cachedType; - final decl = Declaration(usr: usr, originalName: name); final ct = clang.clang_getTypedefDeclUnderlyingType(cursor); final s = getCodeGenType(context, ct, originalCursor: cursor); @@ -78,7 +75,7 @@ Typealias parseTypedefDeclaration( final type = Typealias( usr: usr, originalName: name, - name: config.typedefs.rename(decl), + name: name, type: s, dartDoc: getCursorDocComment(context, cursor), ); 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 87c6269edb..2dec4a9965 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 @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import '../../code_generator.dart'; -import '../../config_provider/config_types.dart'; import '../../context.dart'; import '../clang_bindings/clang_bindings.dart' as clang_types; import '../utils.dart'; @@ -46,7 +45,6 @@ Constant? _addUnNamedEnumConstant( clang_types.CXCursor cursor, ) { final logger = context.logger; - final config = context.config; final bindingsIndex = context.bindingsIndex; final usr = cursor.usr(); @@ -68,9 +66,7 @@ Constant? _addUnNamedEnumConstant( final constant = UnnamedEnumConstant( usr: usr, originalName: cursor.spelling(), - name: config.unnamedEnums.rename( - Declaration(usr: cursor.usr(), originalName: cursor.spelling()), - ), + name: cursor.spelling(), dartDoc: apiAvailability.dartDoc, rawType: 'int', rawValue: clang.clang_getEnumConstantDeclValue(cursor).toString(), diff --git a/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart b/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart index 6bd83d10ba..2e6da6402f 100644 --- a/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart @@ -41,7 +41,7 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) { constant = Constant( usr: usr, originalName: name, - name: config.globals.rename(decl), + name: name, dartDoc: getCursorDocComment(context, cursor), rawType: 'int', rawValue: value.toString(), @@ -52,7 +52,7 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) { constant = Constant( usr: usr, originalName: name, - name: config.globals.rename(decl), + name: name, dartDoc: getCursorDocComment(context, cursor), rawType: 'double', rawValue: writeDoubleAsString(value), @@ -64,7 +64,7 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) { constant = Constant( usr: usr, originalName: name, - name: config.globals.rename(decl), + name: name, dartDoc: getCursorDocComment(context, cursor), rawType: 'String', rawValue: "'$rawValue'", @@ -101,7 +101,7 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) { final global = Global( originalName: name, - name: config.globals.rename(decl), + name: name, usr: usr, type: type, dartDoc: getCursorDocComment(context, cursor), diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart new file mode 100644 index 0000000000..5c65e5c96f --- /dev/null +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -0,0 +1,404 @@ +// Copyright (c) 2026, 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 'code_generator.dart' as cg; + +/// Abstract base class for all public AST nodes. +abstract class _AstNode { + const _AstNode(); + void accept(Visitor visitor); + void visitChildren(Visitor visitor) {} +} + +/// Base class for AST visitors. +abstract class Visitor { + const Visitor(); + + // ignore: library_private_types_in_public_api + void visitAll(Iterable<_AstNode> nodes) { + for (final node in nodes) { + node.accept(this); + } + } + + void visitFunc(Func node) { + node.visitChildren(this); + } + + void visitStruct(Struct node) { + node.visitChildren(this); + } + + void visitUnion(Union node) { + node.visitChildren(this); + } + + void visitEnum(EnumClass node) { + node.visitChildren(this); + } + + void visitGlobal(Global node) {} + void visitMacro(MacroConstant node) {} + void visitTypealias(Typealias node) {} + + void visitObjCInterface(ObjCInterface node) { + node.visitChildren(this); + } + + void visitObjCProtocol(ObjCProtocol node) { + node.visitChildren(this); + } + + void visitObjCCategory(ObjCCategory node) { + node.visitChildren(this); + } + + void visitCppClass(CppClass node) { + node.visitChildren(this); + } + + void visitField(Field node) {} + void visitEnumConstant(EnumConstant node) {} + void visitUnnamedEnumConstant(UnnamedEnumConstant node) {} + void visitParameter(Parameter node) {} + + void visitObjCMethod(ObjCMethod node) { + node.visitChildren(this); + } + + void visitCppMethod(CppMethod node) { + node.visitChildren(this); + } +} + +/// A container holding the AST node wrappers for public AST traversal. +class PublicAst { + // ignore: library_private_types_in_public_api + final List<_AstNode> nodes; + + PublicAst(List rawBindings) + : nodes = rawBindings + .map((b) => b.toPublicAstNode()) + .whereType<_AstNode>() + .toList(); + + void accept(Visitor visitor) { + visitor.visitAll(nodes); + } +} + +/// Public wrapper for [cg.Func]. +class Func extends _AstNode { + final cg.Func _func; + final List params; + + Func(this._func) + : params = _func.functionType.parameters.map(Parameter.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitFunc(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(params); + } + + String get originalName => _func.originalName; + String get name => _func.symbol.oldName; + set name(String value) { + _func.symbol.oldName = value; + _func.funcVarSymbol.oldName = '_$value'; + } +} + +/// Public wrapper for [cg.Struct]. +class Struct extends _AstNode { + final cg.Struct _struct; + final List members; + + Struct(this._struct) : members = _struct.members.map(Field.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitStruct(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(members); + } + + String get originalName => _struct.originalName; + String get name => _struct.symbol.oldName; + set name(String value) => _struct.symbol.oldName = value; +} + +/// Public wrapper for [cg.Union]. +class Union extends _AstNode { + final cg.Union _union; + final List members; + + Union(this._union) : members = _union.members.map(Field.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitUnion(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(members); + } + + String get originalName => _union.originalName; + String get name => _union.symbol.oldName; + set name(String value) => _union.symbol.oldName = value; +} + +/// Public wrapper for [cg.EnumClass]. +class EnumClass extends _AstNode { + final cg.EnumClass _enumClass; + final List constants; + + EnumClass(this._enumClass) + : constants = _enumClass.enumConstants.map(EnumConstant.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitEnum(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(constants); + } + + String get originalName => _enumClass.originalName; + String get name => _enumClass.symbol.oldName; + set name(String value) => _enumClass.symbol.oldName = value; +} + +/// Public wrapper for [cg.Global]. +class Global extends _AstNode { + final cg.Global _global; + + Global(this._global); + + @override + void accept(Visitor visitor) => visitor.visitGlobal(this); + + String get originalName => _global.originalName; + String get name => _global.symbol.oldName; + set name(String value) => _global.symbol.oldName = value; +} + +/// Public wrapper for [cg.MacroConstant]. +class MacroConstant extends _AstNode { + final cg.MacroConstant _macro; + + MacroConstant(this._macro); + + @override + void accept(Visitor visitor) => visitor.visitMacro(this); + + String get originalName => _macro.originalName; + String get name => _macro.symbol.oldName; + set name(String value) => _macro.symbol.oldName = value; +} + +/// Public wrapper for [cg.Typealias]. +class Typealias extends _AstNode { + final cg.Typealias _typealias; + + Typealias(this._typealias); + + @override + void accept(Visitor visitor) => visitor.visitTypealias(this); + + String get originalName => _typealias.originalName; + String get name => _typealias.symbol.oldName; + set name(String value) => _typealias.symbol.oldName = value; +} + +/// Public wrapper for [cg.ObjCInterface]. +class ObjCInterface extends _AstNode { + final cg.ObjCInterface _interface; + final List methods; + + ObjCInterface(this._interface) + : methods = _interface.methods.map(ObjCMethod.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitObjCInterface(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(methods); + } + + String get originalName => _interface.originalName; + String get name => _interface.symbol.oldName; + set name(String value) { + _interface.symbol.oldName = value; + _interface.classObject.symbol.oldName = '_class_$value'; + _interface.classObject.rawSymbol.oldName = '_class_${value}_raw'; + } +} + +/// Public wrapper for [cg.ObjCProtocol]. +class ObjCProtocol extends _AstNode { + final cg.ObjCProtocol _protocol; + final List methods; + + ObjCProtocol(this._protocol) + : methods = _protocol.methods.map(ObjCMethod.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitObjCProtocol(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(methods); + } + + String get originalName => _protocol.originalName; + String get name => _protocol.symbol.oldName; + set name(String value) => _protocol.symbol.oldName = value; +} + +/// Public wrapper for [cg.ObjCCategory]. +class ObjCCategory extends _AstNode { + final cg.ObjCCategory _category; + final List methods; + + ObjCCategory(this._category) + : methods = _category.methods.map(ObjCMethod.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitObjCCategory(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(methods); + } + + String get originalName => _category.originalName; + String get name => _category.symbol.oldName; + set name(String value) => _category.symbol.oldName = value; +} + +/// Public wrapper for [cg.CppClass]. +class CppClass extends _AstNode { + final cg.CppClass _cppClass; + final List methods; + + CppClass(this._cppClass) + : methods = _cppClass.methods.map(CppMethod.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitCppClass(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(methods); + } + + String get originalName => _cppClass.originalName; + String get name => _cppClass.symbol.oldName; + set name(String value) => _cppClass.symbol.oldName = value; +} + +/// Public wrapper for [cg.CompoundMember]. +class Field extends _AstNode { + final cg.CompoundMember _member; + + Field(this._member); + + @override + void accept(Visitor visitor) => visitor.visitField(this); + + String get originalName => _member.originalName; + String get name => _member.symbol.oldName; + set name(String value) => _member.symbol.oldName = value; +} + +/// Public wrapper for [cg.EnumConstant]. +class EnumConstant extends _AstNode { + final cg.EnumConstant _constant; + + EnumConstant(this._constant); + + @override + void accept(Visitor visitor) => visitor.visitEnumConstant(this); + + String get originalName => _constant.originalName ?? _constant.name; + String get name => _constant.symbol.oldName; + set name(String value) => _constant.symbol.oldName = value; +} + +/// Public wrapper for [cg.Parameter]. +class Parameter extends _AstNode { + final cg.Parameter _parameter; + + Parameter(this._parameter); + + @override + void accept(Visitor visitor) => visitor.visitParameter(this); + + String get originalName => _parameter.originalName; + String get name => _parameter.symbol.oldName; + set name(String value) => _parameter.symbol.oldName = value; +} + +/// Public wrapper for [cg.CppMethod]. +class CppMethod extends _AstNode { + final cg.CppMethod _method; + final List params; + + CppMethod(this._method) + : params = _method.parameters.map(Parameter.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitCppMethod(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(params); + } + + String get originalName => _method.originalName; + String get name => _method.name.oldName; + set name(String value) => _method.name.oldName = value; +} + +/// Public wrapper for [cg.ObjCMethod]. +class ObjCMethod extends _AstNode { + final cg.ObjCMethod _method; + final List params; + + ObjCMethod(this._method) + : params = _method.params.map(Parameter.new).toList(); + + @override + void accept(Visitor visitor) => visitor.visitObjCMethod(this); + + @override + void visitChildren(Visitor visitor) { + visitor.visitAll(params); + } + + String get selector => _method.originalName; + String get originalName => _method.originalName; + String get name => _method.symbol.oldName; + set name(String value) => _method.symbol.oldName = value; + bool get isPropertySetter => _method.kind == cg.ObjCMethodKind.propertySetter; +} + +/// Public wrapper for [cg.UnnamedEnumConstant]. +class UnnamedEnumConstant extends _AstNode { + final cg.UnnamedEnumConstant _constant; + + UnnamedEnumConstant(this._constant); + + @override + void accept(Visitor visitor) => visitor.visitUnnamedEnumConstant(this); + + String get originalName => _constant.originalName; + String get name => _constant.symbol.oldName; + set name(String value) => _constant.symbol.oldName = value; +} diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index bf0bc1ee13..efee4f0d10 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -2,13 +2,25 @@ // 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/config_provider.dart'; +import 'package:ffigen/ffigen.dart'; import 'package:ffigen/src/header_parser.dart' show parse; +import 'package:ffigen/src/public_ast.dart' as public_ast; import 'package:path/path.dart' as p; import 'package:test/test.dart'; import '../test_utils.dart'; +class _RenamingVisitor extends public_ast.Visitor { + const _RenamingVisitor(); + + @override + void visitFunc(public_ast.Func node) { + if (node.originalName == 'sum') { + node.name = 'add'; + } + } +} + void main() { group('record_use_test', () { test('Expected Bindings', () { @@ -20,9 +32,8 @@ void main() { functions: Functions( include: (decl) => true, recordUse: (decl) => true, - rename: (decl) => - decl.originalName == 'sum' ? 'add' : decl.originalName, ), + visitors: const [_RenamingVisitor()], output: Output( dartFile: Uri.file('unused.dart'), style: const NativeExternalBindings(), diff --git a/pkgs/ffigen/test/unit_tests/config_util_test.dart b/pkgs/ffigen/test/unit_tests/config_util_test.dart index b928ed54a4..e7b74fe8b4 100644 --- a/pkgs/ffigen/test/unit_tests/config_util_test.dart +++ b/pkgs/ffigen/test/unit_tests/config_util_test.dart @@ -25,24 +25,5 @@ void main() { expect(includer(decl('goo'), 'bar'), isTrue); expect(includer(decl('goo'), 'baz'), isTrue); }); - - test('renameWithMap', () { - final renamer = Declarations.renameWithMap({'foo': 'bar'}); - expect(renamer(decl('foo')), 'bar'); - expect(renamer(decl('bar')), 'bar'); - expect(renamer(decl('baz')), 'baz'); - }); - - test('renameMemberWithMap', () { - final renamer = Declarations.renameMemberWithMap({ - 'foo': {'bar': 'baz'}, - }); - expect(renamer(decl('foo'), 'bar'), 'baz'); - expect(renamer(decl('foo'), 'baz'), 'baz'); - expect(renamer(decl('foo'), 'bop'), 'bop'); - expect(renamer(decl('goo'), 'bar'), 'bar'); - expect(renamer(decl('goo'), 'baz'), 'baz'); - expect(renamer(decl('goo'), 'bop'), 'bop'); - }); }); } diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart new file mode 100644 index 0000000000..89c0ba5e4a --- /dev/null +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -0,0 +1,301 @@ +// Copyright (c) 2026, 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 'package:ffigen/ffigen.dart' show FfiGenerator, Output, YamlConfig; +import 'package:ffigen/src/code_generator.dart'; +import 'package:ffigen/src/header_parser/sub_parsers/api_availability.dart'; +import 'package:ffigen/src/public_ast.dart' as public_ast; +import 'package:test/test.dart'; +import 'package:yaml/yaml.dart'; + +import '../test_utils.dart'; + +class CustomRenamerVisitor extends public_ast.Visitor { + @override + void visitFunc(public_ast.Func node) { + if (node.originalName == 'c_foo') { + node.name = 'dartFoo'; + } + super.visitFunc(node); + } + + @override + void visitStruct(public_ast.Struct node) { + if (node.originalName == 'c_struct') { + node.name = 'DartStruct'; + } + super.visitStruct(node); + } + + @override + void visitField(public_ast.Field node) { + if (node.originalName == 'field_a') { + node.name = 'renamedFieldA'; + } + } + + @override + void visitEnum(public_ast.EnumClass node) { + if (node.originalName == 'c_enum') { + node.name = 'DartEnum'; + } + super.visitEnum(node); + } + + @override + void visitEnumConstant(public_ast.EnumConstant node) { + if (node.originalName == 'K_VALUE_A') { + node.name = 'valueA'; + } + } + + @override + void visitObjCInterface(public_ast.ObjCInterface node) { + if (node.originalName == 'MyClass') { + node.name = 'RenamedMyClass'; + } + super.visitObjCInterface(node); + } + + @override + void visitObjCMethod(public_ast.ObjCMethod node) { + if (node.selector == 'compare:options:range:') { + node.name = 'customCompare'; + node.params[1].name = 'customOptions'; + node.params[2].name = 'customRange'; + } + } +} + +void main() { + group('RenamingVisitor Tests', () { + test('Top-level and member renames via Custom Visitor', () { + final context = testContext( + FfiGenerator(output: Output(dartFile: Uri.file('out.dart'))), + ); + + final func = Func( + name: 'c_foo', + originalName: 'c_foo', + returnType: voidType, + parameters: [Parameter(name: 'arg_0', type: intType)], + ); + + final struct = Struct( + name: 'c_struct', + originalName: 'c_struct', + context: context, + members: [ + CompoundMember( + name: 'field_a', + originalName: 'field_a', + type: intType, + ), + ], + ); + + final enumClass = EnumClass( + name: 'c_enum', + originalName: 'c_enum', + context: context, + enumConstants: [ + EnumConstant(name: 'K_VALUE_A', originalName: 'K_VALUE_A', value: 0), + ], + ); + + final objcMethod = ObjCMethod( + context: context, + originalName: 'compare:options:range:', + name: 'compare:options:range:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: intType, + family: null, + apiAvailability: ApiAvailability.all, + params: [ + Parameter(name: 'str', type: intType), + Parameter(name: 'opts', type: intType), + Parameter(name: 'rng', type: intType), + ], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + + final objcInterface = ObjCInterface( + context: context, + originalName: 'MyClass', + name: 'MyClass', + apiAvailability: ApiAvailability.all, + )..addMethod(objcMethod); + + final rawBindings = [func, struct, enumClass, objcInterface]; + final publicAst = public_ast.PublicAst(rawBindings); + + expect(func.symbol.oldName, 'c_foo'); + expect(struct.symbol.oldName, 'c_struct'); + expect(struct.members[0].symbol.oldName, 'field_a'); + expect(enumClass.symbol.oldName, 'c_enum'); + expect(enumClass.enumConstants[0].symbol.oldName, 'K_VALUE_A'); + expect(objcInterface.symbol.oldName, 'MyClass'); + expect(objcMethod.symbol.oldName, 'compare'); + expect(objcMethod.params.elementAt(1).symbol.oldName, 'options'); + expect(objcMethod.params.elementAt(2).symbol.oldName, 'range'); + + publicAst.accept(CustomRenamerVisitor()); + + expect(func.symbol.oldName, 'dartFoo'); + expect(struct.symbol.oldName, 'DartStruct'); + expect(struct.members[0].symbol.oldName, 'renamedFieldA'); + expect(enumClass.symbol.oldName, 'DartEnum'); + expect(enumClass.enumConstants[0].symbol.oldName, 'valueA'); + expect(objcInterface.symbol.oldName, 'RenamedMyClass'); + expect(objcMethod.symbol.oldName, 'customCompare'); + expect(objcMethod.params.elementAt(1).symbol.oldName, 'customOptions'); + expect(objcMethod.params.elementAt(2).symbol.oldName, 'customRange'); + }); + + test( + 'ObjC method selector splitting in constructor and visitor overrides', + () { + final context = testContext( + FfiGenerator(output: Output(dartFile: Uri.file('out.dart'))), + ); + + final method = ObjCMethod( + context: context, + originalName: 'doSomething:withArg:andOther:', + name: 'doSomething:withArg:andOther:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: voidType, + family: null, + apiAvailability: ApiAvailability.all, + params: [ + Parameter(name: 'a', type: intType), + Parameter(name: 'b', type: intType), + Parameter(name: 'c', type: intType), + ], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + + expect(method.originalName, 'doSomething:withArg:andOther:'); + expect(method.symbol.oldName, 'doSomething'); + expect(method.params.elementAt(0).symbol.oldName, 'a'); + expect(method.params.elementAt(1).symbol.oldName, 'withArg'); + expect(method.params.elementAt(2).symbol.oldName, 'andOther'); + + final publicAst = public_ast.PublicAst([ + ObjCInterface( + context: context, + originalName: 'TestItf', + name: 'TestItf', + apiAvailability: ApiAvailability.all, + )..addMethod(method), + ]); + + publicAst.accept(CustomRenamerVisitor()); + + expect(method.symbol.oldName, 'doSomething'); + expect(method.params.elementAt(1).symbol.oldName, 'withArg'); + }, + ); + + test('YamlConfigAstVisitor exact, regex, and member renames', () { + final yamlConfig = YamlConfig.fromYaml( + loadYaml(r''' +output: 'unused.dart' +headers: + entry-points: + - 'unused.h' +functions: + rename: + 'c_(.*)': 'dart_$1' + member-rename: + 'c_func': + 'param1': 'renamedParam1' +structs: + rename: + 'my_struct': 'MyStruct' + member-rename: + 'my_struct': + 'old_field': 'newField' +objc-interfaces: + rename: + 'OldClass': 'NewClass' + member-rename: + 'OldClass': + 'foo:bar:': 'customFoo:customBar:' +''') + as YamlMap, + createTestLogger(), + ); + + final generator = yamlConfig.configAdapter(); + expect(generator.visitors.length, 1); + + final context = testContext(generator); + + final func = Func( + name: 'c_func', + originalName: 'c_func', + returnType: voidType, + parameters: [Parameter(name: 'param1', type: intType)], + ); + + final struct = Struct( + name: 'my_struct', + originalName: 'my_struct', + context: context, + members: [ + CompoundMember( + name: 'old_field', + originalName: 'old_field', + type: intType, + ), + ], + ); + + final objcMethod = ObjCMethod( + context: context, + originalName: 'foo:bar:', + name: 'foo:bar:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: voidType, + family: null, + apiAvailability: ApiAvailability.all, + params: [ + Parameter(name: 'a', type: intType), + Parameter(name: 'b', type: intType), + ], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + + final objcInterface = ObjCInterface( + context: context, + originalName: 'OldClass', + name: 'OldClass', + apiAvailability: ApiAvailability.all, + )..addMethod(objcMethod); + + final publicAst = public_ast.PublicAst([func, struct, objcInterface]); + publicAst.accept(generator.visitors.first); + + expect(func.symbol.oldName, 'dart_func'); + expect(func.functionType.parameters[0].symbol.oldName, 'renamedParam1'); + + expect(struct.symbol.oldName, 'MyStruct'); + expect(struct.members[0].symbol.oldName, 'newField'); + + expect(objcInterface.symbol.oldName, 'NewClass'); + expect(objcMethod.symbol.oldName, 'customFoo'); + expect(objcMethod.params.elementAt(1).symbol.oldName, 'customBar'); + }); + }); +} From 19a0c6b9a6db2509e17a283a707e1170bb5ec882 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 14:10:00 +1000 Subject: [PATCH 12/19] clean up --- pkgs/ffigen/lib/src/public_ast.dart | 112 ++++++++-------------------- 1 file changed, 30 insertions(+), 82 deletions(-) diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index 5c65e5c96f..b1b486a717 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -8,7 +8,6 @@ import 'code_generator.dart' as cg; abstract class _AstNode { const _AstNode(); void accept(Visitor visitor); - void visitChildren(Visitor visitor) {} } /// Base class for AST visitors. @@ -22,54 +21,23 @@ abstract class Visitor { } } - void visitFunc(Func node) { - node.visitChildren(this); - } - - void visitStruct(Struct node) { - node.visitChildren(this); - } - - void visitUnion(Union node) { - node.visitChildren(this); - } - - void visitEnum(EnumClass node) { - node.visitChildren(this); - } - + void visitFunc(Func node) {} + void visitStruct(Struct node) {} + void visitUnion(Union node) {} + void visitEnum(EnumClass node) {} void visitGlobal(Global node) {} void visitMacro(MacroConstant node) {} void visitTypealias(Typealias node) {} - - void visitObjCInterface(ObjCInterface node) { - node.visitChildren(this); - } - - void visitObjCProtocol(ObjCProtocol node) { - node.visitChildren(this); - } - - void visitObjCCategory(ObjCCategory node) { - node.visitChildren(this); - } - - void visitCppClass(CppClass node) { - node.visitChildren(this); - } - + void visitObjCInterface(ObjCInterface node) {} + void visitObjCProtocol(ObjCProtocol node) {} + void visitObjCCategory(ObjCCategory node) {} + void visitCppClass(CppClass node) {} void visitField(Field node) {} void visitEnumConstant(EnumConstant node) {} void visitUnnamedEnumConstant(UnnamedEnumConstant node) {} void visitParameter(Parameter node) {} - - void visitObjCMethod(ObjCMethod node) { - node.visitChildren(this); - } - - void visitCppMethod(CppMethod node) { - node.visitChildren(this); - } + void visitObjCMethod(ObjCMethod node) {} + void visitCppMethod(CppMethod node) {} } /// A container holding the AST node wrappers for public AST traversal. @@ -97,10 +65,8 @@ class Func extends _AstNode { : params = _func.functionType.parameters.map(Parameter.new).toList(); @override - void accept(Visitor visitor) => visitor.visitFunc(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitFunc(this); visitor.visitAll(params); } @@ -120,10 +86,8 @@ class Struct extends _AstNode { Struct(this._struct) : members = _struct.members.map(Field.new).toList(); @override - void accept(Visitor visitor) => visitor.visitStruct(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitStruct(this); visitor.visitAll(members); } @@ -140,10 +104,8 @@ class Union extends _AstNode { Union(this._union) : members = _union.members.map(Field.new).toList(); @override - void accept(Visitor visitor) => visitor.visitUnion(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitUnion(this); visitor.visitAll(members); } @@ -161,10 +123,8 @@ class EnumClass extends _AstNode { : constants = _enumClass.enumConstants.map(EnumConstant.new).toList(); @override - void accept(Visitor visitor) => visitor.visitEnum(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitEnum(this); visitor.visitAll(constants); } @@ -224,10 +184,8 @@ class ObjCInterface extends _AstNode { : methods = _interface.methods.map(ObjCMethod.new).toList(); @override - void accept(Visitor visitor) => visitor.visitObjCInterface(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitObjCInterface(this); visitor.visitAll(methods); } @@ -249,10 +207,8 @@ class ObjCProtocol extends _AstNode { : methods = _protocol.methods.map(ObjCMethod.new).toList(); @override - void accept(Visitor visitor) => visitor.visitObjCProtocol(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitObjCProtocol(this); visitor.visitAll(methods); } @@ -270,10 +226,8 @@ class ObjCCategory extends _AstNode { : methods = _category.methods.map(ObjCMethod.new).toList(); @override - void accept(Visitor visitor) => visitor.visitObjCCategory(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitObjCCategory(this); visitor.visitAll(methods); } @@ -291,10 +245,8 @@ class CppClass extends _AstNode { : methods = _cppClass.methods.map(CppMethod.new).toList(); @override - void accept(Visitor visitor) => visitor.visitCppClass(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitCppClass(this); visitor.visitAll(methods); } @@ -354,10 +306,8 @@ class CppMethod extends _AstNode { : params = _method.parameters.map(Parameter.new).toList(); @override - void accept(Visitor visitor) => visitor.visitCppMethod(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitCppMethod(this); visitor.visitAll(params); } @@ -375,10 +325,8 @@ class ObjCMethod extends _AstNode { : params = _method.params.map(Parameter.new).toList(); @override - void accept(Visitor visitor) => visitor.visitObjCMethod(this); - - @override - void visitChildren(Visitor visitor) { + void accept(Visitor visitor) { + visitor.visitObjCMethod(this); visitor.visitAll(params); } From ae13ce97b30a00cf8352c37a1fc49f0bf79b4371 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 15:10:17 +1000 Subject: [PATCH 13/19] nits --- .../lib/src/code_generator/objc_methods.dart | 2 + .../lib/src/config_provider/yaml_config.dart | 108 ++++++++------ pkgs/ffigen/lib/src/public_ast.dart | 54 +++---- .../header_parser_tests/record_use_test.dart | 2 +- .../test/native_objc_test/rename_test.dart | 2 +- .../rename_test_bindings.dart | 4 +- .../unit_tests/renaming_visitor_test.dart | 139 +++++++++++++++++- 7 files changed, 224 insertions(+), 87 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart index 04ee538fb6..554f021aa5 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_methods.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_methods.dart @@ -324,6 +324,8 @@ class ObjCMethod extends AstNode with HasLocalScope { bool get isProperty => kind == ObjCMethodKind.propertyGetter || kind == ObjCMethodKind.propertySetter; + bool get isPropertyGetter => kind == ObjCMethodKind.propertyGetter; + bool get isPropertySetter => kind == ObjCMethodKind.propertySetter; bool get isRequired => !isOptional; bool get isInstanceMethod => !isClassMethod; bool get unavailable => apiAvailability.availability == Availability.none; diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index e28095001a..20c6f4e296 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1338,24 +1338,31 @@ class YamlConfigAstVisitor extends public_ast.Visitor { const YamlConfigAstVisitor(this.config); - Declaration _decl(String originalName) => - Declaration(usr: '', originalName: originalName); + Declaration _decl(String originalName, [String usr = '']) => + Declaration(usr: usr, originalName: originalName); @override void visitFunc(public_ast.Func node) { - final renamed = config.functionDecl.rename(_decl(node.originalName)); - if (renamed != node.originalName) { - final postfix = node.name.startsWith(node.originalName) - ? node.name.substring(node.originalName.length) - : ''; - node.name = renamed + postfix; + final declName = node.name; + final renamed = config.functionDecl.rename(_decl(declName, node.usr)); + if (renamed != declName) { + node.name = renamed; } for (final param in node.params) { - final renamedParam = config.functionDecl.renameMember( - _decl(node.originalName), - param.originalName, + var renamedParam = config.functionDecl.renameMember( + _decl(declName, node.usr), + param.name, ); - if (renamedParam != param.originalName && renamedParam.isNotEmpty) { + if (renamedParam == param.name && param.name.startsWith('arg')) { + final unnamedRenamed = config.functionDecl.renameMember( + _decl(declName, node.usr), + '', + ); + if (unnamedRenamed.isNotEmpty && unnamedRenamed != '') { + renamedParam = unnamedRenamed; + } + } + if (renamedParam != param.name && renamedParam.isNotEmpty) { param.name = renamedParam; } } @@ -1364,25 +1371,26 @@ class YamlConfigAstVisitor extends public_ast.Visitor { @override void visitUnnamedEnumConstant(public_ast.UnnamedEnumConstant node) { final renamed = config.unnamedEnumConstants.rename( - _decl(node.originalName), + _decl(node.name, node.usr), ); - if (renamed != node.originalName) { + if (renamed != node.name) { node.name = renamed; } } @override void visitStruct(public_ast.Struct node) { - final renamed = config.structDecl.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.structDecl.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final member in node.members) { final renamedMember = config.structDecl.renameMember( - _decl(node.originalName), - member.originalName, + _decl(declName, node.usr), + member.name, ); - if (renamedMember != member.originalName) { + if (renamedMember != member.name) { member.name = renamedMember; } } @@ -1390,16 +1398,17 @@ class YamlConfigAstVisitor extends public_ast.Visitor { @override void visitUnion(public_ast.Union node) { - final renamed = config.unionDecl.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.unionDecl.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final member in node.members) { final renamedMember = config.unionDecl.renameMember( - _decl(node.originalName), - member.originalName, + _decl(declName, node.usr), + member.name, ); - if (renamedMember != member.originalName) { + if (renamedMember != member.name) { member.name = renamedMember; } } @@ -1407,16 +1416,17 @@ class YamlConfigAstVisitor extends public_ast.Visitor { @override void visitEnum(public_ast.EnumClass node) { - final renamed = config.enumClassDecl.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.enumClassDecl.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final constant in node.constants) { final renamedMember = config.enumClassDecl.renameMember( - _decl(node.originalName), - constant.originalName, + _decl(declName, node.usr), + constant.name, ); - if (renamedMember != constant.originalName) { + if (renamedMember != constant.name) { constant.name = renamedMember; } } @@ -1424,70 +1434,74 @@ class YamlConfigAstVisitor extends public_ast.Visitor { @override void visitGlobal(public_ast.Global node) { - final renamed = config.globals.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final renamed = config.globals.rename(_decl(node.name, node.usr)); + if (renamed != node.name) { node.name = renamed; } } @override void visitMacro(public_ast.MacroConstant node) { - final renamed = config.macroDecl.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final renamed = config.macroDecl.rename(_decl(node.name, node.usr)); + if (renamed != node.name) { node.name = renamed; } } @override void visitTypealias(public_ast.Typealias node) { - final renamed = config.typedefs.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final renamed = config.typedefs.rename(_decl(node.name, node.usr)); + if (renamed != node.name) { node.name = renamed; } } @override void visitObjCInterface(public_ast.ObjCInterface node) { - final renamed = config.objcInterfaces.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.objcInterfaces.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final method in node.methods) { - _renameObjCMethod(method, node.originalName, config.objcInterfaces); + _renameObjCMethod(method, declName, node.usr, config.objcInterfaces); } } @override void visitObjCProtocol(public_ast.ObjCProtocol node) { - final renamed = config.objcProtocols.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.objcProtocols.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final method in node.methods) { - _renameObjCMethod(method, node.originalName, config.objcProtocols); + _renameObjCMethod(method, declName, node.usr, config.objcProtocols); } } @override void visitObjCCategory(public_ast.ObjCCategory node) { - final renamed = config.objcCategories.rename(_decl(node.originalName)); - if (renamed != node.originalName) { + final declName = node.name; + final renamed = config.objcCategories.rename(_decl(declName, node.usr)); + if (renamed != declName) { node.name = renamed; } for (final method in node.methods) { - _renameObjCMethod(method, node.originalName, config.objcCategories); + _renameObjCMethod(method, declName, node.usr, config.objcCategories); } } void _renameObjCMethod( public_ast.ObjCMethod method, - String declOriginalName, + String declName, + String usr, YamlDeclarationFilters filters, ) { if (method.isPropertySetter) return; final renamedSelector = filters.renameMember( - _decl(declOriginalName), + _decl(declName, usr), method.selector, ); @@ -1504,7 +1518,7 @@ class YamlConfigAstVisitor extends public_ast.Visitor { } else { method.name = renamedSelector.replaceAll(':', '_'); for (var i = 1; i < method.params.length; ++i) { - method.params[i].name = method.params[i].originalName; + method.params[i].name = method.params[i].name; } } } diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index b1b486a717..666bfeeb22 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -35,7 +35,7 @@ abstract class Visitor { void visitField(Field node) {} void visitEnumConstant(EnumConstant node) {} void visitUnnamedEnumConstant(UnnamedEnumConstant node) {} - void visitParameter(Parameter node) {} + void visitParam(Param node) {} void visitObjCMethod(ObjCMethod node) {} void visitCppMethod(CppMethod node) {} } @@ -59,10 +59,10 @@ class PublicAst { /// Public wrapper for [cg.Func]. class Func extends _AstNode { final cg.Func _func; - final List params; + final List params; Func(this._func) - : params = _func.functionType.parameters.map(Parameter.new).toList(); + : params = _func.functionType.parameters.map(Param.new).toList(); @override void accept(Visitor visitor) { @@ -70,7 +70,7 @@ class Func extends _AstNode { visitor.visitAll(params); } - String get originalName => _func.originalName; + String get usr => _func.usr; String get name => _func.symbol.oldName; set name(String value) { _func.symbol.oldName = value; @@ -91,7 +91,7 @@ class Struct extends _AstNode { visitor.visitAll(members); } - String get originalName => _struct.originalName; + String get usr => _struct.usr; String get name => _struct.symbol.oldName; set name(String value) => _struct.symbol.oldName = value; } @@ -109,7 +109,7 @@ class Union extends _AstNode { visitor.visitAll(members); } - String get originalName => _union.originalName; + String get usr => _union.usr; String get name => _union.symbol.oldName; set name(String value) => _union.symbol.oldName = value; } @@ -128,7 +128,7 @@ class EnumClass extends _AstNode { visitor.visitAll(constants); } - String get originalName => _enumClass.originalName; + String get usr => _enumClass.usr; String get name => _enumClass.symbol.oldName; set name(String value) => _enumClass.symbol.oldName = value; } @@ -142,7 +142,7 @@ class Global extends _AstNode { @override void accept(Visitor visitor) => visitor.visitGlobal(this); - String get originalName => _global.originalName; + String get usr => _global.usr; String get name => _global.symbol.oldName; set name(String value) => _global.symbol.oldName = value; } @@ -156,7 +156,7 @@ class MacroConstant extends _AstNode { @override void accept(Visitor visitor) => visitor.visitMacro(this); - String get originalName => _macro.originalName; + String get usr => _macro.usr; String get name => _macro.symbol.oldName; set name(String value) => _macro.symbol.oldName = value; } @@ -170,7 +170,7 @@ class Typealias extends _AstNode { @override void accept(Visitor visitor) => visitor.visitTypealias(this); - String get originalName => _typealias.originalName; + String get usr => _typealias.usr; String get name => _typealias.symbol.oldName; set name(String value) => _typealias.symbol.oldName = value; } @@ -189,7 +189,7 @@ class ObjCInterface extends _AstNode { visitor.visitAll(methods); } - String get originalName => _interface.originalName; + String get usr => _interface.usr; String get name => _interface.symbol.oldName; set name(String value) { _interface.symbol.oldName = value; @@ -212,7 +212,7 @@ class ObjCProtocol extends _AstNode { visitor.visitAll(methods); } - String get originalName => _protocol.originalName; + String get usr => _protocol.usr; String get name => _protocol.symbol.oldName; set name(String value) => _protocol.symbol.oldName = value; } @@ -231,7 +231,7 @@ class ObjCCategory extends _AstNode { visitor.visitAll(methods); } - String get originalName => _category.originalName; + String get usr => _category.usr; String get name => _category.symbol.oldName; set name(String value) => _category.symbol.oldName = value; } @@ -250,7 +250,7 @@ class CppClass extends _AstNode { visitor.visitAll(methods); } - String get originalName => _cppClass.originalName; + String get usr => _cppClass.usr; String get name => _cppClass.symbol.oldName; set name(String value) => _cppClass.symbol.oldName = value; } @@ -264,7 +264,6 @@ class Field extends _AstNode { @override void accept(Visitor visitor) => visitor.visitField(this); - String get originalName => _member.originalName; String get name => _member.symbol.oldName; set name(String value) => _member.symbol.oldName = value; } @@ -278,21 +277,19 @@ class EnumConstant extends _AstNode { @override void accept(Visitor visitor) => visitor.visitEnumConstant(this); - String get originalName => _constant.originalName ?? _constant.name; String get name => _constant.symbol.oldName; set name(String value) => _constant.symbol.oldName = value; } /// Public wrapper for [cg.Parameter]. -class Parameter extends _AstNode { +class Param extends _AstNode { final cg.Parameter _parameter; - Parameter(this._parameter); + Param(this._parameter); @override - void accept(Visitor visitor) => visitor.visitParameter(this); + void accept(Visitor visitor) => visitor.visitParam(this); - String get originalName => _parameter.originalName; String get name => _parameter.symbol.oldName; set name(String value) => _parameter.symbol.oldName = value; } @@ -300,10 +297,9 @@ class Parameter extends _AstNode { /// Public wrapper for [cg.CppMethod]. class CppMethod extends _AstNode { final cg.CppMethod _method; - final List params; + final List params; - CppMethod(this._method) - : params = _method.parameters.map(Parameter.new).toList(); + CppMethod(this._method) : params = _method.parameters.map(Param.new).toList(); @override void accept(Visitor visitor) { @@ -311,7 +307,6 @@ class CppMethod extends _AstNode { visitor.visitAll(params); } - String get originalName => _method.originalName; String get name => _method.name.oldName; set name(String value) => _method.name.oldName = value; } @@ -319,10 +314,9 @@ class CppMethod extends _AstNode { /// Public wrapper for [cg.ObjCMethod]. class ObjCMethod extends _AstNode { final cg.ObjCMethod _method; - final List params; + final List params; - ObjCMethod(this._method) - : params = _method.params.map(Parameter.new).toList(); + ObjCMethod(this._method) : params = _method.params.map(Param.new).toList(); @override void accept(Visitor visitor) { @@ -331,10 +325,10 @@ class ObjCMethod extends _AstNode { } String get selector => _method.originalName; - String get originalName => _method.originalName; String get name => _method.symbol.oldName; set name(String value) => _method.symbol.oldName = value; - bool get isPropertySetter => _method.kind == cg.ObjCMethodKind.propertySetter; + bool get isPropertyGetter => _method.isPropertyGetter; + bool get isPropertySetter => _method.isPropertySetter; } /// Public wrapper for [cg.UnnamedEnumConstant]. @@ -346,7 +340,7 @@ class UnnamedEnumConstant extends _AstNode { @override void accept(Visitor visitor) => visitor.visitUnnamedEnumConstant(this); - String get originalName => _constant.originalName; + String get usr => _constant.usr; String get name => _constant.symbol.oldName; set name(String value) => _constant.symbol.oldName = value; } diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index efee4f0d10..ef0965626b 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -15,7 +15,7 @@ class _RenamingVisitor extends public_ast.Visitor { @override void visitFunc(public_ast.Func node) { - if (node.originalName == 'sum') { + if (node.name == 'sum') { node.name = 'add'; } } diff --git a/pkgs/ffigen/test/native_objc_test/rename_test.dart b/pkgs/ffigen/test/native_objc_test/rename_test.dart index 08910a6a8e..259fff6b6d 100644 --- a/pkgs/ffigen/test/native_objc_test/rename_test.dart +++ b/pkgs/ffigen/test/native_objc_test/rename_test.dart @@ -40,7 +40,7 @@ void main() { test('Renamed method', () { final renamed = Renamed(); - expect(renamed.fooBarBaz(123, y: 456), 579); + expect(renamed.fooBarBaz(123, otherArg: 456), 579); }); test('Renamed property', () { diff --git a/pkgs/ffigen/test/native_objc_test/rename_test_bindings.dart b/pkgs/ffigen/test/native_objc_test/rename_test_bindings.dart index ea954ae1ef..ea453eea06 100644 --- a/pkgs/ffigen/test/native_objc_test/rename_test_bindings.dart +++ b/pkgs/ffigen/test/native_objc_test/rename_test_bindings.dart @@ -94,13 +94,13 @@ extension Renamed$Methods on Renamed { } /// renamedMethod:otherArg: - int fooBarBaz(int x, {required int y}) { + int fooBarBaz(int x, {required int otherArg}) { final _$$ref = object$.ref; return _objc_msgSend_1q0lyci( _$$ref.pointer, _sel_renamedMethod_otherArg_, x, - y, + otherArg, ); } diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart index 89c0ba5e4a..0a90c10fce 100644 --- a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -14,7 +14,7 @@ import '../test_utils.dart'; class CustomRenamerVisitor extends public_ast.Visitor { @override void visitFunc(public_ast.Func node) { - if (node.originalName == 'c_foo') { + if (node.name == 'c_foo') { node.name = 'dartFoo'; } super.visitFunc(node); @@ -22,7 +22,7 @@ class CustomRenamerVisitor extends public_ast.Visitor { @override void visitStruct(public_ast.Struct node) { - if (node.originalName == 'c_struct') { + if (node.name == 'c_struct') { node.name = 'DartStruct'; } super.visitStruct(node); @@ -30,14 +30,14 @@ class CustomRenamerVisitor extends public_ast.Visitor { @override void visitField(public_ast.Field node) { - if (node.originalName == 'field_a') { + if (node.name == 'field_a') { node.name = 'renamedFieldA'; } } @override void visitEnum(public_ast.EnumClass node) { - if (node.originalName == 'c_enum') { + if (node.name == 'c_enum') { node.name = 'DartEnum'; } super.visitEnum(node); @@ -45,14 +45,14 @@ class CustomRenamerVisitor extends public_ast.Visitor { @override void visitEnumConstant(public_ast.EnumConstant node) { - if (node.originalName == 'K_VALUE_A') { + if (node.name == 'K_VALUE_A') { node.name = 'valueA'; } } @override void visitObjCInterface(public_ast.ObjCInterface node) { - if (node.originalName == 'MyClass') { + if (node.name == 'MyClass') { node.name = 'RenamedMyClass'; } super.visitObjCInterface(node); @@ -66,6 +66,13 @@ class CustomRenamerVisitor extends public_ast.Visitor { node.params[2].name = 'customRange'; } } + + @override + void visitParam(public_ast.Param node) { + if (node.name == 'arg_0') { + node.name = 'renamedArg0'; + } + } } void main() { @@ -297,5 +304,125 @@ objc-interfaces: expect(objcMethod.symbol.oldName, 'customFoo'); expect(objcMethod.params.elementAt(1).symbol.oldName, 'customBar'); }); + + test('Public AST nodes expose usr getter', () { + final context = testContext( + FfiGenerator(output: Output(dartFile: Uri.file('out.dart'))), + ); + + final func = Func( + usr: 'c_foo_usr', + name: 'c_foo', + originalName: 'c_foo', + returnType: voidType, + ); + final struct = Struct( + usr: 'c_struct_usr', + name: 'c_struct', + originalName: 'c_struct', + context: context, + ); + final union = Union( + usr: 'c_union_usr', + name: 'c_union', + originalName: 'c_union', + context: context, + ); + final enumClass = EnumClass( + usr: 'c_enum_usr', + name: 'c_enum', + originalName: 'c_enum', + context: context, + ); + final global = Global( + usr: 'c_global_usr', + name: 'c_global', + originalName: 'c_global', + type: intType, + ); + final macro = MacroConstant( + usr: 'c_macro_usr', + name: 'c_macro', + originalName: 'c_macro', + rawType: 'int', + rawValue: '42', + ); + final typealias = Typealias( + usr: 'c_typealias_usr', + name: 'c_typealias', + type: intType, + ); + final objcInterface = ObjCInterface( + usr: 'c_interface_usr', + context: context, + originalName: 'MyClass', + name: 'MyClass', + apiAvailability: ApiAvailability.all, + ); + final objcProtocol = ObjCProtocol( + usr: 'c_protocol_usr', + context: context, + originalName: 'MyProto', + name: 'MyProto', + apiAvailability: ApiAvailability.all, + ); + final objcCategory = ObjCCategory( + usr: 'c_category_usr', + context: context, + originalName: 'MyCat', + name: 'MyCat', + parent: objcInterface, + apiAvailability: ApiAvailability.all, + ); + final cppClass = CppClass( + usr: 'c_cppclass_usr', + name: 'CppClass', + originalName: 'CppClass', + context: context, + methods: [], + fields: [], + ); + final unnamedEnumConst = UnnamedEnumConstant( + usr: 'c_unnamed_usr', + name: 'c_unnamed', + originalName: 'c_unnamed', + rawType: 'int', + rawValue: '0', + ); + + final rawBindings = [ + func, + struct, + union, + enumClass, + global, + macro, + typealias, + objcInterface, + objcProtocol, + objcCategory, + cppClass, + unnamedEnumConst, + ]; + + final publicAst = public_ast.PublicAst(rawBindings); + final nodes = publicAst.nodes; + + expect((nodes[0] as public_ast.Func).usr, 'c_foo_usr'); + expect((nodes[1] as public_ast.Struct).usr, 'c_struct_usr'); + expect((nodes[2] as public_ast.Union).usr, 'c_union_usr'); + expect((nodes[3] as public_ast.EnumClass).usr, 'c_enum_usr'); + expect((nodes[4] as public_ast.Global).usr, 'c_global_usr'); + expect((nodes[5] as public_ast.MacroConstant).usr, 'c_macro_usr'); + expect((nodes[6] as public_ast.Typealias).usr, 'c_typealias_usr'); + expect((nodes[7] as public_ast.ObjCInterface).usr, 'c_interface_usr'); + expect((nodes[8] as public_ast.ObjCProtocol).usr, 'c_protocol_usr'); + expect((nodes[9] as public_ast.ObjCCategory).usr, 'c_category_usr'); + expect((nodes[10] as public_ast.CppClass).usr, 'c_cppclass_usr'); + expect( + (nodes[11] as public_ast.UnnamedEnumConstant).usr, + 'c_unnamed_usr', + ); + }); }); } From 37c01ba063c770785f411fc23b2abe4f8639ad03 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 15:36:49 +1000 Subject: [PATCH 14/19] Inline visitor construction --- .../lib/src/config_provider/yaml_config.dart | 2 +- pkgs/ffigen/lib/src/public_ast.dart | 133 +++++++++++++++++- .../header_parser_tests/record_use_test.dart | 2 +- .../unit_tests/renaming_visitor_test.dart | 63 +++++++++ 4 files changed, 197 insertions(+), 3 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 20c6f4e296..46f78ff7ea 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1336,7 +1336,7 @@ final class YamlConfig { class YamlConfigAstVisitor extends public_ast.Visitor { final YamlConfig config; - const YamlConfigAstVisitor(this.config); + const YamlConfigAstVisitor(this.config) : super.base(); Declaration _decl(String originalName, [String usr = '']) => Declaration(usr: usr, originalName: originalName); diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index 666bfeeb22..fbede4d952 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -12,7 +12,27 @@ abstract class _AstNode { /// Base class for AST visitors. abstract class Visitor { - const Visitor(); + const Visitor.base(); + + factory Visitor({ + void Function(Func) visitFunc, + void Function(Struct) visitStruct, + void Function(Union) visitUnion, + void Function(EnumClass) visitEnum, + void Function(Global) visitGlobal, + void Function(MacroConstant) visitMacro, + void Function(Typealias) visitTypealias, + void Function(ObjCInterface) visitObjCInterface, + void Function(ObjCProtocol) visitObjCProtocol, + void Function(ObjCCategory) visitObjCCategory, + void Function(CppClass) visitCppClass, + void Function(Field) visitField, + void Function(EnumConstant) visitEnumConstant, + void Function(UnnamedEnumConstant) visitUnnamedEnumConstant, + void Function(Param) visitParam, + void Function(ObjCMethod) visitObjCMethod, + void Function(CppMethod) visitCppMethod, + }) = _CallbackVisitor; // ignore: library_private_types_in_public_api void visitAll(Iterable<_AstNode> nodes) { @@ -40,6 +60,117 @@ abstract class Visitor { void visitCppMethod(CppMethod node) {} } +class _CallbackVisitor extends Visitor { + final void Function(Func) _visitFunc; + final void Function(Struct) _visitStruct; + final void Function(Union) _visitUnion; + final void Function(EnumClass) _visitEnum; + final void Function(Global) _visitGlobal; + final void Function(MacroConstant) _visitMacro; + final void Function(Typealias) _visitTypealias; + final void Function(ObjCInterface) _visitObjCInterface; + final void Function(ObjCProtocol) _visitObjCProtocol; + final void Function(ObjCCategory) _visitObjCCategory; + final void Function(CppClass) _visitCppClass; + final void Function(Field) _visitField; + final void Function(EnumConstant) _visitEnumConstant; + final void Function(UnnamedEnumConstant) _visitUnnamedEnumConstant; + final void Function(Param) _visitParam; + final void Function(ObjCMethod) _visitObjCMethod; + final void Function(CppMethod) _visitCppMethod; + + const _CallbackVisitor({ + void Function(Func) visitFunc = _defaultVisit, + void Function(Struct) visitStruct = _defaultVisit, + void Function(Union) visitUnion = _defaultVisit, + void Function(EnumClass) visitEnum = _defaultVisit, + void Function(Global) visitGlobal = _defaultVisit, + void Function(MacroConstant) visitMacro = _defaultVisit, + void Function(Typealias) visitTypealias = _defaultVisit, + void Function(ObjCInterface) visitObjCInterface = _defaultVisit, + void Function(ObjCProtocol) visitObjCProtocol = _defaultVisit, + void Function(ObjCCategory) visitObjCCategory = _defaultVisit, + void Function(CppClass) visitCppClass = _defaultVisit, + void Function(Field) visitField = _defaultVisit, + void Function(EnumConstant) visitEnumConstant = _defaultVisit, + void Function(UnnamedEnumConstant) visitUnnamedEnumConstant = _defaultVisit, + void Function(Param) visitParam = _defaultVisit, + void Function(ObjCMethod) visitObjCMethod = _defaultVisit, + void Function(CppMethod) visitCppMethod = _defaultVisit, + }) : _visitFunc = visitFunc, + _visitStruct = visitStruct, + _visitUnion = visitUnion, + _visitEnum = visitEnum, + _visitGlobal = visitGlobal, + _visitMacro = visitMacro, + _visitTypealias = visitTypealias, + _visitObjCInterface = visitObjCInterface, + _visitObjCProtocol = visitObjCProtocol, + _visitObjCCategory = visitObjCCategory, + _visitCppClass = visitCppClass, + _visitField = visitField, + _visitEnumConstant = visitEnumConstant, + _visitUnnamedEnumConstant = visitUnnamedEnumConstant, + _visitParam = visitParam, + _visitObjCMethod = visitObjCMethod, + _visitCppMethod = visitCppMethod, + super.base(); + + static void _defaultVisit(Object _) {} + + @override + void visitFunc(Func node) => _visitFunc(node); + + @override + void visitStruct(Struct node) => _visitStruct(node); + + @override + void visitUnion(Union node) => _visitUnion(node); + + @override + void visitEnum(EnumClass node) => _visitEnum(node); + + @override + void visitGlobal(Global node) => _visitGlobal(node); + + @override + void visitMacro(MacroConstant node) => _visitMacro(node); + + @override + void visitTypealias(Typealias node) => _visitTypealias(node); + + @override + void visitObjCInterface(ObjCInterface node) => _visitObjCInterface(node); + + @override + void visitObjCProtocol(ObjCProtocol node) => _visitObjCProtocol(node); + + @override + void visitObjCCategory(ObjCCategory node) => _visitObjCCategory(node); + + @override + void visitCppClass(CppClass node) => _visitCppClass(node); + + @override + void visitField(Field node) => _visitField(node); + + @override + void visitEnumConstant(EnumConstant node) => _visitEnumConstant(node); + + @override + void visitUnnamedEnumConstant(UnnamedEnumConstant node) => + _visitUnnamedEnumConstant(node); + + @override + void visitParam(Param node) => _visitParam(node); + + @override + void visitObjCMethod(ObjCMethod node) => _visitObjCMethod(node); + + @override + void visitCppMethod(CppMethod node) => _visitCppMethod(node); +} + /// A container holding the AST node wrappers for public AST traversal. class PublicAst { // ignore: library_private_types_in_public_api diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index ef0965626b..3e2cc09251 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -11,7 +11,7 @@ import 'package:test/test.dart'; import '../test_utils.dart'; class _RenamingVisitor extends public_ast.Visitor { - const _RenamingVisitor(); + const _RenamingVisitor() : super.base(); @override void visitFunc(public_ast.Func node) { diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart index 0a90c10fce..587a23e815 100644 --- a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -12,6 +12,7 @@ import 'package:yaml/yaml.dart'; import '../test_utils.dart'; class CustomRenamerVisitor extends public_ast.Visitor { + CustomRenamerVisitor() : super.base(); @override void visitFunc(public_ast.Func node) { if (node.name == 'c_foo') { @@ -424,5 +425,67 @@ objc-interfaces: 'c_unnamed_usr', ); }); + + test('Visitor callback-based factory constructor', () { + final context = testContext( + FfiGenerator(output: Output(dartFile: Uri.file('out.dart'))), + ); + + final func = Func( + name: 'c_foo', + originalName: 'c_foo', + returnType: voidType, + parameters: [Parameter(name: 'arg_0', type: intType)], + ); + + final struct = Struct( + name: 'c_struct', + originalName: 'c_struct', + context: context, + members: [ + CompoundMember( + name: 'field_a', + originalName: 'field_a', + type: intType, + ), + ], + ); + + final visitedFuncs = []; + final visitedStructs = []; + final visitedParams = []; + + final visitor = public_ast.Visitor( + visitFunc: (node) { + visitedFuncs.add(node.name); + if (node.name == 'c_foo') { + node.name = 'dartFoo'; + } + }, + visitStruct: (node) { + visitedStructs.add(node.name); + if (node.name == 'c_struct') { + node.name = 'DartStruct'; + } + }, + visitParam: (node) { + visitedParams.add(node.name); + if (node.name == 'arg_0') { + node.name = 'renamedArg0'; + } + }, + ); + + final publicAst = public_ast.PublicAst([func, struct]); + publicAst.accept(visitor); + + expect(visitedFuncs, ['c_foo']); + expect(visitedStructs, ['c_struct']); + expect(visitedParams, ['arg_0']); + + expect(func.symbol.oldName, 'dartFoo'); + expect(struct.symbol.oldName, 'DartStruct'); + expect(func.functionType.parameters[0].symbol.oldName, 'renamedArg0'); + }); }); } From 8773112dfce0b49724794d8427a69bae4e8fe6f8 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 16:58:25 +1000 Subject: [PATCH 15/19] wip --- .../lib/src/config_provider/config.dart | 40 ++++- pkgs/ffigen/lib/src/public_ast.dart | 168 ++++++++++++++++-- pkgs/swiftgen/lib/src/config.dart | 4 + pkgs/swiftgen/lib/src/generator.dart | 5 +- 4 files changed, 193 insertions(+), 24 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index c7bd6eca2d..a181cfe517 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -59,7 +59,45 @@ final class FfiGenerator { /// The configuration for outputting bindings. final Output output; - /// AST visitors to run on the generated bindings. + /// AST visitors to run on the generated bindings to perform transformations + /// before Dart code generation occurs. + /// + /// Visitors are executed sequentially in the order they appear in this list. + /// Each visitor can inspect or mutate AST node names and properties (such as + /// renaming functions, parameters, struct fields, enum constants, etc.). + /// + /// Examples: + /// + /// Inline visitor using the constructor callbacks: + /// ```dart + /// FfiGenerator( + /// // ... + /// visitors: [ + /// Visitor( + /// visitFunc: (func) { + /// if (func.name.startsWith('custom_')) { + /// func.name = func.name.substring(7); + /// } + /// }, + /// ), + /// ], + /// ) + /// ``` + /// + /// Custom visitor class extending [Visitor]: + /// ```dart + /// class PrefixStripperVisitor extends Visitor { + /// final String prefix; + /// const PrefixStripperVisitor(this.prefix) : super.base(); + /// + /// @override + /// void visitFunc(Func node) { + /// if (node.name.startsWith(prefix)) { + /// node.name = node.name.substring(prefix.length); + /// } + /// } + /// } + /// ``` final List visitors; /// Returns an [ImportedType] if the given [Declaration] should be imported diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index fbede4d952..a27519c712 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -10,10 +10,18 @@ abstract class _AstNode { void accept(Visitor visitor); } -/// Base class for AST visitors. +/// Base class for AST visitors that inspect and transform AST nodes. +/// +/// Implementations can extend [Visitor] by calling [Visitor.base] or use the +/// [Visitor] factory constructor to provide inline callbacks for specific +/// nodes. abstract class Visitor { + /// Base constructor for subclasses extending [Visitor]. const Visitor.base(); + /// Creates a [Visitor] that delegates visiting to the provided callbacks. + /// + /// Unprovided callbacks default to no-op handlers. factory Visitor({ void Function(Func) visitFunc, void Function(Struct) visitStruct, @@ -171,7 +179,7 @@ class _CallbackVisitor extends Visitor { void visitCppMethod(CppMethod node) => _visitCppMethod(node); } -/// A container holding the AST node wrappers for public AST traversal. +/// A container holding top-level public AST nodes for visitor traversal. class PublicAst { // ignore: library_private_types_in_public_api final List<_AstNode> nodes; @@ -187,11 +195,14 @@ class PublicAst { } } -/// Public wrapper for [cg.Func]. +/// Public AST node representing a C function declaration. class Func extends _AstNode { final cg.Func _func; + + /// The parameters of this function. final List params; + /// Creates a public [Func] AST node wrapper. Func(this._func) : params = _func.functionType.parameters.map(Param.new).toList(); @@ -201,19 +212,27 @@ class Func extends _AstNode { visitor.visitAll(params); } + /// The Unified Symbol Resolution (USR) identifier of this function. String get usr => _func.usr; + + /// The generated Dart name for this function. String get name => _func.symbol.oldName; + + /// Sets the generated Dart name for this function. set name(String value) { _func.symbol.oldName = value; _func.funcVarSymbol.oldName = '_$value'; } } -/// Public wrapper for [cg.Struct]. +/// Public AST node representing a C struct declaration. class Struct extends _AstNode { final cg.Struct _struct; + + /// The fields belonging to this struct. final List members; + /// Creates a public [Struct] AST node wrapper. Struct(this._struct) : members = _struct.members.map(Field.new).toList(); @override @@ -222,16 +241,24 @@ class Struct extends _AstNode { visitor.visitAll(members); } + /// The Unified Symbol Resolution (USR) identifier of this struct. String get usr => _struct.usr; + + /// The generated Dart name for this struct. String get name => _struct.symbol.oldName; + + /// Sets the generated Dart name for this struct. set name(String value) => _struct.symbol.oldName = value; } -/// Public wrapper for [cg.Union]. +/// Public AST node representing a C union declaration. class Union extends _AstNode { final cg.Union _union; + + /// The fields belonging to this union. final List members; + /// Creates a public [Union] AST node wrapper. Union(this._union) : members = _union.members.map(Field.new).toList(); @override @@ -240,16 +267,24 @@ class Union extends _AstNode { visitor.visitAll(members); } + /// The Unified Symbol Resolution (USR) identifier of this union. String get usr => _union.usr; + + /// The generated Dart name for this union. String get name => _union.symbol.oldName; + + /// Sets the generated Dart name for this union. set name(String value) => _union.symbol.oldName = value; } -/// Public wrapper for [cg.EnumClass]. +/// Public AST node representing an enum declaration. class EnumClass extends _AstNode { final cg.EnumClass _enumClass; + + /// The constants belonging to this enum. final List constants; + /// Creates a public [EnumClass] AST node wrapper. EnumClass(this._enumClass) : constants = _enumClass.enumConstants.map(EnumConstant.new).toList(); @@ -259,58 +294,84 @@ class EnumClass extends _AstNode { visitor.visitAll(constants); } + /// The Unified Symbol Resolution (USR) identifier of this enum. String get usr => _enumClass.usr; + + /// The generated Dart name for this enum. String get name => _enumClass.symbol.oldName; + + /// Sets the generated Dart name for this enum. set name(String value) => _enumClass.symbol.oldName = value; } -/// Public wrapper for [cg.Global]. +/// Public AST node representing a C global variable declaration. class Global extends _AstNode { final cg.Global _global; + /// Creates a public [Global] AST node wrapper. Global(this._global); @override void accept(Visitor visitor) => visitor.visitGlobal(this); + /// The Unified Symbol Resolution (USR) identifier of this global variable. String get usr => _global.usr; + + /// The generated Dart name for this global variable. String get name => _global.symbol.oldName; + + /// Sets the generated Dart name for this global variable. set name(String value) => _global.symbol.oldName = value; } -/// Public wrapper for [cg.MacroConstant]. +/// Public AST node representing a C macro constant declaration. class MacroConstant extends _AstNode { final cg.MacroConstant _macro; + /// Creates a public [MacroConstant] AST node wrapper. MacroConstant(this._macro); @override void accept(Visitor visitor) => visitor.visitMacro(this); + /// The Unified Symbol Resolution (USR) identifier of this macro constant. String get usr => _macro.usr; + + /// The generated Dart name for this macro constant. String get name => _macro.symbol.oldName; + + /// Sets the generated Dart name for this macro constant. set name(String value) => _macro.symbol.oldName = value; } -/// Public wrapper for [cg.Typealias]. +/// Public AST node representing a C typedef (type alias) declaration. class Typealias extends _AstNode { final cg.Typealias _typealias; + /// Creates a public [Typealias] AST node wrapper. Typealias(this._typealias); @override void accept(Visitor visitor) => visitor.visitTypealias(this); + /// The Unified Symbol Resolution (USR) identifier of this typedef. String get usr => _typealias.usr; + + /// The generated Dart name for this typedef. String get name => _typealias.symbol.oldName; + + /// Sets the generated Dart name for this typedef. set name(String value) => _typealias.symbol.oldName = value; } -/// Public wrapper for [cg.ObjCInterface]. +/// Public AST node representing an Objective-C interface (class) declaration. class ObjCInterface extends _AstNode { final cg.ObjCInterface _interface; + + /// The methods belonging to this Objective-C interface. final List methods; + /// Creates a public [ObjCInterface] AST node wrapper. ObjCInterface(this._interface) : methods = _interface.methods.map(ObjCMethod.new).toList(); @@ -320,8 +381,14 @@ class ObjCInterface extends _AstNode { visitor.visitAll(methods); } + /// The Unified Symbol Resolution (USR) identifier of this Objective-C + /// interface. String get usr => _interface.usr; + + /// The generated Dart name for this Objective-C interface. String get name => _interface.symbol.oldName; + + /// Sets the generated Dart name for this Objective-C interface. set name(String value) { _interface.symbol.oldName = value; _interface.classObject.symbol.oldName = '_class_$value'; @@ -329,11 +396,14 @@ class ObjCInterface extends _AstNode { } } -/// Public wrapper for [cg.ObjCProtocol]. +/// Public AST node representing an Objective-C protocol declaration. class ObjCProtocol extends _AstNode { final cg.ObjCProtocol _protocol; + + /// The methods belonging to this Objective-C protocol. final List methods; + /// Creates a public [ObjCProtocol] AST node wrapper. ObjCProtocol(this._protocol) : methods = _protocol.methods.map(ObjCMethod.new).toList(); @@ -343,16 +413,25 @@ class ObjCProtocol extends _AstNode { visitor.visitAll(methods); } + /// The Unified Symbol Resolution (USR) identifier of this Objective-C + /// protocol. String get usr => _protocol.usr; + + /// The generated Dart name for this Objective-C protocol. String get name => _protocol.symbol.oldName; + + /// Sets the generated Dart name for this Objective-C protocol. set name(String value) => _protocol.symbol.oldName = value; } -/// Public wrapper for [cg.ObjCCategory]. +/// Public AST node representing an Objective-C category declaration. class ObjCCategory extends _AstNode { final cg.ObjCCategory _category; + + /// The methods belonging to this Objective-C category. final List methods; + /// Creates a public [ObjCCategory] AST node wrapper. ObjCCategory(this._category) : methods = _category.methods.map(ObjCMethod.new).toList(); @@ -362,16 +441,25 @@ class ObjCCategory extends _AstNode { visitor.visitAll(methods); } + /// The Unified Symbol Resolution (USR) identifier of this Objective-C + /// category. String get usr => _category.usr; + + /// The generated Dart name for this Objective-C category. String get name => _category.symbol.oldName; + + /// Sets the generated Dart name for this Objective-C category. set name(String value) => _category.symbol.oldName = value; } -/// Public wrapper for [cg.CppClass]. +/// Public AST node representing a C++ class declaration. class CppClass extends _AstNode { final cg.CppClass _cppClass; + + /// The methods belonging to this C++ class. final List methods; + /// Creates a public [CppClass] AST node wrapper. CppClass(this._cppClass) : methods = _cppClass.methods.map(CppMethod.new).toList(); @@ -381,55 +469,75 @@ class CppClass extends _AstNode { visitor.visitAll(methods); } + /// The Unified Symbol Resolution (USR) identifier of this C++ class. String get usr => _cppClass.usr; + + /// The generated Dart name for this C++ class. String get name => _cppClass.symbol.oldName; + + /// Sets the generated Dart name for this C++ class. set name(String value) => _cppClass.symbol.oldName = value; } -/// Public wrapper for [cg.CompoundMember]. +/// Public AST node representing a field in a struct or union. class Field extends _AstNode { final cg.CompoundMember _member; + /// Creates a public [Field] AST node wrapper. Field(this._member); @override void accept(Visitor visitor) => visitor.visitField(this); + /// The generated Dart name for this field. String get name => _member.symbol.oldName; + + /// Sets the generated Dart name for this field. set name(String value) => _member.symbol.oldName = value; } -/// Public wrapper for [cg.EnumConstant]. +/// Public AST node representing a constant inside a named enum. class EnumConstant extends _AstNode { final cg.EnumConstant _constant; + /// Creates a public [EnumConstant] AST node wrapper. EnumConstant(this._constant); @override void accept(Visitor visitor) => visitor.visitEnumConstant(this); + /// The generated Dart name for this enum constant. String get name => _constant.symbol.oldName; + + /// Sets the generated Dart name for this enum constant. set name(String value) => _constant.symbol.oldName = value; } -/// Public wrapper for [cg.Parameter]. +/// Public AST node representing a function or method parameter. class Param extends _AstNode { final cg.Parameter _parameter; + /// Creates a public [Param] AST node wrapper. Param(this._parameter); @override void accept(Visitor visitor) => visitor.visitParam(this); + /// The generated Dart name for this parameter. String get name => _parameter.symbol.oldName; + + /// Sets the generated Dart name for this parameter. set name(String value) => _parameter.symbol.oldName = value; } -/// Public wrapper for [cg.CppMethod]. +/// Public AST node representing a C++ method declaration. class CppMethod extends _AstNode { final cg.CppMethod _method; + + /// The parameters of this C++ method. final List params; + /// Creates a public [CppMethod] AST node wrapper. CppMethod(this._method) : params = _method.parameters.map(Param.new).toList(); @override @@ -438,15 +546,21 @@ class CppMethod extends _AstNode { visitor.visitAll(params); } + /// The generated Dart name for this C++ method. String get name => _method.name.oldName; + + /// Sets the generated Dart name for this C++ method. set name(String value) => _method.name.oldName = value; } -/// Public wrapper for [cg.ObjCMethod]. +/// Public AST node representing an Objective-C method declaration. class ObjCMethod extends _AstNode { final cg.ObjCMethod _method; + + /// The parameters of this Objective-C method. final List params; + /// Creates a public [ObjCMethod] AST node wrapper. ObjCMethod(this._method) : params = _method.params.map(Param.new).toList(); @override @@ -455,23 +569,39 @@ class ObjCMethod extends _AstNode { visitor.visitAll(params); } + /// The Objective-C method selector string. String get selector => _method.originalName; + + /// The generated Dart name for this Objective-C method. String get name => _method.symbol.oldName; + + /// Sets the generated Dart name for this Objective-C method. set name(String value) => _method.symbol.oldName = value; + + /// Whether this method is a property getter. bool get isPropertyGetter => _method.isPropertyGetter; + + /// Whether this method is a property setter. bool get isPropertySetter => _method.isPropertySetter; } -/// Public wrapper for [cg.UnnamedEnumConstant]. +/// Public AST node representing an unnamed enum constant. class UnnamedEnumConstant extends _AstNode { final cg.UnnamedEnumConstant _constant; + /// Creates a public [UnnamedEnumConstant] AST node wrapper. UnnamedEnumConstant(this._constant); @override void accept(Visitor visitor) => visitor.visitUnnamedEnumConstant(this); + /// The Unified Symbol Resolution (USR) identifier of this unnamed enum + /// constant. String get usr => _constant.usr; + + /// The generated Dart name for this unnamed enum constant. String get name => _constant.symbol.oldName; + + /// Sets the generated Dart name for this unnamed enum constant. set name(String value) => _constant.symbol.oldName = value; } diff --git a/pkgs/swiftgen/lib/src/config.dart b/pkgs/swiftgen/lib/src/config.dart index 62dfec8f01..c1b82acc16 100644 --- a/pkgs/swiftgen/lib/src/config.dart +++ b/pkgs/swiftgen/lib/src/config.dart @@ -243,6 +243,9 @@ class FfiGeneratorOptions { /// [ffigen.FfiGenerator.objectiveC] final ffigen.ObjectiveC objectiveC; + /// [ffigen.FfiGenerator.visitors] + final List visitors; + const FfiGeneratorOptions({ this.functions = ffigen.Functions.excludeAll, this.structs = ffigen.Structs.excludeAll, @@ -253,5 +256,6 @@ class FfiGeneratorOptions { this.macros = ffigen.Macros.excludeAll, this.typedefs = ffigen.Typedefs.excludeAll, this.objectiveC = const ffigen.ObjectiveC(), + this.visitors = const [], }); } diff --git a/pkgs/swiftgen/lib/src/generator.dart b/pkgs/swiftgen/lib/src/generator.dart index b46119c2a3..750a27ca0a 100644 --- a/pkgs/swiftgen/lib/src/generator.dart +++ b/pkgs/swiftgen/lib/src/generator.dart @@ -99,8 +99,6 @@ extension SwiftGenGenerator on SwiftGenerator { interfaces: fg.Interfaces( include: interfaces.include, includeMember: interfaces.includeMember, - rename: interfaces.rename, - renameMember: interfaces.renameMember, includeTransitive: interfaces.includeTransitive, module: interfaces.module != fg.Interfaces.noModule ? interfaces.module @@ -109,8 +107,6 @@ extension SwiftGenGenerator on SwiftGenerator { protocols: fg.Protocols( include: protocols.include, includeMember: protocols.includeMember, - rename: protocols.rename, - renameMember: protocols.renameMember, includeTransitive: protocols.includeTransitive, module: protocols.module != fg.Protocols.noModule ? protocols.module @@ -119,6 +115,7 @@ extension SwiftGenGenerator on SwiftGenerator { categories: ffigen.objectiveC.categories, externalVersions: ffigen.objectiveC.externalVersions, ), + visitors: ffigen.visitors, input: fg.Input( entryPoints: [Uri.file(objcHeader)], compilerOptions: [ From 755df31383e55d05dee234fe5f232262d33e072d Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 18:24:56 +1000 Subject: [PATCH 16/19] Parent/child relationships --- .../lib/src/code_generator/binding.dart | 3 +- .../lib/src/code_generator/constant.dart | 4 +- .../lib/src/code_generator/cpp_class.dart | 2 +- .../lib/src/code_generator/enum_class.dart | 3 +- pkgs/ffigen/lib/src/code_generator/func.dart | 2 +- .../ffigen/lib/src/code_generator/global.dart | 2 +- .../lib/src/code_generator/objc_category.dart | 2 +- .../src/code_generator/objc_interface.dart | 2 +- .../lib/src/code_generator/objc_protocol.dart | 2 +- .../ffigen/lib/src/code_generator/struct.dart | 2 +- .../lib/src/code_generator/typealias.dart | 2 +- pkgs/ffigen/lib/src/code_generator/union.dart | 2 +- pkgs/ffigen/lib/src/public_ast.dart | 122 +++++++++------ .../unit_tests/renaming_visitor_test.dart | 143 ++++++++++++++++++ 14 files changed, 237 insertions(+), 56 deletions(-) diff --git a/pkgs/ffigen/lib/src/code_generator/binding.dart b/pkgs/ffigen/lib/src/code_generator/binding.dart index b9e567cdb6..8669e44266 100644 --- a/pkgs/ffigen/lib/src/code_generator/binding.dart +++ b/pkgs/ffigen/lib/src/code_generator/binding.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import '../config_provider/config_types.dart' show Declaration; +import '../public_ast.dart' as public_ast; import '../visitor/ast.dart'; import 'binding_string.dart'; import 'scope.dart'; @@ -62,7 +63,7 @@ abstract class Binding extends AstNode implements Declaration { String? toCppBindingString(Writer w) => null; /// Returns the public AST node wrapper for this binding, or null. - Object? toPublicAstNode() => null; + public_ast.AstNode? toPublicAstNode() => null; @override void visit(Visitation visitation) => visitation.visitBinding(this); diff --git a/pkgs/ffigen/lib/src/code_generator/constant.dart b/pkgs/ffigen/lib/src/code_generator/constant.dart index 6f4955b315..8d0eb67651 100644 --- a/pkgs/ffigen/lib/src/code_generator/constant.dart +++ b/pkgs/ffigen/lib/src/code_generator/constant.dart @@ -78,7 +78,7 @@ class UnnamedEnumConstant extends Constant { }); @override - Object? toPublicAstNode() => public_ast.UnnamedEnumConstant(this); + public_ast.AstNode? toPublicAstNode() => public_ast.UnnamedEnumConstant(this); @override void visit(Visitation visitation) => @@ -98,7 +98,7 @@ class MacroConstant extends Constant { }); @override - Object? toPublicAstNode() => public_ast.MacroConstant(this); + public_ast.AstNode? toPublicAstNode() => public_ast.MacroConstant(this); @override void visit(Visitation visitation) => visitation.visitMacroConstant(this); diff --git a/pkgs/ffigen/lib/src/code_generator/cpp_class.dart b/pkgs/ffigen/lib/src/code_generator/cpp_class.dart index 1366ae0e1a..4ddbf91a39 100644 --- a/pkgs/ffigen/lib/src/code_generator/cpp_class.dart +++ b/pkgs/ffigen/lib/src/code_generator/cpp_class.dart @@ -82,7 +82,7 @@ class CppClass extends BindingType with HasLocalScope { }); @override - Object? toPublicAstNode() => public_ast.CppClass(this); + public_ast.AstNode? toPublicAstNode() => public_ast.CppClass(this); @override void visit(Visitation visitation) => visitation.visitCppClass(this); diff --git a/pkgs/ffigen/lib/src/code_generator/enum_class.dart b/pkgs/ffigen/lib/src/code_generator/enum_class.dart index 1dd378a177..20a6304537 100644 --- a/pkgs/ffigen/lib/src/code_generator/enum_class.dart +++ b/pkgs/ffigen/lib/src/code_generator/enum_class.dart @@ -74,7 +74,8 @@ class EnumClass extends BindingType with HasLocalScope { enumConstants = enumConstants ?? []; @override - Object? toPublicAstNode() => isAnonymous ? null : public_ast.EnumClass(this); + public_ast.AstNode? toPublicAstNode() => + isAnonymous ? null : public_ast.EnumClass(this); /// Returns a string to declare the enum member and any documentation it may /// have had. diff --git a/pkgs/ffigen/lib/src/code_generator/func.dart b/pkgs/ffigen/lib/src/code_generator/func.dart index 39e5c424d5..92410cc04a 100644 --- a/pkgs/ffigen/lib/src/code_generator/func.dart +++ b/pkgs/ffigen/lib/src/code_generator/func.dart @@ -109,7 +109,7 @@ class Func extends LookUpBinding with HasLocalScope { } @override - Object? toPublicAstNode() => public_ast.Func(this); + public_ast.AstNode? toPublicAstNode() => public_ast.Func(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/global.dart b/pkgs/ffigen/lib/src/code_generator/global.dart index 6e4dc5b31d..5e47b0e36d 100644 --- a/pkgs/ffigen/lib/src/code_generator/global.dart +++ b/pkgs/ffigen/lib/src/code_generator/global.dart @@ -45,7 +45,7 @@ class Global extends LookUpBinding with HasLocalScope { }) : super(symbol: Symbol(name, SymbolKind.field)); @override - Object? toPublicAstNode() => public_ast.Global(this); + public_ast.AstNode? toPublicAstNode() => public_ast.Global(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/objc_category.dart b/pkgs/ffigen/lib/src/code_generator/objc_category.dart index b5359f019f..453494b1b8 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_category.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_category.dart @@ -47,7 +47,7 @@ class ObjCCategory extends NoLookUpBinding with ObjCMethods, HasLocalScope { context.objCBuiltInFunctions.isBuiltInCategory(originalName); @override - Object? toPublicAstNode() => public_ast.ObjCCategory(this); + public_ast.AstNode? toPublicAstNode() => public_ast.ObjCCategory(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart index a450dd6f0c..4b7b76429a 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_interface.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_interface.dart @@ -110,7 +110,7 @@ class ObjCInterface extends BindingType with ObjCMethods, HasLocalScope { bool get unavailable => apiAvailability.availability == Availability.none; @override - Object? toPublicAstNode() => public_ast.ObjCInterface(this); + public_ast.AstNode? toPublicAstNode() => public_ast.ObjCInterface(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart index ac6d5d3be6..1618dc03ce 100644 --- a/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart +++ b/pkgs/ffigen/lib/src/code_generator/objc_protocol.dart @@ -73,7 +73,7 @@ class ObjCProtocol extends BindingType with ObjCMethods, HasLocalScope { bool get unavailable => apiAvailability.availability == Availability.none; @override - Object? toPublicAstNode() => public_ast.ObjCProtocol(this); + public_ast.AstNode? toPublicAstNode() => public_ast.ObjCProtocol(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/struct.dart b/pkgs/ffigen/lib/src/code_generator/struct.dart index 56941d797d..25b43b82d6 100644 --- a/pkgs/ffigen/lib/src/code_generator/struct.dart +++ b/pkgs/ffigen/lib/src/code_generator/struct.dart @@ -50,7 +50,7 @@ class Struct extends Compound { int? pack; @override - Object? toPublicAstNode() => public_ast.Struct(this); + public_ast.AstNode? toPublicAstNode() => public_ast.Struct(this); @override void visit(Visitation visitation) => visitation.visitStruct(this); diff --git a/pkgs/ffigen/lib/src/code_generator/typealias.dart b/pkgs/ffigen/lib/src/code_generator/typealias.dart index 602a3e4a21..da8113df3b 100644 --- a/pkgs/ffigen/lib/src/code_generator/typealias.dart +++ b/pkgs/ffigen/lib/src/code_generator/typealias.dart @@ -108,7 +108,7 @@ class Typealias extends BindingType { } @override - Object? toPublicAstNode() => public_ast.Typealias(this); + public_ast.AstNode? toPublicAstNode() => public_ast.Typealias(this); @override BindingString toBindingString(Writer w) { diff --git a/pkgs/ffigen/lib/src/code_generator/union.dart b/pkgs/ffigen/lib/src/code_generator/union.dart index 7d5c92734f..00d2f1f92f 100644 --- a/pkgs/ffigen/lib/src/code_generator/union.dart +++ b/pkgs/ffigen/lib/src/code_generator/union.dart @@ -47,7 +47,7 @@ class Union extends Compound { int? get pack => null; @override - Object? toPublicAstNode() => public_ast.Union(this); + public_ast.AstNode? toPublicAstNode() => public_ast.Union(this); @override void visit(Visitation visitation) => visitation.visitUnion(this); diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index a27519c712..fa1529bf6d 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -5,8 +5,8 @@ import 'code_generator.dart' as cg; /// Abstract base class for all public AST nodes. -abstract class _AstNode { - const _AstNode(); +abstract class AstNode { + const AstNode(); void accept(Visitor visitor); } @@ -42,8 +42,7 @@ abstract class Visitor { void Function(CppMethod) visitCppMethod, }) = _CallbackVisitor; - // ignore: library_private_types_in_public_api - void visitAll(Iterable<_AstNode> nodes) { + void visitAll(Iterable nodes) { for (final node in nodes) { node.accept(this); } @@ -181,13 +180,12 @@ class _CallbackVisitor extends Visitor { /// A container holding top-level public AST nodes for visitor traversal. class PublicAst { - // ignore: library_private_types_in_public_api - final List<_AstNode> nodes; + final List nodes; PublicAst(List rawBindings) : nodes = rawBindings .map((b) => b.toPublicAstNode()) - .whereType<_AstNode>() + .whereType() .toList(); void accept(Visitor visitor) { @@ -196,15 +194,18 @@ class PublicAst { } /// Public AST node representing a C function declaration. -class Func extends _AstNode { +class Func extends AstNode { final cg.Func _func; /// The parameters of this function. final List params; /// Creates a public [Func] AST node wrapper. - Func(this._func) - : params = _func.functionType.parameters.map(Param.new).toList(); + Func(this._func) : params = [] { + params.addAll( + _func.functionType.parameters.map((p) => Param(p, parent: this)), + ); + } @override void accept(Visitor visitor) { @@ -226,14 +227,16 @@ class Func extends _AstNode { } /// Public AST node representing a C struct declaration. -class Struct extends _AstNode { +class Struct extends AstNode { final cg.Struct _struct; /// The fields belonging to this struct. final List members; /// Creates a public [Struct] AST node wrapper. - Struct(this._struct) : members = _struct.members.map(Field.new).toList(); + Struct(this._struct) : members = [] { + members.addAll(_struct.members.map((m) => Field(m, parent: this))); + } @override void accept(Visitor visitor) { @@ -252,14 +255,16 @@ class Struct extends _AstNode { } /// Public AST node representing a C union declaration. -class Union extends _AstNode { +class Union extends AstNode { final cg.Union _union; /// The fields belonging to this union. final List members; /// Creates a public [Union] AST node wrapper. - Union(this._union) : members = _union.members.map(Field.new).toList(); + Union(this._union) : members = [] { + members.addAll(_union.members.map((m) => Field(m, parent: this))); + } @override void accept(Visitor visitor) { @@ -278,15 +283,18 @@ class Union extends _AstNode { } /// Public AST node representing an enum declaration. -class EnumClass extends _AstNode { +class EnumClass extends AstNode { final cg.EnumClass _enumClass; /// The constants belonging to this enum. final List constants; /// Creates a public [EnumClass] AST node wrapper. - EnumClass(this._enumClass) - : constants = _enumClass.enumConstants.map(EnumConstant.new).toList(); + EnumClass(this._enumClass) : constants = [] { + constants.addAll( + _enumClass.enumConstants.map((c) => EnumConstant(c, parent: this)), + ); + } @override void accept(Visitor visitor) { @@ -305,7 +313,7 @@ class EnumClass extends _AstNode { } /// Public AST node representing a C global variable declaration. -class Global extends _AstNode { +class Global extends AstNode { final cg.Global _global; /// Creates a public [Global] AST node wrapper. @@ -325,7 +333,7 @@ class Global extends _AstNode { } /// Public AST node representing a C macro constant declaration. -class MacroConstant extends _AstNode { +class MacroConstant extends AstNode { final cg.MacroConstant _macro; /// Creates a public [MacroConstant] AST node wrapper. @@ -345,7 +353,7 @@ class MacroConstant extends _AstNode { } /// Public AST node representing a C typedef (type alias) declaration. -class Typealias extends _AstNode { +class Typealias extends AstNode { final cg.Typealias _typealias; /// Creates a public [Typealias] AST node wrapper. @@ -365,15 +373,16 @@ class Typealias extends _AstNode { } /// Public AST node representing an Objective-C interface (class) declaration. -class ObjCInterface extends _AstNode { +class ObjCInterface extends AstNode { final cg.ObjCInterface _interface; /// The methods belonging to this Objective-C interface. final List methods; /// Creates a public [ObjCInterface] AST node wrapper. - ObjCInterface(this._interface) - : methods = _interface.methods.map(ObjCMethod.new).toList(); + ObjCInterface(this._interface) : methods = [] { + methods.addAll(_interface.methods.map((m) => ObjCMethod(m, parent: this))); + } @override void accept(Visitor visitor) { @@ -397,15 +406,16 @@ class ObjCInterface extends _AstNode { } /// Public AST node representing an Objective-C protocol declaration. -class ObjCProtocol extends _AstNode { +class ObjCProtocol extends AstNode { final cg.ObjCProtocol _protocol; /// The methods belonging to this Objective-C protocol. final List methods; /// Creates a public [ObjCProtocol] AST node wrapper. - ObjCProtocol(this._protocol) - : methods = _protocol.methods.map(ObjCMethod.new).toList(); + ObjCProtocol(this._protocol) : methods = [] { + methods.addAll(_protocol.methods.map((m) => ObjCMethod(m, parent: this))); + } @override void accept(Visitor visitor) { @@ -425,15 +435,19 @@ class ObjCProtocol extends _AstNode { } /// Public AST node representing an Objective-C category declaration. -class ObjCCategory extends _AstNode { +class ObjCCategory extends AstNode { final cg.ObjCCategory _category; /// The methods belonging to this Objective-C category. final List methods; /// Creates a public [ObjCCategory] AST node wrapper. - ObjCCategory(this._category) - : methods = _category.methods.map(ObjCMethod.new).toList(); + ObjCCategory(this._category) : methods = [] { + methods.addAll(_category.methods.map((m) => ObjCMethod(m, parent: this))); + } + + /// The [ObjCInterface] that this category extends. + ObjCInterface get interface => ObjCInterface(_category.parent); @override void accept(Visitor visitor) { @@ -453,15 +467,16 @@ class ObjCCategory extends _AstNode { } /// Public AST node representing a C++ class declaration. -class CppClass extends _AstNode { +class CppClass extends AstNode { final cg.CppClass _cppClass; /// The methods belonging to this C++ class. final List methods; /// Creates a public [CppClass] AST node wrapper. - CppClass(this._cppClass) - : methods = _cppClass.methods.map(CppMethod.new).toList(); + CppClass(this._cppClass) : methods = [] { + methods.addAll(_cppClass.methods.map((m) => CppMethod(m, parent: this))); + } @override void accept(Visitor visitor) { @@ -480,11 +495,14 @@ class CppClass extends _AstNode { } /// Public AST node representing a field in a struct or union. -class Field extends _AstNode { +class Field extends AstNode { final cg.CompoundMember _member; + /// The parent AST node containing this field (a [Struct] or [Union]). + final AstNode? parent; + /// Creates a public [Field] AST node wrapper. - Field(this._member); + Field(this._member, {this.parent}); @override void accept(Visitor visitor) => visitor.visitField(this); @@ -497,11 +515,14 @@ class Field extends _AstNode { } /// Public AST node representing a constant inside a named enum. -class EnumConstant extends _AstNode { +class EnumConstant extends AstNode { final cg.EnumConstant _constant; + /// The parent [EnumClass] containing this constant. + final EnumClass? parent; + /// Creates a public [EnumConstant] AST node wrapper. - EnumConstant(this._constant); + EnumConstant(this._constant, {this.parent}); @override void accept(Visitor visitor) => visitor.visitEnumConstant(this); @@ -514,11 +535,15 @@ class EnumConstant extends _AstNode { } /// Public AST node representing a function or method parameter. -class Param extends _AstNode { +class Param extends AstNode { final cg.Parameter _parameter; + /// The parent AST node containing this parameter (a [Func], [ObjCMethod], or + /// [CppMethod]). + final AstNode? parent; + /// Creates a public [Param] AST node wrapper. - Param(this._parameter); + Param(this._parameter, {this.parent}); @override void accept(Visitor visitor) => visitor.visitParam(this); @@ -531,14 +556,19 @@ class Param extends _AstNode { } /// Public AST node representing a C++ method declaration. -class CppMethod extends _AstNode { +class CppMethod extends AstNode { final cg.CppMethod _method; /// The parameters of this C++ method. final List params; + /// The parent [CppClass] containing this C++ method. + final CppClass? parent; + /// Creates a public [CppMethod] AST node wrapper. - CppMethod(this._method) : params = _method.parameters.map(Param.new).toList(); + CppMethod(this._method, {this.parent}) : params = [] { + params.addAll(_method.parameters.map((p) => Param(p, parent: this))); + } @override void accept(Visitor visitor) { @@ -554,14 +584,20 @@ class CppMethod extends _AstNode { } /// Public AST node representing an Objective-C method declaration. -class ObjCMethod extends _AstNode { +class ObjCMethod extends AstNode { final cg.ObjCMethod _method; /// The parameters of this Objective-C method. final List params; + /// The parent AST node containing this Objective-C method (an + /// [ObjCInterface], [ObjCProtocol], or [ObjCCategory]). + final AstNode? parent; + /// Creates a public [ObjCMethod] AST node wrapper. - ObjCMethod(this._method) : params = _method.params.map(Param.new).toList(); + ObjCMethod(this._method, {this.parent}) : params = [] { + params.addAll(_method.params.map((p) => Param(p, parent: this))); + } @override void accept(Visitor visitor) { @@ -586,7 +622,7 @@ class ObjCMethod extends _AstNode { } /// Public AST node representing an unnamed enum constant. -class UnnamedEnumConstant extends _AstNode { +class UnnamedEnumConstant extends AstNode { final cg.UnnamedEnumConstant _constant; /// Creates a public [UnnamedEnumConstant] AST node wrapper. diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart index 587a23e815..f58f1cd47e 100644 --- a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -4,6 +4,7 @@ import 'package:ffigen/ffigen.dart' show FfiGenerator, Output, YamlConfig; import 'package:ffigen/src/code_generator.dart'; +import 'package:ffigen/src/code_generator/scope.dart'; import 'package:ffigen/src/header_parser/sub_parsers/api_availability.dart'; import 'package:ffigen/src/public_ast.dart' as public_ast; import 'package:test/test.dart'; @@ -487,5 +488,147 @@ objc-interfaces: expect(struct.symbol.oldName, 'DartStruct'); expect(func.functionType.parameters[0].symbol.oldName, 'renamedArg0'); }); + + test('Parent and child pointers in public AST nodes', () { + final context = testContext( + FfiGenerator(output: Output(dartFile: Uri.file('out.dart'))), + ); + + final cgFunc = Func( + name: 'my_func', + originalName: 'my_func', + returnType: voidType, + parameters: [Parameter(name: 'p1', type: intType)], + ); + final publicFunc = public_ast.Func(cgFunc); + expect(publicFunc.params[0].parent, same(publicFunc)); + + final cgStruct = Struct( + name: 'my_struct', + originalName: 'my_struct', + context: context, + members: [ + CompoundMember(name: 'f1', originalName: 'f1', type: intType), + ], + ); + final publicStruct = public_ast.Struct(cgStruct); + expect(publicStruct.members[0].parent, same(publicStruct)); + + final cgUnion = Union( + name: 'my_union', + originalName: 'my_union', + context: context, + members: [ + CompoundMember(name: 'u1', originalName: 'u1', type: intType), + ], + ); + final publicUnion = public_ast.Union(cgUnion); + expect(publicUnion.members[0].parent, same(publicUnion)); + + final cgEnum = EnumClass( + name: 'my_enum', + originalName: 'my_enum', + context: context, + enumConstants: [EnumConstant(name: 'C1', originalName: 'C1', value: 0)], + ); + final publicEnum = public_ast.EnumClass(cgEnum); + expect(publicEnum.constants[0].parent, same(publicEnum)); + + final cgObjCMethod = ObjCMethod( + context: context, + originalName: 'doIt:', + name: 'doIt:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: voidType, + family: null, + apiAvailability: ApiAvailability.all, + params: [Parameter(name: 'arg1', type: intType)], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + final cgObjCInterface = ObjCInterface( + context: context, + originalName: 'MyItf', + name: 'MyItf', + apiAvailability: ApiAvailability.all, + )..addMethod(cgObjCMethod); + final publicObjCInterface = public_ast.ObjCInterface(cgObjCInterface); + expect(publicObjCInterface.methods[0].parent, same(publicObjCInterface)); + expect( + publicObjCInterface.methods[0].params[0].parent, + same(publicObjCInterface.methods[0]), + ); + + final cgObjCProtoMethod = ObjCMethod( + context: context, + originalName: 'protoMethod:', + name: 'protoMethod:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: voidType, + family: null, + apiAvailability: ApiAvailability.all, + params: [Parameter(name: 'pArg', type: intType)], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + final cgObjCProtocol = ObjCProtocol( + context: context, + originalName: 'MyProto', + name: 'MyProto', + apiAvailability: ApiAvailability.all, + )..addMethod(cgObjCProtoMethod); + final publicObjCProtocol = public_ast.ObjCProtocol(cgObjCProtocol); + expect(publicObjCProtocol.methods[0].parent, same(publicObjCProtocol)); + + final cgObjCCatMethod = ObjCMethod( + context: context, + originalName: 'catMethod:', + name: 'catMethod:', + kind: ObjCMethodKind.method, + isClassMethod: false, + isOptional: false, + returnType: voidType, + family: null, + apiAvailability: ApiAvailability.all, + params: [Parameter(name: 'cArg', type: intType)], + ownershipAttribute: null, + consumesSelfAttribute: false, + ); + final cgObjCCategory = ObjCCategory( + context: context, + originalName: 'MyCat', + name: 'MyCat', + parent: cgObjCInterface, + apiAvailability: ApiAvailability.all, + )..addMethod(cgObjCCatMethod); + final publicObjCCategory = public_ast.ObjCCategory(cgObjCCategory); + expect(publicObjCCategory.methods[0].parent, same(publicObjCCategory)); + expect(publicObjCCategory.interface.name, 'MyItf'); + + final cgCppMethod = CppMethod( + name: Symbol('cppFunc', SymbolKind.method), + originalName: 'cppFunc', + returnType: voidType, + parameters: [Parameter(name: 'cppArg', type: intType)], + isConstant: false, + ); + final cgCppClass = CppClass( + context: context, + originalName: 'CppClass', + name: 'CppClass', + methods: [cgCppMethod], + fields: [], + ); + final publicCppClass = public_ast.CppClass(cgCppClass); + expect(publicCppClass.methods[0].parent, same(publicCppClass)); + expect( + publicCppClass.methods[0].params[0].parent, + same(publicCppClass.methods[0]), + ); + }); }); } From f874e7965da72d77bd7a2cccdea83882b5557710 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 18:38:39 +1000 Subject: [PATCH 17/19] clean up --- pkgs/ffigen/lib/ffigen.dart | 2 +- pkgs/ffigen/lib/src/header_parser/parser.dart | 7 ++- pkgs/ffigen/lib/src/public_ast.dart | 51 +++++++------------ .../unit_tests/renaming_visitor_test.dart | 34 +++++++++---- 4 files changed, 45 insertions(+), 49 deletions(-) diff --git a/pkgs/ffigen/lib/ffigen.dart b/pkgs/ffigen/lib/ffigen.dart index b6c3be87d8..2fd9d698b0 100644 --- a/pkgs/ffigen/lib/ffigen.dart +++ b/pkgs/ffigen/lib/ffigen.dart @@ -55,4 +55,4 @@ export 'src/config_provider.dart' macSdkUri, xcodePath, xcodeUri; -export 'src/public_ast.dart' hide PublicAst; +export 'src/public_ast.dart'; diff --git a/pkgs/ffigen/lib/src/header_parser/parser.dart b/pkgs/ffigen/lib/src/header_parser/parser.dart index 9de28cfc79..c5d1f653b3 100644 --- a/pkgs/ffigen/lib/src/header_parser/parser.dart +++ b/pkgs/ffigen/lib/src/header_parser/parser.dart @@ -14,7 +14,6 @@ import '../code_generator/scope.dart'; import '../config_provider.dart'; import '../config_provider/utils.dart'; import '../context.dart'; -import '../public_ast.dart' show PublicAst; import '../strings.dart' as strings; import '../visitor/apply_config_filters.dart'; import '../visitor/ast.dart'; @@ -168,9 +167,9 @@ List _findObjectiveCSysroot() => [ List transformBindings(List rawBindings, Context context) { final config = context.config; - final publicAst = PublicAst(rawBindings); - for (final visitor in context.config.visitors) { - publicAst.accept(visitor); + final nodes = rawBindings.map((b) => b.toPublicAstNode()).nonNulls.toList(); + for (final visitor in config.visitors) { + visitor.visitAll(nodes); } final allBindings = visit( diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index fa1529bf6d..804898d0b3 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -2,7 +2,7 @@ // 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 'code_generator.dart' as cg; +import 'code_generator.dart' as internal; /// Abstract base class for all public AST nodes. abstract class AstNode { @@ -178,24 +178,9 @@ class _CallbackVisitor extends Visitor { void visitCppMethod(CppMethod node) => _visitCppMethod(node); } -/// A container holding top-level public AST nodes for visitor traversal. -class PublicAst { - final List nodes; - - PublicAst(List rawBindings) - : nodes = rawBindings - .map((b) => b.toPublicAstNode()) - .whereType() - .toList(); - - void accept(Visitor visitor) { - visitor.visitAll(nodes); - } -} - /// Public AST node representing a C function declaration. class Func extends AstNode { - final cg.Func _func; + final internal.Func _func; /// The parameters of this function. final List params; @@ -228,7 +213,7 @@ class Func extends AstNode { /// Public AST node representing a C struct declaration. class Struct extends AstNode { - final cg.Struct _struct; + final internal.Struct _struct; /// The fields belonging to this struct. final List members; @@ -256,7 +241,7 @@ class Struct extends AstNode { /// Public AST node representing a C union declaration. class Union extends AstNode { - final cg.Union _union; + final internal.Union _union; /// The fields belonging to this union. final List members; @@ -284,7 +269,7 @@ class Union extends AstNode { /// Public AST node representing an enum declaration. class EnumClass extends AstNode { - final cg.EnumClass _enumClass; + final internal.EnumClass _enumClass; /// The constants belonging to this enum. final List constants; @@ -314,7 +299,7 @@ class EnumClass extends AstNode { /// Public AST node representing a C global variable declaration. class Global extends AstNode { - final cg.Global _global; + final internal.Global _global; /// Creates a public [Global] AST node wrapper. Global(this._global); @@ -334,7 +319,7 @@ class Global extends AstNode { /// Public AST node representing a C macro constant declaration. class MacroConstant extends AstNode { - final cg.MacroConstant _macro; + final internal.MacroConstant _macro; /// Creates a public [MacroConstant] AST node wrapper. MacroConstant(this._macro); @@ -354,7 +339,7 @@ class MacroConstant extends AstNode { /// Public AST node representing a C typedef (type alias) declaration. class Typealias extends AstNode { - final cg.Typealias _typealias; + final internal.Typealias _typealias; /// Creates a public [Typealias] AST node wrapper. Typealias(this._typealias); @@ -374,7 +359,7 @@ class Typealias extends AstNode { /// Public AST node representing an Objective-C interface (class) declaration. class ObjCInterface extends AstNode { - final cg.ObjCInterface _interface; + final internal.ObjCInterface _interface; /// The methods belonging to this Objective-C interface. final List methods; @@ -407,7 +392,7 @@ class ObjCInterface extends AstNode { /// Public AST node representing an Objective-C protocol declaration. class ObjCProtocol extends AstNode { - final cg.ObjCProtocol _protocol; + final internal.ObjCProtocol _protocol; /// The methods belonging to this Objective-C protocol. final List methods; @@ -436,7 +421,7 @@ class ObjCProtocol extends AstNode { /// Public AST node representing an Objective-C category declaration. class ObjCCategory extends AstNode { - final cg.ObjCCategory _category; + final internal.ObjCCategory _category; /// The methods belonging to this Objective-C category. final List methods; @@ -468,7 +453,7 @@ class ObjCCategory extends AstNode { /// Public AST node representing a C++ class declaration. class CppClass extends AstNode { - final cg.CppClass _cppClass; + final internal.CppClass _cppClass; /// The methods belonging to this C++ class. final List methods; @@ -496,7 +481,7 @@ class CppClass extends AstNode { /// Public AST node representing a field in a struct or union. class Field extends AstNode { - final cg.CompoundMember _member; + final internal.CompoundMember _member; /// The parent AST node containing this field (a [Struct] or [Union]). final AstNode? parent; @@ -516,7 +501,7 @@ class Field extends AstNode { /// Public AST node representing a constant inside a named enum. class EnumConstant extends AstNode { - final cg.EnumConstant _constant; + final internal.EnumConstant _constant; /// The parent [EnumClass] containing this constant. final EnumClass? parent; @@ -536,7 +521,7 @@ class EnumConstant extends AstNode { /// Public AST node representing a function or method parameter. class Param extends AstNode { - final cg.Parameter _parameter; + final internal.Parameter _parameter; /// The parent AST node containing this parameter (a [Func], [ObjCMethod], or /// [CppMethod]). @@ -557,7 +542,7 @@ class Param extends AstNode { /// Public AST node representing a C++ method declaration. class CppMethod extends AstNode { - final cg.CppMethod _method; + final internal.CppMethod _method; /// The parameters of this C++ method. final List params; @@ -585,7 +570,7 @@ class CppMethod extends AstNode { /// Public AST node representing an Objective-C method declaration. class ObjCMethod extends AstNode { - final cg.ObjCMethod _method; + final internal.ObjCMethod _method; /// The parameters of this Objective-C method. final List params; @@ -623,7 +608,7 @@ class ObjCMethod extends AstNode { /// Public AST node representing an unnamed enum constant. class UnnamedEnumConstant extends AstNode { - final cg.UnnamedEnumConstant _constant; + final internal.UnnamedEnumConstant _constant; /// Creates a public [UnnamedEnumConstant] AST node wrapper. UnnamedEnumConstant(this._constant); diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart index f58f1cd47e..1d7913eeed 100644 --- a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -140,7 +140,10 @@ void main() { )..addMethod(objcMethod); final rawBindings = [func, struct, enumClass, objcInterface]; - final publicAst = public_ast.PublicAst(rawBindings); + final nodes = rawBindings + .map((b) => b.toPublicAstNode()) + .nonNulls + .toList(); expect(func.symbol.oldName, 'c_foo'); expect(struct.symbol.oldName, 'c_struct'); @@ -152,7 +155,7 @@ void main() { expect(objcMethod.params.elementAt(1).symbol.oldName, 'options'); expect(objcMethod.params.elementAt(2).symbol.oldName, 'range'); - publicAst.accept(CustomRenamerVisitor()); + CustomRenamerVisitor().visitAll(nodes); expect(func.symbol.oldName, 'dartFoo'); expect(struct.symbol.oldName, 'DartStruct'); @@ -197,16 +200,16 @@ void main() { expect(method.params.elementAt(1).symbol.oldName, 'withArg'); expect(method.params.elementAt(2).symbol.oldName, 'andOther'); - final publicAst = public_ast.PublicAst([ + final nodes = [ ObjCInterface( context: context, originalName: 'TestItf', name: 'TestItf', apiAvailability: ApiAvailability.all, )..addMethod(method), - ]); + ].map((b) => b.toPublicAstNode()).nonNulls.toList(); - publicAst.accept(CustomRenamerVisitor()); + CustomRenamerVisitor().visitAll(nodes); expect(method.symbol.oldName, 'doSomething'); expect(method.params.elementAt(1).symbol.oldName, 'withArg'); @@ -293,8 +296,12 @@ objc-interfaces: apiAvailability: ApiAvailability.all, )..addMethod(objcMethod); - final publicAst = public_ast.PublicAst([func, struct, objcInterface]); - publicAst.accept(generator.visitors.first); + final nodes = [ + func, + struct, + objcInterface, + ].map((b) => b.toPublicAstNode()).nonNulls.toList(); + generator.visitors.first.visitAll(nodes); expect(func.symbol.oldName, 'dart_func'); expect(func.functionType.parameters[0].symbol.oldName, 'renamedParam1'); @@ -407,8 +414,10 @@ objc-interfaces: unnamedEnumConst, ]; - final publicAst = public_ast.PublicAst(rawBindings); - final nodes = publicAst.nodes; + final nodes = rawBindings + .map((b) => b.toPublicAstNode()) + .nonNulls + .toList(); expect((nodes[0] as public_ast.Func).usr, 'c_foo_usr'); expect((nodes[1] as public_ast.Struct).usr, 'c_struct_usr'); @@ -477,8 +486,11 @@ objc-interfaces: }, ); - final publicAst = public_ast.PublicAst([func, struct]); - publicAst.accept(visitor); + final nodes = [ + func, + struct, + ].map((b) => b.toPublicAstNode()).nonNulls.toList(); + visitor.visitAll(nodes); expect(visitedFuncs, ['c_foo']); expect(visitedStructs, ['c_struct']); From 35c3038e5af391ff56ac1929fe28192e46729587 Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Thu, 6 Aug 2026 18:42:43 +1000 Subject: [PATCH 18/19] clean up --- pkgs/ffigen/lib/src/config_provider/config.dart | 2 +- pkgs/ffigen/lib/src/config_provider/yaml_config.dart | 2 +- pkgs/ffigen/lib/src/public_ast.dart | 4 ++-- pkgs/ffigen/test/header_parser_tests/record_use_test.dart | 2 +- pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index a181cfe517..ccdb6d53da 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -86,7 +86,7 @@ final class FfiGenerator { /// /// Custom visitor class extending [Visitor]: /// ```dart - /// class PrefixStripperVisitor extends Visitor { + /// final class PrefixStripperVisitor extends Visitor { /// final String prefix; /// const PrefixStripperVisitor(this.prefix) : super.base(); /// diff --git a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart index 46f78ff7ea..ac32b524e6 100644 --- a/pkgs/ffigen/lib/src/config_provider/yaml_config.dart +++ b/pkgs/ffigen/lib/src/config_provider/yaml_config.dart @@ -1333,7 +1333,7 @@ final class YamlConfig { } /// AST Visitor that applies renames configured in [YamlConfig]. -class YamlConfigAstVisitor extends public_ast.Visitor { +final class YamlConfigAstVisitor extends public_ast.Visitor { final YamlConfig config; const YamlConfigAstVisitor(this.config) : super.base(); diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index 804898d0b3..90126dd73b 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -15,7 +15,7 @@ abstract class AstNode { /// Implementations can extend [Visitor] by calling [Visitor.base] or use the /// [Visitor] factory constructor to provide inline callbacks for specific /// nodes. -abstract class Visitor { +abstract base class Visitor { /// Base constructor for subclasses extending [Visitor]. const Visitor.base(); @@ -67,7 +67,7 @@ abstract class Visitor { void visitCppMethod(CppMethod node) {} } -class _CallbackVisitor extends Visitor { +final class _CallbackVisitor extends Visitor { final void Function(Func) _visitFunc; final void Function(Struct) _visitStruct; final void Function(Union) _visitUnion; diff --git a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart index 3e2cc09251..fb83820a04 100644 --- a/pkgs/ffigen/test/header_parser_tests/record_use_test.dart +++ b/pkgs/ffigen/test/header_parser_tests/record_use_test.dart @@ -10,7 +10,7 @@ import 'package:test/test.dart'; import '../test_utils.dart'; -class _RenamingVisitor extends public_ast.Visitor { +final class _RenamingVisitor extends public_ast.Visitor { const _RenamingVisitor() : super.base(); @override diff --git a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart index 1d7913eeed..ba22e9467a 100644 --- a/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart +++ b/pkgs/ffigen/test/unit_tests/renaming_visitor_test.dart @@ -12,7 +12,7 @@ import 'package:yaml/yaml.dart'; import '../test_utils.dart'; -class CustomRenamerVisitor extends public_ast.Visitor { +final class CustomRenamerVisitor extends public_ast.Visitor { CustomRenamerVisitor() : super.base(); @override void visitFunc(public_ast.Func node) { From 434c236142f4dacb9b58d42acca170fb314c165d Mon Sep 17 00:00:00 2001 From: Liam Appelbe Date: Fri, 7 Aug 2026 11:06:11 +1000 Subject: [PATCH 19/19] clean up docs --- .../lib/src/config_provider/config.dart | 39 ++++---- pkgs/ffigen/lib/src/public_ast.dart | 88 +++++++------------ 2 files changed, 47 insertions(+), 80 deletions(-) diff --git a/pkgs/ffigen/lib/src/config_provider/config.dart b/pkgs/ffigen/lib/src/config_provider/config.dart index ccdb6d53da..7a04541b68 100644 --- a/pkgs/ffigen/lib/src/config_provider/config.dart +++ b/pkgs/ffigen/lib/src/config_provider/config.dart @@ -66,37 +66,28 @@ final class FfiGenerator { /// Each visitor can inspect or mutate AST node names and properties (such as /// renaming functions, parameters, struct fields, enum constants, etc.). /// - /// Examples: + /// ### Examples /// - /// Inline visitor using the constructor callbacks: + /// Filtering declarations: /// ```dart - /// FfiGenerator( - /// // ... - /// visitors: [ - /// Visitor( - /// visitFunc: (func) { - /// if (func.name.startsWith('custom_')) { - /// func.name = func.name.substring(7); - /// } - /// }, - /// ), - /// ], + /// Visitor( + /// visitFunc: (node) { + /// if (node.name.startsWith('_')) { + /// node.isIncluded = false; + /// } + /// }, /// ) /// ``` /// - /// Custom visitor class extending [Visitor]: + /// Renaming declarations: /// ```dart - /// final class PrefixStripperVisitor extends Visitor { - /// final String prefix; - /// const PrefixStripperVisitor(this.prefix) : super.base(); - /// - /// @override - /// void visitFunc(Func node) { - /// if (node.name.startsWith(prefix)) { - /// node.name = node.name.substring(prefix.length); + /// Visitor( + /// visitStruct: (node) { + /// if (node.name == 'custom_type') { + /// node.name = 'CustomType'; /// } - /// } - /// } + /// }, + /// ) /// ``` final List visitors; diff --git a/pkgs/ffigen/lib/src/public_ast.dart b/pkgs/ffigen/lib/src/public_ast.dart index 90126dd73b..7660460030 100644 --- a/pkgs/ffigen/lib/src/public_ast.dart +++ b/pkgs/ffigen/lib/src/public_ast.dart @@ -12,16 +12,13 @@ abstract class AstNode { /// Base class for AST visitors that inspect and transform AST nodes. /// -/// Implementations can extend [Visitor] by calling [Visitor.base] or use the -/// [Visitor] factory constructor to provide inline callbacks for specific -/// nodes. +/// Implementations can extend [Visitor] (must call the [Visitor.base] +/// constructor) or use the [Visitor] factory constructor to provide inline +/// callbacks for specific nodes. abstract base class Visitor { - /// Base constructor for subclasses extending [Visitor]. const Visitor.base(); /// Creates a [Visitor] that delegates visiting to the provided callbacks. - /// - /// Unprovided callbacks default to no-op handlers. factory Visitor({ void Function(Func) visitFunc, void Function(Struct) visitStruct, @@ -178,14 +175,13 @@ final class _CallbackVisitor extends Visitor { void visitCppMethod(CppMethod node) => _visitCppMethod(node); } -/// Public AST node representing a C function declaration. +/// A C function declaration. class Func extends AstNode { final internal.Func _func; /// The parameters of this function. final List params; - /// Creates a public [Func] AST node wrapper. Func(this._func) : params = [] { params.addAll( _func.functionType.parameters.map((p) => Param(p, parent: this)), @@ -198,7 +194,7 @@ class Func extends AstNode { visitor.visitAll(params); } - /// The Unified Symbol Resolution (USR) identifier of this function. + /// USR identifier of this function. String get usr => _func.usr; /// The generated Dart name for this function. @@ -211,14 +207,13 @@ class Func extends AstNode { } } -/// Public AST node representing a C struct declaration. +/// A C struct declaration. class Struct extends AstNode { final internal.Struct _struct; /// The fields belonging to this struct. final List members; - /// Creates a public [Struct] AST node wrapper. Struct(this._struct) : members = [] { members.addAll(_struct.members.map((m) => Field(m, parent: this))); } @@ -229,7 +224,7 @@ class Struct extends AstNode { visitor.visitAll(members); } - /// The Unified Symbol Resolution (USR) identifier of this struct. + /// USR identifier of this struct. String get usr => _struct.usr; /// The generated Dart name for this struct. @@ -239,14 +234,13 @@ class Struct extends AstNode { set name(String value) => _struct.symbol.oldName = value; } -/// Public AST node representing a C union declaration. +/// A C union declaration. class Union extends AstNode { final internal.Union _union; /// The fields belonging to this union. final List members; - /// Creates a public [Union] AST node wrapper. Union(this._union) : members = [] { members.addAll(_union.members.map((m) => Field(m, parent: this))); } @@ -257,7 +251,7 @@ class Union extends AstNode { visitor.visitAll(members); } - /// The Unified Symbol Resolution (USR) identifier of this union. + /// USR identifier of this union. String get usr => _union.usr; /// The generated Dart name for this union. @@ -267,14 +261,13 @@ class Union extends AstNode { set name(String value) => _union.symbol.oldName = value; } -/// Public AST node representing an enum declaration. +/// An enum declaration. class EnumClass extends AstNode { final internal.EnumClass _enumClass; /// The constants belonging to this enum. final List constants; - /// Creates a public [EnumClass] AST node wrapper. EnumClass(this._enumClass) : constants = [] { constants.addAll( _enumClass.enumConstants.map((c) => EnumConstant(c, parent: this)), @@ -287,7 +280,7 @@ class EnumClass extends AstNode { visitor.visitAll(constants); } - /// The Unified Symbol Resolution (USR) identifier of this enum. + /// USR identifier of this enum. String get usr => _enumClass.usr; /// The generated Dart name for this enum. @@ -297,17 +290,16 @@ class EnumClass extends AstNode { set name(String value) => _enumClass.symbol.oldName = value; } -/// Public AST node representing a C global variable declaration. +/// A C global variable declaration. class Global extends AstNode { final internal.Global _global; - /// Creates a public [Global] AST node wrapper. Global(this._global); @override void accept(Visitor visitor) => visitor.visitGlobal(this); - /// The Unified Symbol Resolution (USR) identifier of this global variable. + /// USR identifier of this global variable. String get usr => _global.usr; /// The generated Dart name for this global variable. @@ -317,17 +309,16 @@ class Global extends AstNode { set name(String value) => _global.symbol.oldName = value; } -/// Public AST node representing a C macro constant declaration. +/// A C macro constant declaration. class MacroConstant extends AstNode { final internal.MacroConstant _macro; - /// Creates a public [MacroConstant] AST node wrapper. MacroConstant(this._macro); @override void accept(Visitor visitor) => visitor.visitMacro(this); - /// The Unified Symbol Resolution (USR) identifier of this macro constant. + /// USR identifier of this macro constant. String get usr => _macro.usr; /// The generated Dart name for this macro constant. @@ -337,17 +328,16 @@ class MacroConstant extends AstNode { set name(String value) => _macro.symbol.oldName = value; } -/// Public AST node representing a C typedef (type alias) declaration. +/// A C typedef (type alias) declaration. class Typealias extends AstNode { final internal.Typealias _typealias; - /// Creates a public [Typealias] AST node wrapper. Typealias(this._typealias); @override void accept(Visitor visitor) => visitor.visitTypealias(this); - /// The Unified Symbol Resolution (USR) identifier of this typedef. + /// USR identifier of this typedef. String get usr => _typealias.usr; /// The generated Dart name for this typedef. @@ -357,14 +347,13 @@ class Typealias extends AstNode { set name(String value) => _typealias.symbol.oldName = value; } -/// Public AST node representing an Objective-C interface (class) declaration. +/// An Objective-C interface (class) declaration. class ObjCInterface extends AstNode { final internal.ObjCInterface _interface; /// The methods belonging to this Objective-C interface. final List methods; - /// Creates a public [ObjCInterface] AST node wrapper. ObjCInterface(this._interface) : methods = [] { methods.addAll(_interface.methods.map((m) => ObjCMethod(m, parent: this))); } @@ -375,8 +364,7 @@ class ObjCInterface extends AstNode { visitor.visitAll(methods); } - /// The Unified Symbol Resolution (USR) identifier of this Objective-C - /// interface. + /// USR identifier of this Objective-C interface. String get usr => _interface.usr; /// The generated Dart name for this Objective-C interface. @@ -390,14 +378,13 @@ class ObjCInterface extends AstNode { } } -/// Public AST node representing an Objective-C protocol declaration. +/// An Objective-C protocol declaration. class ObjCProtocol extends AstNode { final internal.ObjCProtocol _protocol; /// The methods belonging to this Objective-C protocol. final List methods; - /// Creates a public [ObjCProtocol] AST node wrapper. ObjCProtocol(this._protocol) : methods = [] { methods.addAll(_protocol.methods.map((m) => ObjCMethod(m, parent: this))); } @@ -408,8 +395,7 @@ class ObjCProtocol extends AstNode { visitor.visitAll(methods); } - /// The Unified Symbol Resolution (USR) identifier of this Objective-C - /// protocol. + /// USR identifier of this Objective-C protocol. String get usr => _protocol.usr; /// The generated Dart name for this Objective-C protocol. @@ -419,14 +405,13 @@ class ObjCProtocol extends AstNode { set name(String value) => _protocol.symbol.oldName = value; } -/// Public AST node representing an Objective-C category declaration. +/// An Objective-C category declaration. class ObjCCategory extends AstNode { final internal.ObjCCategory _category; /// The methods belonging to this Objective-C category. final List methods; - /// Creates a public [ObjCCategory] AST node wrapper. ObjCCategory(this._category) : methods = [] { methods.addAll(_category.methods.map((m) => ObjCMethod(m, parent: this))); } @@ -440,8 +425,7 @@ class ObjCCategory extends AstNode { visitor.visitAll(methods); } - /// The Unified Symbol Resolution (USR) identifier of this Objective-C - /// category. + /// USR identifier of this Objective-C category. String get usr => _category.usr; /// The generated Dart name for this Objective-C category. @@ -451,14 +435,13 @@ class ObjCCategory extends AstNode { set name(String value) => _category.symbol.oldName = value; } -/// Public AST node representing a C++ class declaration. +/// A C++ class declaration. class CppClass extends AstNode { final internal.CppClass _cppClass; /// The methods belonging to this C++ class. final List methods; - /// Creates a public [CppClass] AST node wrapper. CppClass(this._cppClass) : methods = [] { methods.addAll(_cppClass.methods.map((m) => CppMethod(m, parent: this))); } @@ -469,7 +452,7 @@ class CppClass extends AstNode { visitor.visitAll(methods); } - /// The Unified Symbol Resolution (USR) identifier of this C++ class. + /// USR identifier of this C++ class. String get usr => _cppClass.usr; /// The generated Dart name for this C++ class. @@ -479,14 +462,13 @@ class CppClass extends AstNode { set name(String value) => _cppClass.symbol.oldName = value; } -/// Public AST node representing a field in a struct or union. +/// A field in a struct or union. class Field extends AstNode { final internal.CompoundMember _member; /// The parent AST node containing this field (a [Struct] or [Union]). final AstNode? parent; - /// Creates a public [Field] AST node wrapper. Field(this._member, {this.parent}); @override @@ -499,14 +481,13 @@ class Field extends AstNode { set name(String value) => _member.symbol.oldName = value; } -/// Public AST node representing a constant inside a named enum. +/// A constant inside a named enum. class EnumConstant extends AstNode { final internal.EnumConstant _constant; /// The parent [EnumClass] containing this constant. final EnumClass? parent; - /// Creates a public [EnumConstant] AST node wrapper. EnumConstant(this._constant, {this.parent}); @override @@ -519,7 +500,7 @@ class EnumConstant extends AstNode { set name(String value) => _constant.symbol.oldName = value; } -/// Public AST node representing a function or method parameter. +/// A function or method parameter. class Param extends AstNode { final internal.Parameter _parameter; @@ -527,7 +508,6 @@ class Param extends AstNode { /// [CppMethod]). final AstNode? parent; - /// Creates a public [Param] AST node wrapper. Param(this._parameter, {this.parent}); @override @@ -540,7 +520,7 @@ class Param extends AstNode { set name(String value) => _parameter.symbol.oldName = value; } -/// Public AST node representing a C++ method declaration. +/// A C++ method declaration. class CppMethod extends AstNode { final internal.CppMethod _method; @@ -550,7 +530,6 @@ class CppMethod extends AstNode { /// The parent [CppClass] containing this C++ method. final CppClass? parent; - /// Creates a public [CppMethod] AST node wrapper. CppMethod(this._method, {this.parent}) : params = [] { params.addAll(_method.parameters.map((p) => Param(p, parent: this))); } @@ -568,7 +547,7 @@ class CppMethod extends AstNode { set name(String value) => _method.name.oldName = value; } -/// Public AST node representing an Objective-C method declaration. +/// An Objective-C method declaration. class ObjCMethod extends AstNode { final internal.ObjCMethod _method; @@ -579,7 +558,6 @@ class ObjCMethod extends AstNode { /// [ObjCInterface], [ObjCProtocol], or [ObjCCategory]). final AstNode? parent; - /// Creates a public [ObjCMethod] AST node wrapper. ObjCMethod(this._method, {this.parent}) : params = [] { params.addAll(_method.params.map((p) => Param(p, parent: this))); } @@ -606,18 +584,16 @@ class ObjCMethod extends AstNode { bool get isPropertySetter => _method.isPropertySetter; } -/// Public AST node representing an unnamed enum constant. +/// An unnamed enum constant. class UnnamedEnumConstant extends AstNode { final internal.UnnamedEnumConstant _constant; - /// Creates a public [UnnamedEnumConstant] AST node wrapper. UnnamedEnumConstant(this._constant); @override void accept(Visitor visitor) => visitor.visitUnnamedEnumConstant(this); - /// The Unified Symbol Resolution (USR) identifier of this unnamed enum - /// constant. + /// USR identifier of this unnamed enum constant. String get usr => _constant.usr; /// The generated Dart name for this unnamed enum constant.