macro_prototype icon indicating copy to clipboard operation
macro_prototype copied to clipboard

Provide access to metadata

Open jakemac53 opened this issue 4 years ago • 6 comments

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.

jakemac53 avatar Jun 25 '21 16:06 jakemac53

cc @davidmorgan

jakemac53 avatar Jun 25 '21 16:06 jakemac53

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;
}

scheglov avatar Jul 03 '21 19:07 scheglov

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)

jakemac53 avatar Jul 06 '21 17:07 jakemac53

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.

jakemac53 avatar Jul 08 '21 15:07 jakemac53

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.

scheglov avatar Jul 08 '21 16:07 scheglov

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.

jakemac53 avatar Jul 08 '21 16:07 jakemac53