Provide access to metadata
The current introspection api does not provide access to metadata annotations on declarations today. You can configure macros themselves by passing info to the constructor, but you can't see any other metadata or macros.
This likely would mean we want to expose some sort of equivalent to the DartObject api for these, which is a larger undertaking.
cc @davidmorgan
Note, that until the declaration phase ends we cannot resolve metadata, because at any point a new declaration could be added, and so change the resolution.
import 'package:my/macro.dart' show myAnnotation, myMacro;
@myMacro
class A {
@myAnnotation
int foo;
}
If myMacro adds a new static const field to A, then @myAnnotation will be resolved to it.
import 'package:my/macro.dart' show myAnnotation, myMacro;
@myMacro
class A {
static const myAnnotation = 0;
@myAnnotation
int foo;
}
Also if the metadata class or any constructors used in arguments come from the current library cycle then we can't construct it at all 🤔 (it isn't complete until after the definition phase)
So one idea here is we could place some restrictions on metadata annotations:
- Macros aren't allowed to introduce declarations that would shadow identifiers used in metadata
- Possibly, this would be a good generalized restriction to reduce confusion?
- Classes used as metadata must be defined in a separate module (similar to macros)
- Classes used as arguments to metadata must also be defined in a separate module
With those restrictions, I think we should be able to provide access to metadata from any phase.
EDIT: this would imply however that all phases of macros have to be ran for any class used as metadata, before running any phase of macro from the current module. Macros themselves already also have this restriction though.
We probably cannot disallow using local declaration for all metadata.
But it would be reasonable for annotations that are macro references.
Probably mostly such configuration will be primitives - String and int, or some objects declared in macro libraries.
Running all phases seems reasonable, in the analyzer we usually process library cycles fully one by one.
It is likely a reasonable restriction that macros can only access metadata for types reachable by the macro definition itself. Possibly with an api like Iterable<Annotation> annotationsOfType<T>() on the Declaration class. We would have to not allow passing type variables to that api I think, which gets a bit funky, but is probably doable.