google / reflectable.dart

Reflectable is a Dart library that allows programmers to eliminate certain usages of dynamic reflection by specialization of reflective code to an equivalent implementation using only static techniques. The use of dynamic reflection is constrained in order to ensure that the specialized code can be generated and will have a reasonable size.
https://pub.dev/packages/reflectable
BSD 3-Clause "New" or "Revised" License
381 stars 57 forks source link

How to generate code according to filter rules #313

Closed jiajiawei closed 1 year ago

jiajiawei commented 1 year ago

Because of the large amount of generated code, there are now 30000 lines And the generation process is also very slow.

I want to generate code to "main.reflectable.dart" only those marked.

import 'package:reflectable/reflectable.dart';

class MyReflectable extends Reflectable {
  const MyReflectable()
      : super(metadataCapability, instanceInvokeCapability,
            staticInvokeCapability, declarationsCapability, libraryCapability);
}

class Property {
  const Property();
}

class Method {
  const Method();
}

@MyReflectable()
class A {
  @Property()
  String get name => 'zhangsan'; // will generate property code

  int get age => 20; // not generate

  @Method()
  void work() {} // will generate method code

  void sleep() {} // not generate
}

I use the following code to generate code. Can I add callback to the reflectableBuild method to implement filtering?

import 'package:reflectable/reflectable_builder.dart' as builder;

void main() async {
  await builder.reflectableBuild(['lib/main.dart']);
}
eernstg commented 1 year ago

There is no support for running the reflectable code generator in a way that allows a kind of plugin to filter the supported declarations.

But it sounds like you could use InstanceInvokeMetaCapability. Check out this reflector and how it is used in Foo3 for an example.

You would need more than one InstanceInvokeMetaCapability because each one can only have one type of metadata. Or you could introduce a common superclass ReflectorMetadata of Property and Method and then use InstanceInvokeMetaCapability(ReflectorMetadata), whatever fits your needs.

You could also use InstanceInvokeCapability(r'some regular expression') where the supported instance members are the ones whose name matches that regular expression, but that would probably be less convenient in your case.

jiajiawei commented 1 year ago

Thank you very much. This is exactly what I want. I see that the generated code has changed from 26000 to 14000, and other methods have disappeared

class MyReflectable extends Reflectable {
  const MyReflectable()
      : super(
            metadataCapability,
            const InstanceInvokeMetaCapability(Property),
            const InstanceInvokeMetaCapability(Method),
            staticInvokeCapability,
            declarationsCapability,
            libraryCapability);
}