native
native copied to clipboard
Add option for dart-idiomatic renaming
UpperCamelCase for structs, lowerCamelCase for functions and members. Current regex-based rename mechanism is unable to achieve this with snake_case symbols.
Better if it can coexist with the existing regex-based rename (to be run before or after).
Hi @safasofuoglu, I haven't been able to find any standard or widely used way for doing this via regexp. The current regexp replace design is very similar to VSCode's. Let us know if you have any design suggestions for this. We'd ideally want to be able to capitalise words or letters via the regexp replace syntax. I'll try to find something as well.
Hi @mannprerak2. Doing this via regex is not possible, since it requires character case transformations which is beyond the capabilities of ECMA regex.
Implementation can be inspired from: https://github.com/Ephenodrom/Dart-Basic-Utils/blob/898970fb31cfbed17366dc9593d474730634616f/lib/src/StringUtils.dart#L32 (MIT)
Design-wise, my suggestion is a root-level configuration:
dart-style-rename: true | false
Renames all identifiers based on the guidelines specified in
https://dart.dev/guides/language/effective-dart/style.
Runs after regex-based renames.
default: false
If granularity is desired, key can be replicated in specific configs, root-level one serving as the default. Example:
dart-style-rename: true
functions:
rename:
'clang_(.*)': '$1'
dart-style-rename: false
For me, this granularity is not important. I just want dart code to look like other dart code.
In general this seems a fine feature to me.
I just want dart code to look like other dart code.
However, this can never be true. Because you have to think about resource management: freeing malloced memory, releasing file handles, closing SQLite statements, etc. (Unless you're writing very simple functions that take in all their arguments by value and return a single result by value.)
I think the right mental model with FFI code is that you're writing C code in Dart syntax. And then wrap that code in an object oriented API. It might be actually kind of helpful if those C function in Dart syntax actually have C naming conventions. But of course that is a matter of preference.
That's a good point. What I'm currently working on abstracts away memory/resource management, so I haven't thought that way.
IMO it would be better to just make ffigen more customizable. Instead of relying on yaml, provide better support for using ffigen as library:
Possible API:
final config = YamlConfig.fromFile(File('ffigen.yaml'));
final customizable = CustomizableConfig(config)
customizable.enumClassDecl.customizeRename((x) => x.camelCase);
FfiGen().run(customizable)
IMO it would be better to just make ffigen more customizable. Instead of relying on yaml, provide better support for using ffigen as library:
Possible API:
final config = YamlConfig.fromFile(File('ffigen.yaml')); final customizable = CustomizableConfig(config) customizable.enumClassDecl.customizeRename((x) => x.camelCase); FfiGen().run(customizable)
Similar effort is happening for jnigen: https://github.com/dart-lang/native/issues/1171
Cool. Another benefit of code based approach is being able to use pub.dev. For example a very common pattern in ffi is pseudo OOP with methods having an opaque pointer as first argument.
@ffi.Native<ffi.Void Function(ffi.Pointer<gameboy_s>, ffi.Uint16, ffi.Uint16)>(symbol: 'GB_cpu_disassemble')
external void cpu_disassemble(ffi.Pointer<gameboy_s> gb, int pc, int count);
It can be manually rewritten to an extension on Pointer:
extension GameboyFfi on ffi.Pointer<gameboy_s> {
@ffi.Native<ffi.Void Function(ffi.Pointer<gameboy_s>, ffi.Uint16, ffi.Uint16)>(symbol: 'GB_cpu_disassemble')
external void cpu_disassemble(int pc, int count);
}
Handling this automatically may be out of scope for ffigen, but if it was extensible, someone else would write a package that does this.
IMO it would be better to just make ffigen more customizable. Instead of relying on yaml, provide better support for using ffigen as library:
Possible API:
final config = YamlConfig.fromFile(File('ffigen.yaml')); final customizable = CustomizableConfig(config) customizable.enumClassDecl.customizeRename((x) => x.camelCase); FfiGen().run(customizable)
This is now possible with the Dart API in the 20.0.0 dev release. https://pub.dev/documentation/ffigen/20.0.0-dev.0/ffigen/Functions/renameMember.html you can write arbitrary Dart code.
Closing issue, please re-open if it doesn't work for you.