[macros] Add dart:_macros

This adds the dart:_macros library to the SDK and adds support for accessing dart:_macros from package:macros. The library is not used yet.

This change is needed as a prestep to adding the package:macros and using it in the CFE and analyzer, and needs to be rolled in as the checked in sdk before package:macros can be supported.

TEST=ci

Change-Id: Ife3ffd48527e3a196048d2ddf7387b8b7818f3a3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/348680
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: William Hesse <whesse@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2024-02-02 07:47:59 +00:00
committed by Commit Queue
parent 1327a9a71e
commit fe52b9bfe5
33 changed files with 1790 additions and 112 deletions
@@ -1368,6 +1368,18 @@ class Isolate {
)
]);
final MockSdkLibrary _LIB_MACROS = MockSdkLibrary(
'_macros',
[
MockSdkLibraryUnit(
'_macros/_macros.dart',
'''
library dart._macros;
''',
)
],
);
final MockSdkLibrary _LIB_MATH = MockSdkLibrary(
'math',
[
@@ -1444,6 +1456,7 @@ final List<MockSdkLibrary> _LIBRARIES = [
_LIB_INTERNAL,
_LIB_IO,
_LIB_ISOLATE,
_LIB_MACROS,
_LIB_MATH,
_LIB_TYPED_DATA,
_LIB_WASM,
@@ -29,6 +29,20 @@ import 'dart:_internal';
]);
}
test_macros() async {
// Note, in these error cases we may generate an UNUSED_IMPORT hint, while
// we could prevent the hint from being generated by testing the import
// directive for the error, this is such a minor corner case that we don't
// think we should add the additional computation time to figure out such
// cases.
await assertErrorsInCode('''
import 'dart:_macros';
''', [
error(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, 7, 14),
error(WarningCode.UNUSED_IMPORT, 7, 14),
]);
}
test_wasm_fromJs() async {
final packageRootPath = _newPackage('js');
final file = newFile('$packageRootPath/lib/js.dart', '''
+1
View File
@@ -173,6 +173,7 @@ Set<Source?> scanReachableFiles(Uri entryUri) {
'dart:core',
'dart:developer',
'dart:_internal',
'dart:_macros',
'dart:isolate',
'dart:math',
'dart:mirrors',
@@ -275,6 +275,7 @@ const requiredLibraries = <String, List<String>>{
'dart:_js_types',
'dart:_late_helper',
'dart:_load_library_priority',
'dart:_macros',
'dart:_metadata',
'dart:_native_typed_data',
'dart:_recipe_syntax',
@@ -315,6 +316,7 @@ const requiredLibraries = <String, List<String>>{
'dart:_js_types',
'dart:_late_helper',
'dart:_load_library_priority',
'dart:_macros',
'dart:_native_typed_data',
'dart:_recipe_syntax',
'dart:_rti',
+1
View File
@@ -144,6 +144,7 @@ class WasmTarget extends Target {
'dart:_internal',
'dart:_js_helper',
'dart:_js_types',
'dart:_macros',
'dart:_wasm',
'dart:async',
'dart:developer',
@@ -71,6 +71,7 @@ class DevCompilerTarget extends Target {
'dart:_js_names',
'dart:_js_primitives',
'dart:_js_types',
'dart:_macros',
'dart:_metadata',
'dart:_native_typed_data',
'dart:async',
@@ -7,10 +7,11 @@ library from "org-dartlang-test:///main.dart" as main {
static method foo() → dynamic {}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -14,10 +14,11 @@ library from "org-dartlang-test:///main.dart" as main {
static method foo() → dynamic {}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -26,9 +26,10 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 17 platform libraries:
And 18 platform libraries:
- dart:_builtin
- dart:_internal
- dart:_macros
- dart:_vmservice
- dart:async
- dart:cli
@@ -16,10 +16,11 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -16,10 +16,11 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -6,10 +6,11 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -14,10 +14,11 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -14,10 +14,11 @@ library from "org-dartlang-test:///main.dart" as main {
}
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -27,10 +27,11 @@ constants {
#C1 = 0
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -29,10 +29,11 @@ constants {
#C1 = 0
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
@@ -27,10 +27,11 @@ constants {
#C1 = 0
}
And 18 platform libraries:
And 19 platform libraries:
- dart:_http
- dart:_builtin
- dart:vmservice_io
- dart:_macros
- dart:async
- dart:cli
- dart:collection
+8 -2
View File
@@ -354,8 +354,14 @@ abstract class Target {
/// testing purposes.
bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
importer.isScheme("dart") ||
(importer.isScheme("package") &&
importer.path.startsWith("dart_internal/"));
(imported.isScheme('dart') &&
imported.path == '_internal' &&
importer.isScheme("package") &&
importer.path.startsWith("dart_internal/")) ||
(imported.isScheme('dart') &&
imported.path == '_macros' &&
importer.isScheme("package") &&
importer.path.startsWith("macros/"));
/// Whether the `native` language extension is supported within the library
/// with the given import [uri].
+1
View File
@@ -21,6 +21,7 @@ class DartRunnerTarget extends VmTarget {
'dart:developer',
'dart:ffi',
'dart:_internal',
'dart:_macros',
'dart:isolate',
'dart:math',
+1
View File
@@ -27,6 +27,7 @@ class FlutterTarget extends VmTarget {
'dart:developer',
'dart:ffi',
'dart:_internal',
'dart:_macros',
'dart:isolate',
'dart:math',
+1
View File
@@ -21,6 +21,7 @@ class FlutterRunnerTarget extends VmTarget {
'dart:developer',
'dart:ffi',
'dart:_internal',
'dart:_macros',
'dart:isolate',
'dart:math',
+4 -1
View File
@@ -79,6 +79,7 @@ class VmTarget extends Target {
'dart:developer',
'dart:ffi',
'dart:_internal',
'dart:_macros',
'dart:isolate',
'dart:math',
@@ -96,7 +97,9 @@ class VmTarget extends Target {
];
@override
List<String> get extraRequiredLibrariesPlatform => const <String>[];
List<String> get extraRequiredLibrariesPlatform => const <String>[
'dart:_macros',
];
void _patchVmConstants(CoreTypes coreTypes) {
// Fix Endian.host to be a const field equal to Endian.little instead of
@@ -14,6 +14,7 @@ LoadingUnit(id=1, parent=0,
dart:mirrors
dart:math
dart:isolate
dart:_macros
dart:_internal
dart:ffi
dart:developer
+2
View File
@@ -161,6 +161,7 @@ _full_sdk_snapshots = _platform_sdk_snapshots + [
# Libraries that go under lib/
_full_sdk_libraries = [
"_internal",
"_macros",
"async",
"cli",
"collection",
@@ -193,6 +194,7 @@ _full_sdk_libraries = [
#
# _platform_sdk_libraries = [
# "_internal",
# "_macros",
# "async",
# "cli",
# "collection",
+313
View File
@@ -0,0 +1,313 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart._macros;
/// The base interface used to add declarations to the program as well
/// as augment existing ones.
///
/// Can also be used to emit diagnostic messages back to the parent tool.
abstract interface class Builder {
/// Attaches [diagnostic] to the result of this macro application phase.
///
/// Note that this will not immediately send the result, these will all be
/// collected and reported at once when the macro completes this phase.
void report(Diagnostic diagnostic);
}
/// The interface for all introspection that is allowed during the type phase
/// (and later).
abstract interface class TypePhaseIntrospector {
/// Returns an [Identifier] for a top level [name] in [library].
///
/// You should only do this for libraries that are definitely in the
/// transitive import graph of the library you are generating code into. If
/// [library] is not in this transitive import graph, then an unspecified
/// [Exception] should be thrown. The best way to ensure this, is to have the
/// macro library itself import [library] (even if it doesn't directly use
/// it).
///
/// When the name alone is not sufficient to disambiguate between multiple
/// declarations, such as the case of a field (which has a synthetic getter),
/// an [Identifier] pointing to the non-synthetic declaration will be
/// returned. Future calls to `declarationOf(identifier)` will return that
/// non-synthetic declaration.
///
/// If [name] does not exist in [library], then an unspecified [Exception]
/// should be thrown.
@Deprecated(
'This API should eventually be replaced with a different, safer API.')
Future<Identifier> resolveIdentifier(Uri library, String name);
}
/// The API used by [Macro]s to contribute new type declarations to the
/// current library, and get [TypeAnnotation]s from runtime [Type] objects.
abstract interface class TypeBuilder implements Builder, TypePhaseIntrospector {
/// Adds a new type declaration to the surrounding library.
///
/// The [name] must match the name of the new [typeDeclaration] (this does
/// not include any type parameters, just the name).
void declareType(String name, DeclarationCode typeDeclaration);
}
/// The API used by macros in the type phase to add interfaces to an existing
/// type.
abstract interface class InterfaceTypesBuilder implements TypeBuilder {
/// Appends [interfaces] to the list of interfaces for this type.
void appendInterfaces(Iterable<TypeAnnotationCode> interfaces);
}
/// The API used by macros in the type phase to add mixins to an existing
/// type.
abstract interface class MixinTypesBuilder implements TypeBuilder {
/// Appends [mixins] to the list of mixins for this type.
void appendMixins(Iterable<TypeAnnotationCode> mixins);
}
/// The API used by macros in the type phase to augment classes.
abstract interface class ClassTypeBuilder
implements TypeBuilder, InterfaceTypesBuilder, MixinTypesBuilder {}
/// The API used by macros in the type phase to augment enums.
abstract interface class EnumTypeBuilder
implements TypeBuilder, InterfaceTypesBuilder, MixinTypesBuilder {}
/// The API used by macros in the type phase to augment mixins.
///
/// Note that mixins don't support mixins, only interfaces.
abstract interface class MixinTypeBuilder
implements TypeBuilder, InterfaceTypesBuilder {}
/// The interface for all introspection that is allowed during the declaration
/// phase (and later).
abstract interface class DeclarationPhaseIntrospector
implements TypePhaseIntrospector {
/// Instantiates a new [StaticType] for a given [type] annotation.
///
/// Throws if [type] is a [RawTypeAnnotationCode], more specific subtypes must
/// be used, as raw [Identifier]s are not allowed.
///
/// Throws an error if the [type] object contains [Identifier]s which cannot
/// be resolved. This should only happen in the case of incomplete or invalid
/// programs, but macros may be asked to run in this state during the
/// development cycle. It may be helpful for users if macros provide a best
/// effort implementation in that case or handle the error in a useful way.
Future<StaticType> resolve(TypeAnnotationCode type);
/// The values available for [enuum].
///
/// This may be incomplete if additional declaration macros are going to run
/// on [enuum].
Future<List<EnumValueDeclaration>> valuesOf(covariant EnumDeclaration enuum);
/// The fields available for [type].
///
/// This may be incomplete if additional declaration macros are going to run
/// on [type].
Future<List<FieldDeclaration>> fieldsOf(covariant TypeDeclaration type);
/// The methods available for [type].
///
/// This may be incomplete if additional declaration macros are going to run
/// on [type].
Future<List<MethodDeclaration>> methodsOf(covariant TypeDeclaration type);
/// The constructors available for [type].
///
/// This may be incomplete if additional declaration macros are going to run
/// on [type].
Future<List<ConstructorDeclaration>> constructorsOf(
covariant TypeDeclaration type);
/// [TypeDeclaration]s for all the types declared in [library].
///
/// Note that this includes [ExtensionDeclaration]s as well, even though they
/// do not actually introduce a new type.
Future<List<TypeDeclaration>> typesOf(covariant Library library);
/// Resolves an [identifier] to its [TypeDeclaration].
///
/// If [identifier] does not resolve to a [TypeDeclaration], then an
/// [ArgumentError] is thrown.
Future<TypeDeclaration> typeDeclarationOf(covariant Identifier identifier);
}
/// The API used by [Macro]s to contribute new (non-type)
/// declarations to the current library.
///
/// Can also be used to do subtype checks on types.
abstract interface class DeclarationBuilder
implements Builder, DeclarationPhaseIntrospector {
/// Adds a new regular declaration to the surrounding library.
///
/// Note that type declarations are not supported.
void declareInLibrary(DeclarationCode declaration);
}
/// The API used by [Macro]s to contribute new members to a type.
abstract interface class MemberDeclarationBuilder
implements DeclarationBuilder {
/// Adds a new declaration to the surrounding class.
void declareInType(DeclarationCode declaration);
}
/// The API used by [Macro]s to contribute new members or values to an enum.
abstract interface class EnumDeclarationBuilder
implements MemberDeclarationBuilder {
/// Adds a new enum entry declaration to the surrounding enum.
void declareEnumValue(DeclarationCode declaration);
}
/// The interface for all introspection that is allowed during the definition
/// phase (and later).
abstract interface class DefinitionPhaseIntrospector
implements DeclarationPhaseIntrospector {
/// Resolves any [identifier] to its [Declaration].
Future<Declaration> declarationOf(covariant Identifier identifier);
/// Resolves an [identifier] referring to a type to its [TypeDeclaration].
@override
Future<TypeDeclaration> typeDeclarationOf(covariant Identifier identifier);
/// Infers a real type annotation for [omittedType].
///
/// If no type could be inferred, then a type annotation representing the
/// dynamic type will be given.
Future<TypeAnnotation> inferType(covariant OmittedTypeAnnotation omittedType);
/// Returns a list of all the [Declaration]s in the given [library].
Future<List<Declaration>> topLevelDeclarationsOf(covariant Library library);
}
/// The base class for builders in the definition phase. These can convert
/// any [TypeAnnotation] into its corresponding [TypeDeclaration], and also
/// reflect more deeply on those.
abstract interface class DefinitionBuilder
implements Builder, DefinitionPhaseIntrospector {}
/// The APIs used by [Macro]s that run on library directives, to fill in the
/// definitions of any declarations within that library.
abstract interface class LibraryDefinitionBuilder implements DefinitionBuilder {
/// Retrieve a [TypeDefinitionBuilder] for a type declaration with
/// [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a type
/// declaration in this library.
Future<TypeDefinitionBuilder> buildType(Identifier identifier);
/// Retrieve a [FunctionDefinitionBuilder] for a function declaration with
/// [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a top level
/// function declaration in this library.
Future<FunctionDefinitionBuilder> buildFunction(Identifier identifier);
/// Retrieve a [VariableDefinitionBuilder] for a variable declaration with
/// [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a top level
/// variable declaration in this library.
Future<VariableDefinitionBuilder> buildVariable(Identifier identifier);
}
/// The APIs used by [Macro]s that run on type declarations, to fill in the
/// definitions of any declarations within that class.
abstract interface class TypeDefinitionBuilder implements DefinitionBuilder {
/// Retrieve a [VariableDefinitionBuilder] for a field with [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a field in
/// this class.
Future<VariableDefinitionBuilder> buildField(Identifier identifier);
/// Retrieve a [FunctionDefinitionBuilder] for a method with [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a method in
/// this class.
Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier);
/// Retrieve a [ConstructorDefinitionBuilder] for a constructor with
/// [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to a constructor
/// in this class.
Future<ConstructorDefinitionBuilder> buildConstructor(Identifier identifier);
}
/// The APIs used by [Macro]s that run on enums, to fill in the
/// definitions of any declarations within that enum.
abstract interface class EnumDefinitionBuilder
implements TypeDefinitionBuilder {
/// Retrieve an [EnumValueDefinitionBuilder] for an entry with [identifier].
///
/// Throws an [ArgumentError] if [identifier] does not refer to an entry on
/// this enum.
Future<EnumValueDefinitionBuilder> buildEnumValue(Identifier identifier);
}
/// The APIs used by [Macro]s to define the body of a constructor
/// or wrap the body of an existing constructor with additional statements.
abstract interface class ConstructorDefinitionBuilder
implements DefinitionBuilder {
/// Augments an existing constructor body with [body] and [initializers].
///
/// The [initializers] should not contain trailing or preceding commas.
///
/// If [docComments] are supplied, they will be added above this augment
/// declaration.
///
/// TODO: Link the library augmentations proposal to describe the semantics.
void augment({
FunctionBodyCode? body,
List<Code>? initializers,
CommentCode? docComments,
});
}
/// The APIs used by [Macro]s to augment functions or methods.
abstract interface class FunctionDefinitionBuilder
implements DefinitionBuilder {
/// Augments the function.
///
/// If [docComments] are supplied, they will be added above this augment
/// declaration.
///
/// TODO: Link the library augmentations proposal to describe the semantics.
void augment(
FunctionBodyCode body, {
CommentCode? docComments,
});
}
/// The API used by [Macro]s to augment a top level variable or instance field.
abstract interface class VariableDefinitionBuilder
implements DefinitionBuilder {
/// Augments the field.
///
/// For [getter] and [setter] the full function declaration should be
/// provided, minus the `augment` keyword (which will be implicitly added).
///
/// If [initializerDocComments] are supplied, they will be added above the
/// augment declaration for [initializer]. It is an error to provide
/// [initializerDocComments] but not [initializer].
///
/// To provide doc comments for [getter] or [setter], just include them in
/// the [DeclarationCode] object for those.
///
/// TODO: Link the library augmentations proposal to describe the semantics.
void augment({
DeclarationCode? getter,
DeclarationCode? setter,
ExpressionCode? initializer,
CommentCode? initializerDocComments,
});
}
/// The API used by [Macro]s to augment an enum entry.
abstract interface class EnumValueDefinitionBuilder
implements DefinitionBuilder {
/// Augments the entry by replacing it with a new one.
///
/// The name of the produced [entry] must match the original name.
void augment(DeclarationCode entry);
}
+477
View File
@@ -0,0 +1,477 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart._macros;
/// The base class representing an arbitrary chunk of Dart code, which may or
/// may not be syntactically or semantically valid yet.
sealed class Code {
/// All the chunks of [Code], raw [String]s, or [Identifier]s that
/// comprise this [Code] object.
final List<Object> parts;
/// Can be used to more efficiently detect the kind of code, avoiding is
/// checks and enabling switch statements.
CodeKind get kind;
Code.fromString(String code) : parts = [code];
Code.fromParts(this.parts)
: assert(parts.every((element) =>
element is String || element is Code || element is Identifier));
}
/// An arbitrary chunk of code, which does not have to be syntactically valid
/// on its own. Useful to construct other types of code from several parts.
final class RawCode extends Code {
@override
CodeKind get kind => CodeKind.raw;
RawCode.fromString(super.code) : super.fromString();
RawCode.fromParts(super.parts) : super.fromParts();
}
/// A piece of code representing a syntactically valid declaration.
final class DeclarationCode extends Code {
@override
CodeKind get kind => CodeKind.declaration;
DeclarationCode.fromString(super.code) : super.fromString();
DeclarationCode.fromParts(super.parts) : super.fromParts();
}
/// A piece of code representing a code comment. This may contain identifier
/// references inside of `[]` brackets if the comments are doc comments.
final class CommentCode extends Code {
@override
CodeKind get kind => CodeKind.comment;
CommentCode.fromString(super.code) : super.fromString();
CommentCode.fromParts(super.parts) : super.fromParts();
}
/// A piece of code representing a syntactically valid expression.
final class ExpressionCode extends Code {
@override
CodeKind get kind => CodeKind.expression;
ExpressionCode.fromString(super.code) : super.fromString();
ExpressionCode.fromParts(super.parts) : super.fromParts();
}
/// A piece of code representing a syntactically valid function body.
///
/// This includes any and all code after the parameter list of a function,
/// including modifiers like `async`.
///
/// Both arrow and block function bodies are allowed.
final class FunctionBodyCode extends Code {
@override
CodeKind get kind => CodeKind.functionBody;
FunctionBodyCode.fromString(super.code) : super.fromString();
FunctionBodyCode.fromParts(super.parts) : super.fromParts();
}
/// A piece of code identifying a syntactically valid function or function type
/// parameter.
///
/// There is no distinction here made between named and positional parameters.
///
/// There is also no distinction between function type parameters and normal
/// function parameters, so the [name] is nullable (it is not required for
/// positional function type parameters).
///
/// It is the job of the user to construct and combine these together in a way
/// that creates valid parameter lists.
final class ParameterCode implements Code {
final Code? defaultValue;
final List<String> keywords;
final String? name;
final TypeAnnotationCode? type;
@override
CodeKind get kind => CodeKind.parameter;
@override
List<Object> get parts => [
if (keywords.isNotEmpty) ...[
...keywords.joinAsCode(' '),
' ',
],
if (type != null) ...[
type!,
' ',
],
if (name != null) name!,
if (defaultValue != null) ...[
' = ',
defaultValue!,
]
];
ParameterCode({
this.defaultValue,
this.keywords = const [],
this.name,
this.type,
});
}
/// A piece of code representing a type annotation.
sealed class TypeAnnotationCode implements Code, TypeAnnotation {
@override
TypeAnnotationCode get code => this;
/// Returns a [TypeAnnotationCode] object which is a non-nullable version
/// of this one.
///
/// Returns the current instance if it is already non-nullable.
TypeAnnotationCode get asNonNullable => this;
/// Returns a [TypeAnnotationCode] object which is a non-nullable version
/// of this one.
///
/// Returns the current instance if it is already nullable.
NullableTypeAnnotationCode get asNullable =>
new NullableTypeAnnotationCode(this);
/// Whether or not this type is nullable.
@override
bool get isNullable => false;
}
/// The nullable version of an underlying type annotation.
final class NullableTypeAnnotationCode implements TypeAnnotationCode {
/// The underlying type that is being made nullable.
TypeAnnotationCode underlyingType;
@override
TypeAnnotationCode get code => this;
@override
CodeKind get kind => CodeKind.nullableTypeAnnotation;
@override
List<Object> get parts => [...underlyingType.parts, '?'];
/// Creates a nullable [underlyingType] annotation.
///
/// If [underlyingType] is a NullableTypeAnnotationCode, returns that
/// same type.
NullableTypeAnnotationCode(this.underlyingType);
@override
TypeAnnotationCode get asNonNullable => underlyingType;
@override
NullableTypeAnnotationCode get asNullable => this;
@override
bool get isNullable => true;
}
/// A piece of code representing a reference to a named type.
final class NamedTypeAnnotationCode extends TypeAnnotationCode {
final Identifier name;
final List<TypeAnnotationCode> typeArguments;
@override
CodeKind get kind => CodeKind.namedTypeAnnotation;
@override
List<Object> get parts => [
name,
if (typeArguments.isNotEmpty) ...[
'<',
...typeArguments.joinAsCode(', '),
'>',
],
];
NamedTypeAnnotationCode({required this.name, this.typeArguments = const []});
}
/// A piece of code representing a function type annotation.
final class FunctionTypeAnnotationCode extends TypeAnnotationCode {
final List<ParameterCode> namedParameters;
final List<ParameterCode> optionalPositionalParameters;
final List<ParameterCode> positionalParameters;
final TypeAnnotationCode? returnType;
final List<TypeParameterCode> typeParameters;
@override
CodeKind get kind => CodeKind.functionTypeAnnotation;
@override
List<Object> get parts => [
if (returnType != null) returnType!,
' Function',
if (typeParameters.isNotEmpty) ...[
'<',
...typeParameters.joinAsCode(', '),
'>',
],
'(',
for (ParameterCode positional in positionalParameters) ...[
positional,
', ',
],
if (optionalPositionalParameters.isNotEmpty) ...[
'[',
for (ParameterCode optional in optionalPositionalParameters) ...[
optional,
', ',
],
']',
],
if (namedParameters.isNotEmpty) ...[
'{',
for (ParameterCode named in namedParameters) ...[
named,
', ',
],
'}',
],
')',
];
FunctionTypeAnnotationCode({
this.namedParameters = const [],
this.optionalPositionalParameters = const [],
this.positionalParameters = const [],
this.returnType,
this.typeParameters = const [],
});
}
/// A piece of code identifying a syntactically valid record field declaration.
/// This is only usable in the context of [RecordTypeAnnotationCode] objects.
///
/// There is no distinction here made between named and positional fields.
///
/// The name is not required because it is optional for positional fields.
///
/// It is the job of the user to construct and combine these together in a way
/// that creates valid record type annotations.
final class RecordFieldCode implements Code {
final String? name;
final TypeAnnotationCode type;
@override
CodeKind get kind => CodeKind.recordField;
@override
List<Object> get parts => [
type,
if (name != null) ' ${name!}',
];
RecordFieldCode({
this.name,
required this.type,
});
}
/// A piece of code representing a syntactically valid record type annotation.
final class RecordTypeAnnotationCode extends TypeAnnotationCode {
final List<RecordFieldCode> namedFields;
final List<RecordFieldCode> positionalFields;
@override
CodeKind get kind => CodeKind.recordTypeAnnotation;
@override
List<Object> get parts => [
'(',
if (positionalFields.isNotEmpty)
for (RecordFieldCode positional in positionalFields) ...[
if (positional != positionalFields.first) ', ',
positional,
],
if (namedFields.isNotEmpty) ...[
if (positionalFields.isNotEmpty) ', ',
'{',
for (RecordFieldCode named in namedFields) ...[
if (named != namedFields.first) ', ',
named,
],
'}',
],
')',
];
RecordTypeAnnotationCode({
this.namedFields = const [],
this.positionalFields = const [],
});
}
final class OmittedTypeAnnotationCode extends TypeAnnotationCode {
final OmittedTypeAnnotation typeAnnotation;
OmittedTypeAnnotationCode(this.typeAnnotation);
@override
CodeKind get kind => CodeKind.omittedTypeAnnotation;
@override
List<Object> get parts => [typeAnnotation];
}
/// Raw type annotations are typically used to refer to a local type which you
/// do not have an [Identifier] for (possibly you just created it).
///
/// Whenever possible, use a more specific [TypeAnnotationCode] subtype.
final class RawTypeAnnotationCode extends RawCode
implements TypeAnnotationCode {
@override
CodeKind get kind => CodeKind.rawTypeAnnotation;
/// Returns a [TypeAnnotationCode] object which is a non-nullable version
/// of this one.
///
/// Returns the current instance if it is already non-nullable.
@override
TypeAnnotationCode get asNonNullable => this;
/// Returns a [TypeAnnotationCode] object which is a non-nullable version
/// of this one.
///
/// Returns the current instance if it is already nullable.
@override
NullableTypeAnnotationCode get asNullable =>
new NullableTypeAnnotationCode(this);
RawTypeAnnotationCode._(super.parts) : super.fromParts();
/// Creates a [TypeAnnotationCode] from a raw [String].
///
/// The [code] object must not have trailing whitespace.
static TypeAnnotationCode fromString(String code) => fromParts([code]);
/// Creates a [TypeAnnotationCode] from a raw code [parts].
///
/// Must not end in trailing whitespace.
static TypeAnnotationCode fromParts(List<Object> parts) {
bool wasNullable;
(wasNullable, parts) = _makeNonNullable(parts);
TypeAnnotationCode code = new RawTypeAnnotationCode._(parts);
if (wasNullable) code = code.asNullable;
return code;
}
@override
TypeAnnotationCode get code => this;
@override
bool get isNullable => false;
/// Checks if [parts] ends with a ?, and if so then it is removed.
///
/// Returns a record which indicates if [parts] was nullable originally, as
/// well as the potentially new list of parts.
///
/// Throws if [parts] ends with whitespace because we don't allow type
/// annotations to do that.
static (bool wasNullable, List<Object> parts) _makeNonNullable(
List<Object> parts) {
final Iterator<Object> iterator = parts.reversed.iterator;
while (iterator.moveNext()) {
final Object current = iterator.current;
switch (current) {
case String():
if (current.trimRight() != current) {
throw new ArgumentError(
'Invalid type annotation, type annotations should not end with '
'whitespace but got `$current`.');
} else if (current.isEmpty) {
continue;
} else if (current.endsWith('?')) {
// It was nullable, trim the `?` and return a copy.
return (
true,
// We are iterating backwards, and need to reverse it after.
[
// Strip the '?'.
current.substring(0, current.length - 1),
for (bool hasNext = iterator.moveNext();
hasNext;
hasNext = iterator.moveNext())
iterator.current,
].reversed.toList(),
);
} else {
return (false, parts);
}
case Identifier():
// Identifiers never contain a `?`.
return (false, parts);
}
}
throw new ArgumentError('The empty string is not a valid type annotation.');
}
}
/// A piece of code representing a valid named type parameter.
final class TypeParameterCode implements Code {
final TypeAnnotationCode? bound;
final String name;
@override
CodeKind get kind => CodeKind.typeParameter;
@override
List<Object> get parts => [
name,
if (bound != null) ...[
' extends ',
bound!,
]
];
TypeParameterCode({this.bound, required this.name});
}
extension Join<T extends Object> on List<T> {
/// Joins all the items in [this] with [separator], and returns a new list.
///
/// Works on any kind of non-nullable list which accepts String entries, and
/// does not convert the individual items to strings.
List<Object> joinAsCode(String separator) => [
for (int i = 0; i < length - 1; i++) ...[
this[i],
separator,
],
if (isNotEmpty) last,
];
}
enum CodeKind {
comment,
declaration,
expression,
functionBody,
functionTypeAnnotation,
namedTypeAnnotation,
nullableTypeAnnotation,
omittedTypeAnnotation,
parameter,
raw,
rawTypeAnnotation,
recordField,
recordTypeAnnotation,
typeParameter,
}
+96
View File
@@ -0,0 +1,96 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart._macros;
/// A diagnostic reported from a [Macro].
class Diagnostic {
/// Additional [DiagnosticMessage]s related to this one, to help with the
/// context.
final Iterable<DiagnosticMessage> contextMessages;
/// An optional message describing to the user how they might fix this
/// diagnostic.
final String? correctionMessage;
/// The primary message for this diagnostic.
final DiagnosticMessage message;
/// The severity of this diagnostic.
final Severity severity;
/// General diagnostics for the current macro application.
///
/// These will be attached to the macro application itself.
Diagnostic(this.message, this.severity,
{List<DiagnosticMessage> contextMessages = const [],
this.correctionMessage})
: contextMessages = new UnmodifiableListView(contextMessages);
}
/// A message and optional target for a [Diagnostic] reported by a [Macro].
class DiagnosticMessage {
/// The primary message for this diagnostic message.
final String message;
/// The optional target for this diagnostic message.
///
/// If provided, the diagnostic should be linked to this target.
///
/// If not provided, it should be implicitly linked to the macro application
/// that generated this diagnostic.
final DiagnosticTarget? target;
DiagnosticMessage(this.message, {this.target});
}
/// A target for a [DiagnosticMessage]. We use a sealed class to represent a
/// union type of the valid target types.
sealed class DiagnosticTarget {}
/// A [DiagnosticMessage] target which is a [Declaration].
final class DeclarationDiagnosticTarget extends DiagnosticTarget {
final Declaration declaration;
DeclarationDiagnosticTarget(this.declaration);
}
/// A simplified way of creating a [DiagnosticTarget] target for a
/// [Declaration].
extension DeclarationAsTarget on Declaration {
DeclarationDiagnosticTarget get asDiagnosticTarget =>
new DeclarationDiagnosticTarget(this);
}
/// A [DiagnosticMessage] target which is a [TypeAnnotation].
final class TypeAnnotationDiagnosticTarget extends DiagnosticTarget {
final TypeAnnotation typeAnnotation;
TypeAnnotationDiagnosticTarget(this.typeAnnotation);
}
/// A simplified way of creating a [DiagnosticTarget] target for a
/// [TypeAnnotation].
extension TypeAnnotationAsTarget on TypeAnnotation {
TypeAnnotationDiagnosticTarget get asDiagnosticTarget =>
new TypeAnnotationDiagnosticTarget(this);
}
/// The severities supported for [Diagnostic]s.
enum Severity {
/// Informational message only, for example a style guideline is not being
/// followed. These may not always be shown to the user depending on how the
/// app is being compiled and with what flags.
info,
/// Not a critical failure, but something is likely wrong and the code should
/// be changed. Always shown to the user by default, but may be silenceable by
/// some tools.
warning,
/// Critical failure, the macro could not proceed. Cannot be silenced and will
/// always prevent the app from compiling successfully. These are always shown
/// to the user and cannot be silenced.
error,
}
+415
View File
@@ -0,0 +1,415 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart._macros;
/// The interface for classes that can be targeted by macros.
///
/// Could be a [Declaration] or [Library].
abstract interface class MacroTarget {}
/// The interface for things that can be annotated with [MetadataAnnotation]s.
abstract interface class Annotatable {
Iterable<MetadataAnnotation> get metadata;
}
/// A concrete reference to a named declaration, which may or may not yet be
/// resolved.
///
/// These can be passed directly to [Code] objects, which will automatically do
/// any necessary prefixing when emitting references.
///
/// Identifier equality/identity is not specified. To check for type equality, a
/// [StaticType] should be used.
abstract interface class Identifier {
String get name;
}
/// The interface for an unresolved reference to a type.
///
/// See the subtypes [FunctionTypeAnnotation] and [NamedTypeAnnotation].
abstract interface class TypeAnnotation {
/// Whether or not the type annotation is explicitly nullable (contains a
/// trailing `?`)
bool get isNullable;
/// A convenience method to get a [Code] object equivalent to this type
/// annotation.
TypeAnnotationCode get code;
}
/// The interface for function type declarations.
abstract interface class FunctionTypeAnnotation implements TypeAnnotation {
/// The return type of this function.
TypeAnnotation get returnType;
/// The positional parameters for this function.
Iterable<FunctionTypeParameter> get positionalParameters;
/// The named parameters for this function.
Iterable<FunctionTypeParameter> get namedParameters;
/// The type parameters for this function.
Iterable<TypeParameterDeclaration> get typeParameters;
}
/// An unresolved reference to a type.
///
/// These can be resolved to a [TypeDeclaration] using the `builder` classes
/// depending on the phase a macro is running in.
abstract interface class NamedTypeAnnotation implements TypeAnnotation {
/// An identifier pointing to this named type.
Identifier get identifier;
/// The type arguments, if applicable.
Iterable<TypeAnnotation> get typeArguments;
}
/// The interface for record type declarations.
abstract interface class RecordTypeAnnotation implements TypeAnnotation {
/// The positional fields for this record.
Iterable<RecordFieldDeclaration> get positionalFields;
/// The named fields for this record.
Iterable<RecordFieldDeclaration> get namedFields;
}
/// An omitted type annotation.
///
/// This will be given whenever there is no explicit type annotation for a
/// declaration.
///
/// These type annotations can still produce valid [Code] objects, which will
/// result in the inferred type being emitted into the resulting code (or
/// dynamic).
///
/// In the definition phase, you may also ask explicitly for the inferred type
/// using the `inferType` API.
abstract interface class OmittedTypeAnnotation implements TypeAnnotation {}
/// The interface representing a resolved type.
///
/// Resolved types understand exactly what type they represent, and can be
/// compared to other static types.
abstract interface class StaticType {
/// Returns true if this is a subtype of [other].
Future<bool> isSubtypeOf(covariant StaticType other);
/// Returns true if this is an identical type to [other].
Future<bool> isExactly(covariant StaticType other);
}
/// A subtype of [StaticType] representing types that can be resolved by name
/// to a concrete declaration.
abstract interface class NamedStaticType implements StaticType {}
/// The interface for all declarations.
abstract interface class Declaration implements Annotatable, MacroTarget {
/// The library in which this declaration is defined.
Library get library;
/// An identifier pointing to this named declaration.
Identifier get identifier;
}
/// Interface for all Declarations which are a member of a surrounding type
/// declaration.
abstract interface class MemberDeclaration implements Declaration {
/// The type that defines this member.
Identifier get definingType;
/// Whether or not this is a static member.
bool get isStatic;
}
/// Marker interface for a declaration that defines a new type in the program.
///
/// See [ParameterizedTypeDeclaration] and [TypeParameterDeclaration].
abstract interface class TypeDeclaration implements Declaration {}
/// A [TypeDeclaration] which may have type parameters.
///
/// See subtypes [ClassDeclaration], [EnumDeclaration], [MixinDeclaration], and
/// [TypeAliasDeclaration].
abstract interface class ParameterizedTypeDeclaration
implements TypeDeclaration {
/// The type parameters defined for this type declaration.
Iterable<TypeParameterDeclaration> get typeParameters;
}
/// Class introspection information.
///
/// Information about fields, methods, and constructors must be retrieved from
/// the `builder` objects.
abstract interface class ClassDeclaration
implements ParameterizedTypeDeclaration {
/// Whether this class has an `abstract` modifier.
bool get hasAbstract;
/// Whether this class has a `base` modifier.
bool get hasBase;
/// Whether this class has an `external` modifier.
bool get hasExternal;
/// Whether this class has a `final` modifier.
bool get hasFinal;
/// Whether this class has an `interface` modifier.
bool get hasInterface;
/// Whether this class has a `mixin` modifier.
bool get hasMixin;
/// Whether this class has a `sealed` modifier.
bool get hasSealed;
/// The `extends` type annotation, if present.
NamedTypeAnnotation? get superclass;
/// All the `implements` type annotations.
Iterable<NamedTypeAnnotation> get interfaces;
/// All the `with` type annotations.
Iterable<NamedTypeAnnotation> get mixins;
}
/// Enum introspection information.
///
/// Information about values, fields, methods, and constructors must be
/// retrieved from the `builder` objects.
abstract interface class EnumDeclaration
implements ParameterizedTypeDeclaration {
/// All the `implements` type annotations.
Iterable<NamedTypeAnnotation> get interfaces;
/// All the `with` type annotations.
Iterable<NamedTypeAnnotation> get mixins;
}
/// Enum entry introspection information.
///
/// Note that enum values are not introspectable, because they can be augmented.
///
/// You can however do const evaluation of enum values, if they are not in a
/// library cycle with the current library.
abstract interface class EnumValueDeclaration implements Declaration {
/// The enum that surrounds this entry.
Identifier get definingEnum;
}
/// The class for introspecting on an extension.
///
/// Note that extensions do not actually introduce a new type, but we model them
/// as [ParameterizedTypeDeclaration]s anyway, because they generally look
/// exactly like other type declarations, and are treated the same.
abstract interface class ExtensionDeclaration
implements ParameterizedTypeDeclaration, Declaration {
/// The type that appears on the `on` clause of this extension.
TypeAnnotation get onType;
}
/// The class for introspecting on an extension type.
abstract interface class ExtensionTypeDeclaration
implements ParameterizedTypeDeclaration, Declaration {
/// The representation type of this extension type.
TypeAnnotation get representationType;
}
/// Mixin introspection information.
///
/// Information about fields and methods must be retrieved from the `builder`
/// objects.
abstract interface class MixinDeclaration
implements ParameterizedTypeDeclaration {
/// Whether this mixin has a `base` modifier.
bool get hasBase;
/// All the `implements` type annotations.
Iterable<NamedTypeAnnotation> get interfaces;
/// All the `on` clause type annotations.
Iterable<NamedTypeAnnotation> get superclassConstraints;
}
/// Type alias introspection information.
abstract interface class TypeAliasDeclaration
implements ParameterizedTypeDeclaration {
/// The type annotation this is an alias for.
TypeAnnotation get aliasedType;
}
/// Function introspection information.
abstract interface class FunctionDeclaration implements Declaration {
/// Whether or not this function has a body.
///
/// This is useful when augmenting a function, so you know whether an
/// `augment super` call would be valid or not.
///
/// Note that for external functions, this may return `false` even though
/// there is actually a body that is filled in later by another tool.
bool get hasBody;
/// Whether this function has an `external` modifier.
bool get hasExternal;
/// Whether this function is an operator.
bool get isOperator;
/// Whether this function is actually a getter.
bool get isGetter;
/// Whether this function is actually a setter.
bool get isSetter;
/// The return type of this function.
TypeAnnotation get returnType;
/// The positional parameters for this function.
Iterable<ParameterDeclaration> get positionalParameters;
/// The named parameters for this function.
Iterable<ParameterDeclaration> get namedParameters;
/// The type parameters for this function.
Iterable<TypeParameterDeclaration> get typeParameters;
}
/// Method introspection information.
abstract interface class MethodDeclaration
implements FunctionDeclaration, MemberDeclaration {}
/// Constructor introspection information.
abstract interface class ConstructorDeclaration implements MethodDeclaration {
/// Whether or not this is a factory constructor.
bool get isFactory;
}
/// Variable introspection information.
abstract interface class VariableDeclaration implements Declaration {
/// Whether this variable has an `external` modifier.
bool get hasExternal;
/// Whether this variable has a `final` modifier.
bool get hasFinal;
/// Whether this variable has a `late` modifier.
bool get hasLate;
/// The type of this field.
TypeAnnotation get type;
}
/// Field introspection information.
abstract interface class FieldDeclaration
implements VariableDeclaration, MemberDeclaration {
/// Whether this field has an `abstract` modifier.
bool get hasAbstract;
}
/// General parameter introspection information, see the subtypes
/// [FunctionTypeParameter] and [ParameterDeclaration].
abstract interface class Parameter implements Annotatable {
/// The type of this parameter.
TypeAnnotation get type;
/// Whether or not this is a named parameter.
bool get isNamed;
/// Whether or not this parameter is either a non-optional positional
/// parameter or an optional parameter with the `required` keyword.
bool get isRequired;
/// A convenience method to get a `code` object equivalent to this parameter.
///
/// Note that the original default value will not be included, as it is not a
/// part of this API.
ParameterCode get code;
}
/// Parameters of normal functions/methods, which always have an identifier.
abstract interface class ParameterDeclaration
implements Parameter, Declaration {}
/// Function type parameters don't always have names, and it is never useful to
/// get an [Identifier] for them, so they do not implement [Declaration] and
/// instead have an optional name.
abstract interface class FunctionTypeParameter implements Parameter {
String? get name;
}
/// Generic type parameter introspection information.
abstract interface class TypeParameterDeclaration implements TypeDeclaration {
/// The bound for this type parameter, if it has any.
TypeAnnotation? get bound;
/// A convenience method to get a `code` object equivalent to this type
/// parameter.
TypeParameterCode get code;
}
/// Introspection information for a field declaration on a Record type.
///
/// Note that for positional fields the [identifier] will be the synthesized
/// one (`$1` etc), while for named fields it will be the declared name.
abstract interface class RecordFieldDeclaration implements Declaration {
/// A convenience method to get a `code` object equivalent to this field
/// declaration.
RecordFieldCode get code;
/// Record fields don't always have names (if they are positional).
///
/// If you want to reference the getter for a field, you should use
/// [identifier] instead.
String? get name;
/// The type of this field.
TypeAnnotation get type;
}
/// Introspection information for a Library.
abstract interface class Library implements Annotatable, MacroTarget {
/// The language version of this library.
LanguageVersion get languageVersion;
/// The uri identifying this library.
Uri get uri;
}
/// The language version of a library, see
/// https://dart.dev/guides/language/evolution#language-version-numbers.
abstract interface class LanguageVersion {
int get major;
int get minor;
}
/// A metadata annotation on a declaration or library directive.
abstract interface class MetadataAnnotation {}
/// A [MetadataAnnotation] which is a reference to a const value.
abstract interface class IdentifierMetadataAnnotation
implements MetadataAnnotation {
/// The [Identifier] for the const reference.
Identifier get identifier;
}
/// A [Metadata] annotation which is a constructor call.
abstract interface class ConstructorMetadataAnnotation
implements MetadataAnnotation {
/// And [Identifier] referring to the type that is being constructed.
Identifier get type;
/// An [Identifier] referring to the specific constructor being called.
///
/// For unnamed constructors, the name of this identifier will be the empty
/// String.
Identifier get constructor;
/// The positional arguments of this constructor call.
Iterable<ExpressionCode> get positionalArguments;
/// The named arguments of this constructor call.
Map<String, ExpressionCode> get namedArguments;
}
+266
View File
@@ -0,0 +1,266 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart._macros;
/// The marker interface for all types of macros.
abstract interface class Macro {}
/// The interface for [Macro]s that can be applied to a library directive, and
/// want to contribute new type declarations to the library.
abstract interface class LibraryTypesMacro implements Macro {
FutureOr<void> buildTypesForLibrary(Library library, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to a library directive, and
/// want to contribute new non-type declarations to the library.
abstract interface class LibraryDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForLibrary(
Library library, DeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to a library directive, and
/// want to provide definitions for declarations in the library.
abstract interface class LibraryDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForLibrary(
Library library, LibraryDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level function,
/// instance method, or static method, and want to contribute new type
/// declarations to the program.
abstract interface class FunctionTypesMacro implements Macro {
FutureOr<void> buildTypesForFunction(
FunctionDeclaration function, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level function,
/// instance method, or static method, and want to contribute new non-type
/// declarations to the program.
abstract interface class FunctionDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForFunction(
FunctionDeclaration function, DeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level function,
/// instance method, or static method, and want to augment the function
/// definition.
abstract interface class FunctionDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForFunction(
FunctionDeclaration function, FunctionDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level variable or
/// instance field, and want to contribute new type declarations to the
/// program.
abstract interface class VariableTypesMacro implements Macro {
FutureOr<void> buildTypesForVariable(
VariableDeclaration variable, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level variable or
/// instance field and want to contribute new non-type declarations to the
/// program.
abstract interface class VariableDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForVariable(
VariableDeclaration variable, DeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any top level variable
/// or instance field, and want to augment the variable definition.
abstract interface class VariableDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForVariable(
VariableDeclaration variable, VariableDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any class, and want to
/// contribute new type declarations to the program.
abstract interface class ClassTypesMacro implements Macro {
FutureOr<void> buildTypesForClass(
ClassDeclaration clazz, ClassTypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any class, and want to
/// contribute new non-type declarations to the program.
abstract interface class ClassDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForClass(
ClassDeclaration clazz, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any class, and want to
/// augment the definitions of the members of that class.
abstract interface class ClassDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForClass(
ClassDeclaration clazz, TypeDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// contribute new type declarations to the program.
abstract interface class EnumTypesMacro implements Macro {
FutureOr<void> buildTypesForEnum(
EnumDeclaration enuum, EnumTypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// contribute new non-type declarations to the program.
abstract interface class EnumDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForEnum(
EnumDeclaration enuum, EnumDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// augment the definitions of members or values of that enum.
abstract interface class EnumDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForEnum(
EnumDeclaration enuum, EnumDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// contribute new type declarations to the program.
abstract interface class EnumValueTypesMacro implements Macro {
FutureOr<void> buildTypesForEnumValue(
EnumValueDeclaration entry, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// contribute new non-type declarations to the program.
abstract interface class EnumValueDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForEnumValue(
EnumValueDeclaration entry, EnumDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any enum, and want to
/// augment the definitions of members or values of that enum.
abstract interface class EnumValueDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForEnumValue(
EnumValueDeclaration entry, EnumValueDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any field, and want to
/// contribute new type declarations to the program.
abstract interface class FieldTypesMacro implements Macro {
FutureOr<void> buildTypesForField(
FieldDeclaration field, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any field, and want to
/// contribute new type declarations to the program.
abstract interface class FieldDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForField(
FieldDeclaration field, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any field, and want to
/// augment the field definition.
abstract interface class FieldDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForField(
FieldDeclaration field, VariableDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any method, and want to
/// contribute new type declarations to the program.
abstract interface class MethodTypesMacro implements Macro {
FutureOr<void> buildTypesForMethod(
MethodDeclaration method, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any method, and want to
/// contribute new non-type declarations to the program.
abstract interface class MethodDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForMethod(
MethodDeclaration method, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any method, and want to
/// augment the function definition.
abstract interface class MethodDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForMethod(
MethodDeclaration method, FunctionDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any constructor, and want
/// to contribute new type declarations to the program.
abstract interface class ConstructorTypesMacro implements Macro {
FutureOr<void> buildTypesForConstructor(
ConstructorDeclaration constructor, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any constructors, and
/// want to contribute new non-type declarations to the program.
abstract interface class ConstructorDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForConstructor(
ConstructorDeclaration constructor, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any constructor, and want
/// to augment the function definition.
abstract interface class ConstructorDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForConstructor(
ConstructorDeclaration constructor, ConstructorDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any mixin declaration, and
/// want to contribute new type declarations to the program.
abstract interface class MixinTypesMacro implements Macro {
FutureOr<void> buildTypesForMixin(
MixinDeclaration mixin, MixinTypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any mixin declaration, and
/// want to contribute new non-type declarations to the program.
abstract interface class MixinDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForMixin(
MixinDeclaration mixin, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any mixin declaration, and
/// want to augment the definitions of the members of that mixin.
abstract interface class MixinDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForMixin(
MixinDeclaration mixin, TypeDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension declaration,
/// and want to contribute new type declarations to the program.
abstract interface class ExtensionTypesMacro implements Macro {
FutureOr<void> buildTypesForExtension(
ExtensionDeclaration extension, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension declaration,
/// and want to contribute new non-type declarations to the program.
abstract interface class ExtensionDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForExtension(
ExtensionDeclaration extension, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension declaration,
/// and want to augment the definitions of the members of that extension.
abstract interface class ExtensionDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForExtension(
ExtensionDeclaration extension, TypeDefinitionBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension type
/// declaration, and want to contribute new type declarations to the program.
abstract interface class ExtensionTypeTypesMacro implements Macro {
FutureOr<void> buildTypesForExtensionType(
ExtensionTypeDeclaration extension, TypeBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension type
/// declaration, and want to contribute new non-type declarations to the
/// program.
abstract interface class ExtensionTypeDeclarationsMacro implements Macro {
FutureOr<void> buildDeclarationsForExtensionType(
ExtensionTypeDeclaration extension, MemberDeclarationBuilder builder);
}
/// The interface for [Macro]s that can be applied to any extension type
/// declaration, and want to augment the definitions of the members of that
/// extension.
abstract interface class ExtensionTypeDefinitionMacro implements Macro {
FutureOr<void> buildDefinitionForExtensionType(
ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder);
}
+14
View File
@@ -0,0 +1,14 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library dart._macros;
import 'dart:async';
import 'dart:collection' show UnmodifiableListView;
part 'builders.dart';
part 'code.dart';
part 'diagnostic.dart';
part 'introspection.dart';
part 'macro.dart';
+27
View File
@@ -4,7 +4,19 @@
"none": {
"libraries": {}
},
"common": {
"libraries": {
"_macros": {
"uri": "_macros/macros.dart"
}
}
},
"vm_common": {
"include": [
{
"target": "common"
}
],
"libraries": {
"_builtin": {
"uri": "_internal/vm/bin/builtin.dart"
@@ -230,6 +242,11 @@
}
},
"wasm_common": {
"include": [
{
"target": "common"
}
],
"libraries": {
"core": {
"uri": "core/core.dart",
@@ -387,6 +404,11 @@
}
},
"_dart2js_common": {
"include": [
{
"target": "common"
}
],
"libraries": {
"async": {
"uri": "async/async.dart",
@@ -506,6 +528,11 @@
}
},
"dartdevc": {
"include": [
{
"target": "common"
}
],
"libraries": {
"_runtime": {
"uri": "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
+108 -95
View File
@@ -14,7 +14,14 @@
none:
libraries: {}
common:
libraries:
_macros:
uri: _macros/macros.dart
vm_common:
include:
- target: "common"
libraries:
_builtin:
uri: "_internal/vm/bin/builtin.dart"
@@ -195,6 +202,8 @@ wasm_base:
uri: _internal/wasm/lib/typed_data.dart
wasm_common:
include:
- target: "common"
libraries:
core:
uri: core/core.dart
@@ -311,6 +320,8 @@ dart2js_server:
patches: "js/_js_server.dart"
_dart2js_common:
include:
- target: "common"
libraries:
async:
uri: "async/async.dart"
@@ -426,134 +437,136 @@ _dart2js_common:
uri: "_internal/js_shared/lib/synced/recipe_syntax.dart"
dartdevc:
libraries:
_runtime:
uri: "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
include:
- target: "common"
libraries:
_runtime:
uri: "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
_debugger:
uri: "_internal/js_dev_runtime/private/debugger.dart"
_debugger:
uri: "_internal/js_dev_runtime/private/debugger.dart"
_foreign_helper:
uri: "_internal/js_dev_runtime/private/foreign_helper.dart"
_foreign_helper:
uri: "_internal/js_dev_runtime/private/foreign_helper.dart"
_http:
uri: "_http/http.dart"
_http:
uri: "_http/http.dart"
_interceptors:
uri: "_internal/js_dev_runtime/private/interceptors.dart"
_interceptors:
uri: "_internal/js_dev_runtime/private/interceptors.dart"
_internal:
uri: "internal/internal.dart"
patches: "_internal/js_dev_runtime/patch/internal_patch.dart"
_internal:
uri: "internal/internal.dart"
patches: "_internal/js_dev_runtime/patch/internal_patch.dart"
_isolate_helper:
uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
_isolate_helper:
uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
_js_annotations:
uri: "js/_js_annotations.dart"
_js_annotations:
uri: "js/_js_annotations.dart"
_js_shared_embedded_names:
uri: "_internal/js_shared/lib/synced/embedded_names.dart"
_js_shared_embedded_names:
uri: "_internal/js_shared/lib/synced/embedded_names.dart"
_js_helper:
uri: "_internal/js_dev_runtime/private/js_helper.dart"
_js_helper:
uri: "_internal/js_dev_runtime/private/js_helper.dart"
_js_names:
uri: "_internal/js_dev_runtime/private/js_names.dart"
_js_names:
uri: "_internal/js_dev_runtime/private/js_names.dart"
_js_primitives:
uri: "_internal/js_dev_runtime/private/js_primitives.dart"
_js_primitives:
uri: "_internal/js_dev_runtime/private/js_primitives.dart"
_js_types:
uri: "_internal/js_shared/lib/js_types.dart"
_js_types:
uri: "_internal/js_shared/lib/js_types.dart"
_metadata:
uri: "html/html_common/metadata.dart"
_metadata:
uri: "html/html_common/metadata.dart"
_native_typed_data:
uri: "_internal/js_dev_runtime/private/native_typed_data.dart"
_native_typed_data:
uri: "_internal/js_dev_runtime/private/native_typed_data.dart"
_dart2js_runtime_metrics:
uri: "_internal/js_dev_runtime/private/runtime_metrics.dart"
_dart2js_runtime_metrics:
uri: "_internal/js_dev_runtime/private/runtime_metrics.dart"
_rti:
uri: "_internal/js_shared/lib/rti.dart"
_rti:
uri: "_internal/js_shared/lib/rti.dart"
_recipe_syntax:
uri: "_internal/js_shared/lib/synced/recipe_syntax.dart"
_recipe_syntax:
uri: "_internal/js_shared/lib/synced/recipe_syntax.dart"
async:
uri: "async/async.dart"
patches: "_internal/js_dev_runtime/patch/async_patch.dart"
async:
uri: "async/async.dart"
patches: "_internal/js_dev_runtime/patch/async_patch.dart"
collection:
uri: "collection/collection.dart"
patches: "_internal/js_dev_runtime/patch/collection_patch.dart"
collection:
uri: "collection/collection.dart"
patches: "_internal/js_dev_runtime/patch/collection_patch.dart"
convert:
uri: "convert/convert.dart"
patches:
- "_internal/js_shared/lib/convert_utf_patch.dart"
- "_internal/js_dev_runtime/patch/convert_patch.dart"
convert:
uri: "convert/convert.dart"
patches:
- "_internal/js_shared/lib/convert_utf_patch.dart"
- "_internal/js_dev_runtime/patch/convert_patch.dart"
core:
uri: "core/core.dart"
patches: "_internal/js_dev_runtime/patch/core_patch.dart"
core:
uri: "core/core.dart"
patches: "_internal/js_dev_runtime/patch/core_patch.dart"
developer:
uri: "developer/developer.dart"
patches: "_internal/js_dev_runtime/patch/developer_patch.dart"
developer:
uri: "developer/developer.dart"
patches: "_internal/js_dev_runtime/patch/developer_patch.dart"
io:
uri: "io/io.dart"
patches: "_internal/js_dev_runtime/patch/io_patch.dart"
supported: false
io:
uri: "io/io.dart"
patches: "_internal/js_dev_runtime/patch/io_patch.dart"
supported: false
isolate:
uri: "isolate/isolate.dart"
patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
supported: false
isolate:
uri: "isolate/isolate.dart"
patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
supported: false
math:
uri: "math/math.dart"
patches: "_internal/js_dev_runtime/patch/math_patch.dart"
math:
uri: "math/math.dart"
patches: "_internal/js_dev_runtime/patch/math_patch.dart"
typed_data:
uri: "typed_data/typed_data.dart"
patches: "_internal/js_dev_runtime/patch/typed_data_patch.dart"
typed_data:
uri: "typed_data/typed_data.dart"
patches: "_internal/js_dev_runtime/patch/typed_data_patch.dart"
html:
uri: "html/dart2js/html_dart2js.dart"
html:
uri: "html/dart2js/html_dart2js.dart"
html_common:
uri: "html/html_common/html_common_dart2js.dart"
html_common:
uri: "html/html_common/html_common_dart2js.dart"
indexed_db:
uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
indexed_db:
uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
js:
uri: "js/js.dart"
patches: "_internal/js_dev_runtime/patch/js_patch.dart"
js:
uri: "js/js.dart"
patches: "_internal/js_dev_runtime/patch/js_patch.dart"
js_interop:
uri: "js_interop/js_interop.dart"
patches: "_internal/js_shared/lib/js_interop_patch.dart"
js_interop:
uri: "js_interop/js_interop.dart"
patches: "_internal/js_shared/lib/js_interop_patch.dart"
js_interop_unsafe:
uri: "js_interop_unsafe/js_interop_unsafe.dart"
patches: "_internal/js_shared/lib/js_interop_unsafe_patch.dart"
js_interop_unsafe:
uri: "js_interop_unsafe/js_interop_unsafe.dart"
patches: "_internal/js_shared/lib/js_interop_unsafe_patch.dart"
js_util:
uri: "js_util/js_util.dart"
patches:
- "_internal/js_shared/lib/js_util_patch.dart"
- "_internal/js_dev_runtime/patch/js_allow_interop_patch.dart"
js_util:
uri: "js_util/js_util.dart"
patches:
- "_internal/js_shared/lib/js_util_patch.dart"
- "_internal/js_dev_runtime/patch/js_allow_interop_patch.dart"
svg:
uri: "svg/dart2js/svg_dart2js.dart"
svg:
uri: "svg/dart2js/svg_dart2js.dart"
web_audio:
uri: "web_audio/dart2js/web_audio_dart2js.dart"
web_audio:
uri: "web_audio/dart2js/web_audio_dart2js.dart"
web_gl:
uri: "web_gl/dart2js/web_gl_dart2js.dart"
web_gl:
uri: "web_gl/dart2js/web_gl_dart2js.dart"
+2 -3
View File
@@ -1056,7 +1056,6 @@
"meta": {
"description": "This configuration is used by the VM AOT builders. Includes VM service testing in addition to legacy Observatory service tests.",
"__comment__": "This configuration should be merged with the other VM AOT builders config below once Observatory is removed."
},
"steps": [
{
@@ -1089,7 +1088,6 @@
"meta": {
"description": "This configuration is used by the VM AOT builders. Includes VM service testing.",
"__comment__": "vm-aot-linux-debug-x64 should be added back into this configuration once Observatory is removed."
},
"steps": [
{
@@ -2947,6 +2945,7 @@
"tools/verify_docs/bin/verify_docs.dart",
"dart:_http",
"dart:_internal",
"dart:_macros",
"dart:_wasm",
"dart:cli",
"dart:convert",
@@ -3025,7 +3024,7 @@
"pkg-win-release-arm64"
],
"meta": {
"description": "This configuration is used by the pkg builders, no shards."
"description": "This configuration is used by the pkg builders, no shards."
},
"steps": [
{