I am using Dart source generators to build some RPC frameworks in a flutter / web view hybrid app (don't ask).
It's going very well, we have this working:
enum ServiceLifecycle {
singleton,
transient
}
class Service {
final String name;
final ServiceLifecycle lifecycle;
const Service(this.name, [this.lifecycle = ServiceLifecycle.singleton]);
}
@Service('Greeter')
class SomeGreeterClassWithAdifferentNameThanGreeter {
String greeting = "Hello";
@ServiceMethod('ChangeGreeting')
void changeGreeting(String greeting) {
this.greeting = greeting;
}
@ServiceMethod('SayHello')
String sayHello(String recipient) {
return "$greeting $recipient!";
}
}
We're auto-generating the required code for the service RPC hooks, again, going well. What's NOT going well, is this whole lifecycle enum.
Here's the generator source code;
import 'package:analyzer/dart/element/type.dart';
import 'package:source_gen/source_gen.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
class ServiceDefinitionGenerator extends GeneratorForAnnotation<Service> {
@override
generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) {
final registeredServiceName = annotation.read('name').stringValue;
// registeredServiceName is the name property of the Service annotation, wonderful.
// Where it gets lost, is here. I've tried all these different ways to get the enum value, but have no luck!
try {
final Object? lifecycleValue = annotation.read('lifecycle').objectValue;
dynamic lc = lifecycleValue;
print('read lifecycle value');
print(lifecycleValue);
print('lifecycleValue.toString()');
print(lifecycleValue.toString());
print("lc['_name'].toString()");
print(lc['_name'].toString());
if (lifecycleValue is String) {
print('lifecycleValue is String');
lifecycle = ServiceLifecycle.values.firstWhereOrNull(
(e) => e.toString().split('.').last == lifecycleValue);
} else if (lifecycleValue is ServiceLifecycle) {
print('lifecycleValue is ServiceLifecycle');
lifecycle = lifecycleValue;
} else {
print('lifecycleValue is not string, setting to null');
lifecycle = null;
}
} catch (e) {
print(e);
lifecycle = null;
}
return 'The cool code';
}
What am I doing wrong? Is there no way to get values from a ConstantReader beyond simple strings / integers? Why is the object casting failing?
I have many questions. Hopefully someone has answers.
pubspec.yaml:
name: some_package
environment:
sdk: ^3.1.2
dependencies:
build_runner: ^2.4.6
json_serializable: ^6.7.1
source_gen: ^1.4.0
build: any
collection: any
analyzer: any
change_case: ^1.1.0
glob: ^2.0.2
dev_dependencies:
lints: ^2.0.0
test: ^1.21.0