diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart index f76cfeeaf4b..f4a78a1652c 100644 --- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart +++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart @@ -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 _LIBRARIES = [ _LIB_INTERNAL, _LIB_IO, _LIB_ISOLATE, + _LIB_MACROS, _LIB_MATH, _LIB_TYPED_DATA, _LIB_WASM, diff --git a/pkg/analyzer/test/src/diagnostics/import_internal_library_test.dart b/pkg/analyzer/test/src/diagnostics/import_internal_library_test.dart index 6068a6c46df..43537f75c40 100644 --- a/pkg/analyzer/test/src/diagnostics/import_internal_library_test.dart +++ b/pkg/analyzer/test/src/diagnostics/import_internal_library_test.dart @@ -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', ''' diff --git a/pkg/analyzer_cli/tool/perf.dart b/pkg/analyzer_cli/tool/perf.dart index a3ce50419af..b88d79ca4f2 100644 --- a/pkg/analyzer_cli/tool/perf.dart +++ b/pkg/analyzer_cli/tool/perf.dart @@ -173,6 +173,7 @@ Set scanReachableFiles(Uri entryUri) { 'dart:core', 'dart:developer', 'dart:_internal', + 'dart:_macros', 'dart:isolate', 'dart:math', 'dart:mirrors', diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart index 96b4964df46..9023f206bd1 100644 --- a/pkg/compiler/lib/src/kernel/dart2js_target.dart +++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart @@ -275,6 +275,7 @@ const requiredLibraries = >{ '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 = >{ 'dart:_js_types', 'dart:_late_helper', 'dart:_load_library_priority', + 'dart:_macros', 'dart:_native_typed_data', 'dart:_recipe_syntax', 'dart:_rti', diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart index 7f1bdc99f22..9c4a05446bd 100644 --- a/pkg/dart2wasm/lib/target.dart +++ b/pkg/dart2wasm/lib/target.dart @@ -144,6 +144,7 @@ class WasmTarget extends Target { 'dart:_internal', 'dart:_js_helper', 'dart:_js_types', + 'dart:_macros', 'dart:_wasm', 'dart:async', 'dart:developer', diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart index 59c7c79c6ee..c81f22003b2 100644 --- a/pkg/dev_compiler/lib/src/kernel/target.dart +++ b/pkg/dev_compiler/lib/src/kernel/target.dart @@ -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', diff --git a/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.1.expect b/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.1.expect index 8a0cc2909ad..2a60735e94e 100644 --- a/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.1.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.2.expect b/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.2.expect index 0e7c789b0be..c2431532f65 100644 --- a/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental/await_in_non_async.yaml.world.2.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/bad_sdk_uri.yaml.world.3.expect b/pkg/front_end/testcases/incremental/bad_sdk_uri.yaml.world.3.expect index a8d71be3fe5..d1df8bceb46 100644 --- a/pkg/front_end/testcases/incremental/bad_sdk_uri.yaml.world.3.expect +++ b/pkg/front_end/testcases/incremental/bad_sdk_uri.yaml.world.3.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.1.expect b/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.1.expect index ab378a3c999..3eaac76e785 100644 --- a/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.1.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.2.expect b/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.2.expect index ab378a3c999..3eaac76e785 100644 --- a/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental/load_from_component_explicitly_import_dart_core.yaml.world.2.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.1.expect index 4981234ae47..cd12e4afa15 100644 --- a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.1.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.4.expect b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.4.expect index b1013a0a358..e9df8c84797 100644 --- a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.4.expect +++ b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.4.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.5.expect b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.5.expect index c3d91f8d50a..85129d7eb01 100644 --- a/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.5.expect +++ b/pkg/front_end/testcases/incremental/omit_platform_works_3.yaml.world.5.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/patterns.yaml.world.1.expect b/pkg/front_end/testcases/incremental/patterns.yaml.world.1.expect index 9994e68fff6..6e3baf19d8e 100644 --- a/pkg/front_end/testcases/incremental/patterns.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental/patterns.yaml.world.1.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/patterns.yaml.world.2.expect b/pkg/front_end/testcases/incremental/patterns.yaml.world.2.expect index 9b2f9fd8123..129c9861ee3 100644 --- a/pkg/front_end/testcases/incremental/patterns.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental/patterns.yaml.world.2.expect @@ -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 diff --git a/pkg/front_end/testcases/incremental/patterns.yaml.world.3.expect b/pkg/front_end/testcases/incremental/patterns.yaml.world.3.expect index 9994e68fff6..6e3baf19d8e 100644 --- a/pkg/front_end/testcases/incremental/patterns.yaml.world.3.expect +++ b/pkg/front_end/testcases/incremental/patterns.yaml.world.3.expect @@ -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 diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart index c8a598f9c1d..535e42cc66a 100644 --- a/pkg/kernel/lib/target/targets.dart +++ b/pkg/kernel/lib/target/targets.dart @@ -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]. diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart index abb071660d1..69d6e9894c4 100644 --- a/pkg/vm/lib/target/dart_runner.dart +++ b/pkg/vm/lib/target/dart_runner.dart @@ -21,6 +21,7 @@ class DartRunnerTarget extends VmTarget { 'dart:developer', 'dart:ffi', 'dart:_internal', + 'dart:_macros', 'dart:isolate', 'dart:math', diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart index 0ed541a8817..a691e51fc4c 100644 --- a/pkg/vm/lib/target/flutter.dart +++ b/pkg/vm/lib/target/flutter.dart @@ -27,6 +27,7 @@ class FlutterTarget extends VmTarget { 'dart:developer', 'dart:ffi', 'dart:_internal', + 'dart:_macros', 'dart:isolate', 'dart:math', diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart index 5d93e7c91a8..263a4424316 100644 --- a/pkg/vm/lib/target/flutter_runner.dart +++ b/pkg/vm/lib/target/flutter_runner.dart @@ -21,6 +21,7 @@ class FlutterRunnerTarget extends VmTarget { 'dart:developer', 'dart:ffi', 'dart:_internal', + 'dart:_macros', 'dart:isolate', 'dart:math', diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart index b4283a560d5..8a8c333204f 100644 --- a/pkg/vm/lib/target/vm.dart +++ b/pkg/vm/lib/target/vm.dart @@ -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 get extraRequiredLibrariesPlatform => const []; + List get extraRequiredLibrariesPlatform => const [ + 'dart:_macros', + ]; void _patchVmConstants(CoreTypes coreTypes) { // Fix Endian.host to be a const field equal to Endian.little instead of diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect index 43edfd24569..bdfeddfc700 100644 --- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect +++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect @@ -14,6 +14,7 @@ LoadingUnit(id=1, parent=0, dart:mirrors dart:math dart:isolate + dart:_macros dart:_internal dart:ffi dart:developer diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index a594ff23fab..50fa5e0da5d 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -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", diff --git a/sdk/lib/_macros/builders.dart b/sdk/lib/_macros/builders.dart new file mode 100644 index 00000000000..d11e9aaddd8 --- /dev/null +++ b/sdk/lib/_macros/builders.dart @@ -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 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 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 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 resolve(TypeAnnotationCode type); + + /// The values available for [enuum]. + /// + /// This may be incomplete if additional declaration macros are going to run + /// on [enuum]. + Future> valuesOf(covariant EnumDeclaration enuum); + + /// The fields available for [type]. + /// + /// This may be incomplete if additional declaration macros are going to run + /// on [type]. + Future> fieldsOf(covariant TypeDeclaration type); + + /// The methods available for [type]. + /// + /// This may be incomplete if additional declaration macros are going to run + /// on [type]. + Future> methodsOf(covariant TypeDeclaration type); + + /// The constructors available for [type]. + /// + /// This may be incomplete if additional declaration macros are going to run + /// on [type]. + Future> 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> typesOf(covariant Library library); + + /// Resolves an [identifier] to its [TypeDeclaration]. + /// + /// If [identifier] does not resolve to a [TypeDeclaration], then an + /// [ArgumentError] is thrown. + Future 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 declarationOf(covariant Identifier identifier); + + /// Resolves an [identifier] referring to a type to its [TypeDeclaration]. + @override + Future 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 inferType(covariant OmittedTypeAnnotation omittedType); + + /// Returns a list of all the [Declaration]s in the given [library]. + Future> 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 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 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 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 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 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 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 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? 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); +} diff --git a/sdk/lib/_macros/code.dart b/sdk/lib/_macros/code.dart new file mode 100644 index 00000000000..dac054c256a --- /dev/null +++ b/sdk/lib/_macros/code.dart @@ -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 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 keywords; + final String? name; + final TypeAnnotationCode? type; + + @override + CodeKind get kind => CodeKind.parameter; + + @override + List 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 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 typeArguments; + + @override + CodeKind get kind => CodeKind.namedTypeAnnotation; + + @override + List 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 namedParameters; + + final List optionalPositionalParameters; + + final List positionalParameters; + + final TypeAnnotationCode? returnType; + + final List typeParameters; + + @override + CodeKind get kind => CodeKind.functionTypeAnnotation; + + @override + List 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 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 namedFields; + + final List positionalFields; + + @override + CodeKind get kind => CodeKind.recordTypeAnnotation; + + @override + List 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 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 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 parts) _makeNonNullable( + List parts) { + final Iterator 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 get parts => [ + name, + if (bound != null) ...[ + ' extends ', + bound!, + ] + ]; + + TypeParameterCode({this.bound, required this.name}); +} + +extension Join on List { + /// 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 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, +} diff --git a/sdk/lib/_macros/diagnostic.dart b/sdk/lib/_macros/diagnostic.dart new file mode 100644 index 00000000000..10454f47cd2 --- /dev/null +++ b/sdk/lib/_macros/diagnostic.dart @@ -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 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 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, +} diff --git a/sdk/lib/_macros/introspection.dart b/sdk/lib/_macros/introspection.dart new file mode 100644 index 00000000000..5ab1b16be0d --- /dev/null +++ b/sdk/lib/_macros/introspection.dart @@ -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 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 get positionalParameters; + + /// The named parameters for this function. + Iterable get namedParameters; + + /// The type parameters for this function. + Iterable 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 get typeArguments; +} + +/// The interface for record type declarations. +abstract interface class RecordTypeAnnotation implements TypeAnnotation { + /// The positional fields for this record. + Iterable get positionalFields; + + /// The named fields for this record. + Iterable 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 isSubtypeOf(covariant StaticType other); + + /// Returns true if this is an identical type to [other]. + Future 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 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 get interfaces; + + /// All the `with` type annotations. + Iterable 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 get interfaces; + + /// All the `with` type annotations. + Iterable 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 get interfaces; + + /// All the `on` clause type annotations. + Iterable 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 get positionalParameters; + + /// The named parameters for this function. + Iterable get namedParameters; + + /// The type parameters for this function. + Iterable 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 get positionalArguments; + + /// The named arguments of this constructor call. + Map get namedArguments; +} diff --git a/sdk/lib/_macros/macro.dart b/sdk/lib/_macros/macro.dart new file mode 100644 index 00000000000..73c20f97bba --- /dev/null +++ b/sdk/lib/_macros/macro.dart @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 buildDefinitionForExtensionType( + ExtensionTypeDeclaration extension, TypeDefinitionBuilder builder); +} diff --git a/sdk/lib/_macros/macros.dart b/sdk/lib/_macros/macros.dart new file mode 100644 index 00000000000..8d148f0c13a --- /dev/null +++ b/sdk/lib/_macros/macros.dart @@ -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'; diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json index 541b8452ca7..5cef1cba42a 100644 --- a/sdk/lib/libraries.json +++ b/sdk/lib/libraries.json @@ -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" diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml index be735a7022f..d2e6117c50d 100644 --- a/sdk/lib/libraries.yaml +++ b/sdk/lib/libraries.yaml @@ -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" diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index 530deec3220..bdc3a645ac2 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -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": [ {