Skip to content

Commit 46b4ae7

Browse files
authored
Revert back to original macro api style (#1986)
Opening for discussion. This PR moves us back towards the original proposal, where there is a different type to implement for each phase, and each declaration type you can run on. **Advantages**: - It is easier for an implementation to know up front exactly which phases a given macro will run in. - It allows an implementation to do more efficient invalidation safely - since macros can't share state across phases with local variables you are free to run only a specific phase of a given macro. - Macros are more composable - you have per-phase functions you can directly delegate work to, instead of only a more general function. - We don't have to worry about users trying to share objects they shouldn't through local variables (`TypeBuilders` etc). - Less nesting, avoids the "callback" style which can be a bit messy. **Disadvantages**: - You have to delegate each phase explicitly for any macro you are composing with (see changes to the example). - There is a disconnect between where you declare something and where you define it. I also added the missing `VariableDefinition` and `VariableDefinitionBuilder` classes for introspecting/augmenting top level variables.
1 parent c05ca71 commit 46b4ae7

File tree

4 files changed

+301
-256
lines changed

4 files changed

+301
-256
lines changed

working/macros/api/builders.dart

Lines changed: 6 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,6 @@ import 'code.dart';
44
import 'introspection.dart';
55
import 'macros.dart'; // For dart docs.
66

7-
/// The interface used by [Macro]s to modify the current library.
8-
abstract class LibraryContext {
9-
/// Used to contribute new type declarations to this library.
10-
void buildTypes(FutureOr<void> Function(TypeBuilder) callback);
11-
12-
/// Used to contribute new non-type declarations to this library.
13-
void buildDeclarations(FutureOr<void> Function(DeclarationBuilder) callback);
14-
}
15-
16-
/// The interface used by [FunctionMacro]s to modify the function.
17-
abstract class FunctionContext implements LibraryContext {
18-
/// Used to augment a function definition.
19-
void buildDefinition(
20-
FutureOr<void> Function(FunctionDefinitionBuilder) callback);
21-
}
22-
23-
/// The interface used by [ClassMacro]s to modify the class.
24-
abstract class ClassContext implements LibraryContext {
25-
/// Used to contribute new non-type declarations to this library or class.
26-
@override
27-
void buildDeclarations(
28-
FutureOr<void> Function(ClassDeclarationBuilder) callback);
29-
30-
/// Used to augment any members in this class.
31-
void buildDefinitions(
32-
FutureOr<void> Function(ClassDefinitionBuilder) callback);
33-
}
34-
35-
/// The interface used by all [Macro]s that run on a member of a class, to add
36-
/// declarations to that class or the surrounding library.
37-
abstract class ClassMemberContext implements LibraryContext {
38-
/// Used to contribute new non-type declarations to the surrounding library
39-
/// or class.
40-
@override
41-
void buildDeclarations(
42-
FutureOr<void> Function(ClassMemberDeclarationBuilder) callback);
43-
}
44-
45-
/// The interface used by [FieldMacro]s to modify the field.
46-
abstract class FieldContext implements ClassMemberContext {
47-
/// Used to augment a field definition.
48-
void buildDefinition(
49-
FutureOr<void> Function(FieldDefinitionBuilder) callback);
50-
}
51-
52-
/// The interface used by [MethodMacro]s to modify the method.
53-
abstract class MethodContext implements ClassMemberContext {
54-
/// Used to augment a method definition.
55-
void buildDefinition(
56-
FutureOr<void> Function(FunctionDefinitionBuilder) callback);
57-
}
58-
59-
/// The interface used by [ConstructorMacro]s to modify the constructor.
60-
abstract class ConstructorContext implements ClassMemberContext {
61-
/// Used to augment a constructor definition.
62-
void buildDefinition(
63-
FutureOr<void> Function(ConstructorDefinitionBuilder) callback);
64-
}
65-
667
/// The base interface used to add declarations to the program as well
678
/// as augment existing ones.
689
abstract class Builder {
@@ -153,23 +94,20 @@ abstract class DefinitionBuilder
15394
/// The apis used by [Macro]s that run on classes, to fill in the definitions
15495
/// of any external declarations within that class.
15596
abstract class ClassDefinitionBuilder implements DefinitionBuilder {
156-
/// Retrieve a [FieldDefinitionBuilder] for a field by [name].
97+
/// Retrieve a [VariableDefinitionBuilder] for a field by [name].
15798
///
15899
/// Throws an [ArgumentError] if there is no field by that name.
159-
Future<void> buildField(String name,
160-
FutureOr<void> Function(FieldDefinitionBuilder builder) callback);
100+
VariableDefinitionBuilder buildField(String name);
161101

162102
/// Retrieve a [FunctionDefinitionBuilder] for a method by [name].
163103
///
164104
/// Throws an [ArgumentError] if there is no method by that name.
165-
Future<void> buildMethod(String name,
166-
FutureOr<void> Function(FunctionDefinitionBuilder builder) callback);
105+
FunctionDefinitionBuilder buildMethod(String name);
167106

168107
/// Retrieve a [ConstructorDefinitionBuilder] for a constructor by [name].
169108
///
170109
/// Throws an [ArgumentError] if there is no constructor by that name.
171-
Future<void> buildConstructor(String name,
172-
FutureOr<void> Function(ConstructorDefinitionBuilder builder) callback);
110+
ConstructorDefinitionBuilder buildConstructor(String name);
173111
}
174112

175113
/// The apis used by [Macro]s to define the body of a constructor
@@ -189,8 +127,8 @@ abstract class FunctionDefinitionBuilder implements DefinitionBuilder {
189127
void augment(FunctionBodyCode body);
190128
}
191129

192-
/// The api used by [Macro]s to augment a field.
193-
abstract class FieldDefinitionBuilder implements DefinitionBuilder {
130+
/// The api used by [Macro]s to augment a top level variable or instance field.
131+
abstract class VariableDefinitionBuilder implements DefinitionBuilder {
194132
/// Augments the field.
195133
///
196134
/// TODO: Link the library augmentations proposal to describe the semantics.

working/macros/api/introspection.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,24 +106,27 @@ abstract class ConstructorDeclaration implements MethodDeclaration {
106106
bool get isFactory;
107107
}
108108

109-
/// Field introspection information ..
110-
abstract class FieldDeclaration implements Declaration {
109+
/// Variable introspection information.
110+
abstract class VariableDeclaration implements Declaration {
111111
/// Whether this function has an `abstract` modifier.
112112
bool get isAbstract;
113113

114114
/// Whether this function has an `external` modifier.
115115
bool get isExternal;
116116

117-
/// Type type of this field.
117+
/// The type of this field.
118118
TypeAnnotation get type;
119119

120-
/// The class that defines this method.
121-
TypeAnnotation get definingClass;
122-
123120
/// A [Code] object representing the initializer for this field, if present.
124121
Code? get initializer;
125122
}
126123

124+
/// Field introspection information ..
125+
abstract class FieldDeclaration implements VariableDeclaration {
126+
/// The class that defines this method.
127+
TypeAnnotation get definingClass;
128+
}
129+
127130
/// Parameter introspection information.
128131
abstract class ParameterDeclaration {
129132
/// The name of the parameter.

working/macros/api/macros.dart

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,132 @@ import 'introspection.dart';
77
abstract class Macro {}
88

99
/// The interface for [Macro]s that can be applied to any top level function,
10-
/// instance method, or static method.
11-
abstract class FunctionMacro implements Macro {
12-
/// Invoked for any function that is annotated with this macro.
13-
FutureOr<void> visitFunction(
14-
FunctionDeclaration function, FunctionContext context);
10+
/// instance method, or static method, and wants to contribute new type
11+
/// declarations to the program.
12+
abstract class FunctionTypesMacro implements Macro {
13+
FutureOr<void> buildTypesForFunction(
14+
FunctionDeclaration function, TypeBuilder builder);
1515
}
1616

17-
/// The interface for [Macro]s that can be applied to classes.
18-
abstract class ClassMacro implements Macro {
19-
/// Invoked for any class that is annotated with this macro.
20-
FutureOr<void> visitClass(ClassDeclaration clazz, ClassContext context);
17+
/// The interface for [Macro]s that can be applied to any top level function,
18+
/// instance method, or static method, and wants to contribute new non-type
19+
/// declarations to the program.
20+
abstract class FunctionDeclarationsMacro implements Macro {
21+
FutureOr<void> buildDeclarationsForFunction(
22+
FunctionDeclaration function, DeclarationBuilder builder);
23+
}
24+
25+
/// The interface for [Macro]s that can be applied to any top level function,
26+
/// instance method, or static method, and wants to augment the function
27+
/// definition.
28+
abstract class FunctionDefinitionMacro implements Macro {
29+
FutureOr<void> buildDefinitionForFunction(
30+
FunctionDeclaration function, FunctionDefinitionBuilder builder);
31+
}
32+
33+
/// The interface for [Macro]s that can be applied to any top level variable or
34+
/// instance field, and wants to contribute new type declarations to the
35+
/// program.
36+
abstract class VariableTypesMacro implements Macro {
37+
FutureOr<void> buildTypesForVariable(
38+
VariableDeclaration variable, TypeBuilder builder);
39+
}
40+
41+
/// The interface for [Macro]s that can be applied to any top level variable or
42+
/// instance field and wants to contribute new non-type declarations to the
43+
/// program.
44+
abstract class VariableDeclarationsMacro implements Macro {
45+
FutureOr<void> buildDeclarationsForVariable(
46+
VariableDeclaration variable, DeclarationBuilder builder);
47+
}
48+
49+
/// The interface for [Macro]s that can be applied to any top level variable
50+
/// or instance field, and wants to augment the variable definition.
51+
abstract class VariableDefinitionMacro implements Macro {
52+
FutureOr<void> buildDefinitionForFunction(
53+
VariableDeclaration variable, VariableDefinitionBuilder builder);
54+
}
55+
56+
/// The interface for [Macro]s that can be applied to any class, and wants to
57+
/// contribute new type declarations to the program.
58+
abstract class ClassTypesMacro implements Macro {
59+
FutureOr<void> buildTypesForClass(
60+
ClassDeclaration clazz, TypeBuilder builder);
61+
}
62+
63+
/// The interface for [Macro]s that can be applied to any class, and wants to
64+
/// contribute new non-type declarations to the program.
65+
abstract class ClassDeclarationsMacro implements Macro {
66+
FutureOr<void> buildDeclarationsForClass(
67+
ClassDeclaration clazz, ClassDeclarationBuilder builder);
68+
}
69+
70+
/// The interface for [Macro]s that can be applied to any class, and wants to
71+
/// augment the definitions of members on the class.
72+
abstract class ClassDefinitionMacro implements Macro {
73+
FutureOr<void> buildDefinitionForClass(
74+
ClassDeclaration clazz, ClassDefinitionBuilder builder);
75+
}
76+
77+
/// The interface for [Macro]s that can be applied to any field, and wants to
78+
/// contribute new type declarations to the program.
79+
abstract class FieldTypesMacro implements Macro {
80+
FutureOr<void> buildTypesForField(
81+
FieldDeclaration field, TypeBuilder builder);
82+
}
83+
84+
/// The interface for [Macro]s that can be applied to any field, and wants to
85+
/// contribute new type declarations to the program.
86+
abstract class FieldDeclarationsMacro implements Macro {
87+
FutureOr<void> buildTypesForField(
88+
FieldDeclaration field, ClassMemberDeclarationBuilder builder);
89+
}
90+
91+
/// The interface for [Macro]s that can be applied to any field, and wants to
92+
/// augement the field definition.
93+
abstract class FieldDefinitionsMacro implements Macro {
94+
FutureOr<void> buildDefinitionForField(
95+
FieldDeclaration field, VariableDefinitionBuilder builder);
96+
}
97+
98+
/// The interface for [Macro]s that can be applied to any method, and wants to
99+
/// contribute new type declarations to the program.
100+
abstract class MethodTypesMacro implements Macro {
101+
FutureOr<void> buildTypesForMethod(
102+
MethodDeclaration method, TypeBuilder builder);
103+
}
104+
105+
/// The interface for [Macro]s that can be applied to any method, and wants to
106+
/// contribute new non-type declarations to the program.
107+
abstract class MethodDeclarationDeclarationsMacro implements Macro {
108+
FutureOr<void> buildDeclarationsForMethod(
109+
MethodDeclaration method, ClassMemberDeclarationBuilder builder);
110+
}
111+
112+
/// The interface for [Macro]s that can be applied to any method, and wants to
113+
/// augment the function definition.
114+
abstract class MethodDefinitionMacro implements Macro {
115+
FutureOr<void> buildDefinitionForMethod(
116+
MethodDeclaration method, FunctionDefinitionBuilder builder);
21117
}
22118

23-
/// The interface for [Macro]s that can be applied to fields.
24-
abstract class FieldMacro implements Macro {
25-
/// Invoked for any field that is annotated with this macro
26-
FutureOr<void> visitField(FieldDeclaration field, FieldContext context);
119+
/// The interface for [Macro]s that can be applied to any constructor, and wants
120+
/// to contribute new type declarations to the program.
121+
abstract class ConstructorTypesMacro implements Macro {
122+
FutureOr<void> buildTypesForConstructor(
123+
ConstructorDeclaration method, TypeBuilder builder);
27124
}
28125

29-
/// The interface for [Macro]s that can be applied to methods.
30-
abstract class MethodMacro implements Macro {
31-
/// Invoked for any method that is annotated with this macro.
32-
FutureOr<void> visitMethod(MethodDeclaration method, MethodContext context);
126+
/// The interface for [Macro]s that can be applied to any constructors, and
127+
/// wants to contribute new non-type declarations to the program.
128+
abstract class ConstructorDeclarationDeclarationsMacro implements Macro {
129+
FutureOr<void> buildDeclarationsForConstructor(
130+
ConstructorDeclaration method, ClassMemberDeclarationBuilder builder);
33131
}
34132

35-
/// The interface for [Macro]s that can be applied to constructors.
36-
abstract class ConstructorMacro implements Macro {
37-
/// Invoked for each constructor annotated with this macro.
38-
FutureOr<void> visitConstructor(
39-
ConstructorDeclaration constructor, ConstructorContext context);
133+
/// The interface for [Macro]s that can be applied to any constructor, and wants
134+
/// to augment the function definition.
135+
abstract class ConstructorDefinitionMacro implements Macro {
136+
FutureOr<void> buildDefinitionForConstructor(
137+
ConstructorDeclaration method, ConstructorDefinitionBuilder builder);
40138
}

0 commit comments

Comments
 (0)