Skip to content

Commit f254c8a

Browse files
jakemac53Commit Queue
authored andcommitted
Add library macro definitions and support for executing them.
These are intended to be applied by annotating a library directive. Note that some parameter types had to be widened since `Library` is not a subtype of `Declaration`. Ultimately I think that is fine though. Bug:dart-lang/language#2839 Change-Id: Ia1311c8aea729f2bd8b76173ce4c7595a6a37a42 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/312140 Reviewed-by: Bob Nystrom <[email protected]> Auto-Submit: Jake Macdonald <[email protected]> Commit-Queue: Jake Macdonald <[email protected]>
1 parent 1c4ad79 commit f254c8a

File tree

14 files changed

+493
-370
lines changed

14 files changed

+493
-370
lines changed

pkg/_fe_analyzer_shared/lib/src/macros/api/builders.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,31 @@ abstract interface class DefinitionBuilder
178178
TypeResolver,
179179
LibraryDeclarationsResolver {}
180180

181+
/// The APIs used by [Macro]s that run on library directives, to fill in the
182+
/// definitions of any declarations within that library.
183+
abstract interface class LibraryDefinitionBuilder implements DefinitionBuilder {
184+
/// Retrieve a [TypeDefinitionBuilder] for a type declaration with
185+
/// [identifier].
186+
///
187+
/// Throws an [ArgumentError] if [identifier] does not refer to a type
188+
/// declaration in this library.
189+
Future<TypeDefinitionBuilder> buildType(Identifier identifier);
190+
191+
/// Retrieve a [FunctionDefinitionBuilder] for a function declaration with
192+
/// [identifier].
193+
///
194+
/// Throws an [ArgumentError] if [identifier] does not refer to a top level
195+
/// function declaration in this library.
196+
Future<FunctionDefinitionBuilder> buildFunction(Identifier identifier);
197+
198+
/// Retrieve a [VariableDefinitionBuilder] for a variable declaration with
199+
/// [identifier].
200+
///
201+
/// Throws an [ArgumentError] if [identifier] does not refer to a top level
202+
/// variable declaration in this library.
203+
Future<VariableDefinitionBuilder> buildVariable(Identifier identifier);
204+
}
205+
181206
/// The APIs used by [Macro]s that run on type declarations, to fill in the
182207
/// definitions of any declarations within that class.
183208
abstract interface class TypeDefinitionBuilder implements DefinitionBuilder {

pkg/_fe_analyzer_shared/lib/src/macros/api/introspection.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
part of '../api.dart';
66

7+
/// The interface for classes that can be targeted by macros.
8+
///
9+
/// Could be a [Declaration] or [Library].
10+
abstract interface class MacroTarget {}
11+
712
/// A concrete reference to a named declaration, which may or may not yet be
813
/// resolved.
914
///
@@ -95,7 +100,7 @@ abstract interface class StaticType {
95100
abstract interface class NamedStaticType implements StaticType {}
96101

97102
/// The interface for all declarations.
98-
abstract interface class Declaration {
103+
abstract interface class Declaration implements MacroTarget {
99104
/// The library in which this declaration is defined.
100105
Library get library;
101106

@@ -351,7 +356,7 @@ abstract interface class RecordFieldDeclaration implements Declaration {
351356
}
352357

353358
/// Introspection information for a Library.
354-
abstract interface class Library {
359+
abstract interface class Library implements MacroTarget {
355360
/// The language version of this library.
356361
LanguageVersion get languageVersion;
357362

pkg/_fe_analyzer_shared/lib/src/macros/api/macros.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ part of '../api.dart';
77
/// The marker interface for all types of macros.
88
abstract interface class Macro {}
99

10+
/// The interface for [Macro]s that can be applied to a library directive, and
11+
/// want to contribute new type declarations to the library.
12+
abstract interface class LibraryTypesMacro implements Macro {
13+
FutureOr<void> buildTypesForLibrary(Library library, TypeBuilder builder);
14+
}
15+
16+
/// The interface for [Macro]s that can be applied to a library directive, and
17+
/// want to contribute new non-type declarations to the library.
18+
abstract interface class LibraryDeclarationsMacro implements Macro {
19+
FutureOr<void> buildDeclarationsForLibrary(
20+
Library library, DeclarationBuilder builder);
21+
}
22+
23+
/// The interface for [Macro]s that can be applied to a library directive, and
24+
/// want to provide definitions for declarations in the library.
25+
abstract interface class LibraryDefinitionMacro implements Macro {
26+
FutureOr<void> buildDefinitionForLibrary(
27+
Library library, LibraryDefinitionBuilder builder);
28+
}
29+
1030
/// The interface for [Macro]s that can be applied to any top level function,
1131
/// instance method, or static method, and want to contribute new type
1232
/// declarations to the program.

pkg/_fe_analyzer_shared/lib/src/macros/bootstrap.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ Future<SerializableResponse> _executeTypesPhase(
240240
serializationZoneId: request.serializationZoneId);
241241
242242
var result = await executeTypesMacro(
243-
instance, request.declaration, identifierResolver);
243+
instance, request.target, identifierResolver);
244244
return new SerializableResponse(
245245
responseType: MessageType.macroExecutionResult,
246246
response: result,
@@ -283,7 +283,7 @@ Future<SerializableResponse> _executeDeclarationsPhase(
283283
serializationZoneId: request.serializationZoneId);
284284
285285
var result = await executeDeclarationsMacro(
286-
instance, request.declaration, identifierResolver, typeIntrospector,
286+
instance, request.target, identifierResolver, typeIntrospector,
287287
typeDeclarationResolver, typeResolver);
288288
return new SerializableResponse(
289289
responseType: MessageType.macroExecutionResult,
@@ -335,7 +335,7 @@ Future<SerializableResponse> _executeDefinitionsPhase(
335335
serializationZoneId: request.serializationZoneId);
336336
337337
var result = await executeDefinitionMacro(
338-
instance, request.declaration, identifierResolver, typeIntrospector,
338+
instance, request.target, identifierResolver, typeIntrospector,
339339
typeResolver, typeDeclarationResolver, typeInferrer,
340340
libraryDeclarationsResolver);
341341
return new SerializableResponse(

pkg/_fe_analyzer_shared/lib/src/macros/executor.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ abstract class MacroExecutor {
3636
///
3737
/// Throws an exception if there is an error executing the macro.
3838
Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
39-
covariant Declaration declaration, IdentifierResolver identifierResolver);
39+
MacroTarget target, IdentifierResolver identifierResolver);
4040

4141
/// Runs the declarations phase for [macro] on a given [declaration].
4242
///
4343
/// Throws an exception if there is an error executing the macro.
4444
Future<MacroExecutionResult> executeDeclarationsPhase(
4545
MacroInstanceIdentifier macro,
46-
covariant Declaration declaration,
46+
MacroTarget target,
4747
IdentifierResolver identifierResolver,
4848
TypeDeclarationResolver typeDeclarationResolver,
4949
TypeResolver typeResolver,
@@ -54,7 +54,7 @@ abstract class MacroExecutor {
5454
/// Throws an exception if there is an error executing the macro.
5555
Future<MacroExecutionResult> executeDefinitionsPhase(
5656
MacroInstanceIdentifier macro,
57-
covariant Declaration declaration,
57+
MacroTarget target,
5858
IdentifierResolver identifierResolver,
5959
TypeDeclarationResolver typeDeclarationResolver,
6060
TypeResolver typeResolver,

pkg/_fe_analyzer_shared/lib/src/macros/executor/builder_impls.dart

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,78 @@ class VariableDefinitionBuilderImpl extends DefinitionBuilderBase
425425
}
426426
}
427427

428+
class LibraryDefinitionBuilderImpl extends DefinitionBuilderBase
429+
implements LibraryDefinitionBuilder {
430+
final Library library;
431+
432+
LibraryDefinitionBuilderImpl(
433+
this.library,
434+
super.identifierResolver,
435+
super.typeIntrospector,
436+
super.typeDeclarationResolver,
437+
super.typeResolver,
438+
super.typeInferrer,
439+
super.libraryDeclarationsResolver, {
440+
super.parentTypeAugmentations,
441+
super.parentEnumValueAugmentations,
442+
super.parentLibraryAugmentations,
443+
});
444+
445+
@override
446+
Future<FunctionDefinitionBuilder> buildFunction(Identifier identifier) async {
447+
FunctionDeclarationImpl function = (await libraryDeclarationsResolver
448+
.topLevelDeclarationsOf(library))
449+
.firstWhere((declaration) => declaration.identifier == identifier)
450+
as FunctionDeclarationImpl;
451+
return new FunctionDefinitionBuilderImpl(
452+
function,
453+
identifierResolver,
454+
typeIntrospector,
455+
typeDeclarationResolver,
456+
typeResolver,
457+
typeInferrer,
458+
libraryDeclarationsResolver,
459+
parentTypeAugmentations: _typeAugmentations,
460+
parentLibraryAugmentations: _libraryAugmentations);
461+
}
462+
463+
@override
464+
Future<TypeDefinitionBuilder> buildType(Identifier identifier) async {
465+
IntrospectableType type = (await libraryDeclarationsResolver
466+
.topLevelDeclarationsOf(library))
467+
.firstWhere((declaration) => declaration.identifier == identifier)
468+
as IntrospectableType;
469+
return new TypeDefinitionBuilderImpl(
470+
type,
471+
identifierResolver,
472+
typeIntrospector,
473+
typeDeclarationResolver,
474+
typeResolver,
475+
typeInferrer,
476+
libraryDeclarationsResolver,
477+
parentTypeAugmentations: _typeAugmentations,
478+
parentLibraryAugmentations: _libraryAugmentations);
479+
}
480+
481+
@override
482+
Future<VariableDefinitionBuilder> buildVariable(Identifier identifier) async {
483+
VariableDeclarationImpl variable = (await libraryDeclarationsResolver
484+
.topLevelDeclarationsOf(library))
485+
.firstWhere((declaration) => declaration.identifier == identifier)
486+
as VariableDeclarationImpl;
487+
return new VariableDefinitionBuilderImpl(
488+
variable,
489+
identifierResolver,
490+
typeIntrospector,
491+
typeDeclarationResolver,
492+
typeResolver,
493+
typeInferrer,
494+
libraryDeclarationsResolver,
495+
parentTypeAugmentations: _typeAugmentations,
496+
parentLibraryAugmentations: _libraryAugmentations);
497+
}
498+
}
499+
428500
/// Builds all the possible augmentations for a variable.
429501
List<DeclarationCode> _buildVariableAugmentations(
430502
VariableDeclaration declaration,

0 commit comments

Comments
 (0)