Dart API to access @RecordUse() recorded usages in link hooks.
During compilation, usages of declarations annotated with @RecordUse() in reachable code are recorded, and information about these usages is made available to post-compile steps (such as link hooks). Usages in unreachable code are not recorded.
final class or enum:final class: any constant instance of the class (including instances created via const redirecting factory constructors), any non-const generative constructor invocation, and any generative constructor tear-off in reachable code will be recorded. Calls to non-const factory constructors are not recorded directly by annotating the class; rather, any generative constructor invocation within the factory body will be recorded.enum: any constant enum element in reachable code will be recorded.@RecordUse() annotation cannot be placed directly on an extension type to record instances.Only usages in executable code are recorded. Usages appearing within metadata (annotations) are ignored.
The @RecordUse() annotation is only allowed on declarations within a package's lib/ directory.
void main() { PirateTranslator.speak('Hello'); print(const PirateShip('Black Pearl', 50)); } abstract class PirateTranslator { @RecordUse() static String speak(String english) => 'Ahoy $english'; } @RecordUse() final class PirateShip { final String name; final int cannons; const PirateShip(this.name, this.cannons); }
This code will generate a data file that contains both the field values of the PirateShip instances, as well as the arguments for the speak method annotated with @RecordUse().
This information can then be accessed in a link hook as follows:
void main(List<String> arguments) { link(arguments, (input, output) async { final uses = input.recordedUses; if (uses == null) return; final calls = uses.calls[methodId] ?? []; for (final call in calls) { switch (call) { case CallWithArguments( positionalArguments: [StringConstant(value: final english), ...], ): // Shrink a translations file based on all the different translation // keys. print('Translating to pirate: $english'); case _: print('Cannot determine which translations are used.'); } } final ships = uses.instances[classId] ?? []; for (final ship in ships) { switch (ship) { case InstanceConstantReference( instanceConstant: InstanceConstant( fields: {'name': StringConstant(value: final name)}, ), ): // Include the 3d model for this ship in the application but not // bundle the other ships. print('Pirate ship found: $name'); case _: print('Cannot determine which ships are used.'); } } }); }
For complete end-to-end examples combining link hooks (hook/link.dart) and package:record_use to tree-shake native C libraries (LinkerOptions.treeshake), see the examples index.
Contributions are welcome! Please open an issue or submit a pull request.