From e00db2dca2483791c5f4457f64859c72534bbfab Mon Sep 17 00:00:00 2001 From: Jake Macdonald Date: Thu, 22 Feb 2024 15:20:52 +0000 Subject: [PATCH] Add package:macros - Also adds the public exception APIs to dart:_macros which were missing. Change-Id: If08bcb8bc60b91eaf08a02140c6d310e7c2e51f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353540 Reviewed-by: Konstantin Shcheglov Reviewed-by: Johnni Winther Commit-Queue: Jake Macdonald --- .../lib/src/generated/error_verifier.dart | 7 + pkg/macros/CHANGELOG.md | 3 + pkg/macros/LICENSE | 27 ++++ pkg/macros/OWNERS | 1 + pkg/macros/README.md | 6 + pkg/macros/analysis_options.yaml | 5 + pkg/macros/lib/api.dart | 142 ++++++++++++++++++ pkg/macros/pubspec.yaml | 12 ++ .../sdk_library_metadata/lib/libraries.dart | 13 +- sdk/lib/_macros/exceptions.dart | 57 +++++++ sdk/lib/_macros/macros.dart | 1 + 11 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 pkg/macros/CHANGELOG.md create mode 100644 pkg/macros/LICENSE create mode 100644 pkg/macros/OWNERS create mode 100644 pkg/macros/README.md create mode 100644 pkg/macros/analysis_options.yaml create mode 100644 pkg/macros/lib/api.dart create mode 100644 pkg/macros/pubspec.yaml create mode 100644 sdk/lib/_macros/exceptions.dart diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 3e6c9e1116a..854589e9e32 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -2892,6 +2892,13 @@ class ErrorVerifier extends RecursiveAstVisitor // should be private var sdk = _currentLibrary.context.sourceFactory.dartSdk!; var uri = exportedLibrary.source.uri.toString(); + + // We allow exporting `dart:_macros` from `package:macros`. + if (uri == 'dart:_macros' && + _currentLibrary.source.uri.scheme == 'package' && + _currentLibrary.source.uri.pathSegments.first == 'macros') { + return; + } var sdkLibrary = sdk.getSdkLibrary(uri); if (sdkLibrary == null) { return; diff --git a/pkg/macros/CHANGELOG.md b/pkg/macros/CHANGELOG.md new file mode 100644 index 00000000000..5470a0b91ab --- /dev/null +++ b/pkg/macros/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 + +Initial release, highly experimental at this time. diff --git a/pkg/macros/LICENSE b/pkg/macros/LICENSE new file mode 100644 index 00000000000..b03a7886835 --- /dev/null +++ b/pkg/macros/LICENSE @@ -0,0 +1,27 @@ +Copyright 2024, the Dart project authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google LLC nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/macros/OWNERS b/pkg/macros/OWNERS new file mode 100644 index 00000000000..876a88472ff --- /dev/null +++ b/pkg/macros/OWNERS @@ -0,0 +1 @@ +file:/tools/OWNERS_FOUNDATION diff --git a/pkg/macros/README.md b/pkg/macros/README.md new file mode 100644 index 00000000000..d6a5710a3ef --- /dev/null +++ b/pkg/macros/README.md @@ -0,0 +1,6 @@ +☠☠ **Warning: This package is experimental and may be removed in a future +version of Dart.** ☠☠ + +This package is for macro authors, and exposes the APIs necessary to write +a macro. Specifically, it exports the `dart:_macros` library, but enables +versioning separate from the SDK itself. diff --git a/pkg/macros/analysis_options.yaml b/pkg/macros/analysis_options.yaml new file mode 100644 index 00000000000..055ac10871c --- /dev/null +++ b/pkg/macros/analysis_options.yaml @@ -0,0 +1,5 @@ +include: package:lints/recommended.yaml + +analyzer: + language: + strict-casts: true diff --git a/pkg/macros/lib/api.dart b/pkg/macros/lib/api.dart new file mode 100644 index 00000000000..008a1da2b1d --- /dev/null +++ b/pkg/macros/lib/api.dart @@ -0,0 +1,142 @@ +// 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. + +// The actual functionality exposed by this package is implemented in +// "dart:_macros", since the version used by precompiled SDK binaries must +// match exactly the version a user gets in their local version solve. This +// package exists as a shell to expose that internal API to outside code, with +// a versioning mechanism that is separate from the SDK itself. +// +// There are both public and private libraries as a part of `dart:_macros`, we +// only want to expose the public portions from this library, and use explicit +// shows to do that. + +export 'dart:_macros' + show + Annotatable, + Builder, + ClassDeclaration, + ClassDeclarationsMacro, + ClassDefinitionMacro, + ClassTypeBuilder, + ClassTypesMacro, + Code, + CodeKind, + CommentCode, + ConstructorDeclaration, + ConstructorDeclarationsMacro, + ConstructorDefinitionBuilder, + ConstructorDefinitionMacro, + ConstructorMetadataAnnotation, + ConstructorTypesMacro, + Declaration, + DeclarationAsTarget, + DeclarationBuilder, + DeclarationCode, + DeclarationDiagnosticTarget, + DeclarationPhaseIntrospector, + DefinitionBuilder, + DefinitionPhaseIntrospector, + Diagnostic, + DiagnosticException, + DiagnosticMessage, + DiagnosticTarget, + EnumDeclaration, + EnumDeclarationBuilder, + EnumDeclarationsMacro, + EnumDefinitionBuilder, + EnumDefinitionMacro, + EnumTypeBuilder, + EnumTypesMacro, + EnumValueDeclaration, + EnumValueDeclarationsMacro, + EnumValueDefinitionBuilder, + EnumValueDefinitionMacro, + EnumValueTypesMacro, + ExpressionCode, + ExtensionDeclaration, + ExtensionDeclarationsMacro, + ExtensionDefinitionMacro, + ExtensionTypeDeclaration, + ExtensionTypeDeclarationsMacro, + ExtensionTypeDefinitionMacro, + ExtensionTypesMacro, + ExtensionTypeTypesMacro, + FieldDeclaration, + FieldDeclarationsMacro, + FieldDefinitionMacro, + FieldTypesMacro, + FormalParameter, + FormalParameterDeclaration, + FunctionBodyCode, + FunctionDeclaration, + FunctionDeclarationsMacro, + FunctionDefinitionBuilder, + FunctionDefinitionMacro, + FunctionTypeAnnotation, + FunctionTypeAnnotationCode, + FunctionTypesMacro, + Identifier, + IdentifierMetadataAnnotation, + InterfaceTypesBuilder, + LanguageVersion, + Library, + LibraryDeclarationsMacro, + LibraryDefinitionBuilder, + LibraryDefinitionMacro, + LibraryTypesMacro, + Macro, + MacroException, + MacroImplementationException, + MacroIntrospectionCycleException, + MacroTarget, + MemberDeclaration, + MemberDeclarationBuilder, + MetadataAnnotation, + MetadataAnnotationAsTarget, + MetadataAnnotationDiagnosticTarget, + MethodDeclaration, + MethodDeclarationsMacro, + MethodDefinitionMacro, + MethodTypesMacro, + MixinDeclaration, + MixinDeclarationsMacro, + MixinDefinitionMacro, + MixinTypeBuilder, + MixinTypesBuilder, + MixinTypesMacro, + NamedStaticType, + NamedTypeAnnotation, + NamedTypeAnnotationCode, + NullableTypeAnnotationCode, + OmittedTypeAnnotation, + OmittedTypeAnnotationCode, + ParameterCode, + ParameterizedTypeDeclaration, + RawCode, + RawTypeAnnotationCode, + RecordFieldDeclaration, + RecordFieldCode, + RecordTypeAnnotation, + RecordTypeAnnotationCode, + Severity, + StaticType, + TypeAliasDeclaration, + TypeAnnotation, + TypeAnnotationAsTarget, + TypeAnnotationCode, + TypeAnnotationDiagnosticTarget, + TypeBuilder, + TypeDeclaration, + TypeDefinitionBuilder, + TypeParameter, + TypeParameterCode, + TypeParameterDeclaration, + TypePhaseIntrospector, + UnexpectedMacroException, + VariableDeclaration, + VariableDeclarationsMacro, + VariableDefinitionBuilder, + VariableDefinitionMacro, + VariableTypesMacro; diff --git a/pkg/macros/pubspec.yaml b/pkg/macros/pubspec.yaml new file mode 100644 index 00000000000..680cc24111a --- /dev/null +++ b/pkg/macros/pubspec.yaml @@ -0,0 +1,12 @@ +name: macros +version: 0.1.0 +description: >- + This package is for macro authors, and exposes the APIs necessary to write + a macro. It exports the APIs from the `dart:_macros` library, but enables + versioning separate from the SDK itself. +repository: https://github.com/dart-lang/sdk/tree/main/pkg/macros + +environment: + # Restrict the upper bound to the next release, which allows us to do breaking + # changes if required, in minor SDK releases. + sdk: ">=3.4.0-0 <3.5.0" diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart index 52f6a2cd22a..1e99ff86aa3 100644 --- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart +++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart @@ -309,8 +309,17 @@ const Map libraries = const { documented: false, platforms: DART2JS_PLATFORM, ), - "_wasm": const LibraryInfo('_wasm/wasm_types.dart', - categories: '', documented: false), + "_wasm": const LibraryInfo( + '_wasm/wasm_types.dart', + categories: '', + documented: false, + ), + "_macros": const LibraryInfo( + '_macros/macros.dart', + documented: false, + platforms: VM_PLATFORM, + maturity: Maturity.EXPERIMENTAL, + ), }; /// Information about a "dart:" library. diff --git a/sdk/lib/_macros/exceptions.dart b/sdk/lib/_macros/exceptions.dart new file mode 100644 index 00000000000..01356e1f0e7 --- /dev/null +++ b/sdk/lib/_macros/exceptions.dart @@ -0,0 +1,57 @@ +// 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; + +/// Exception for use in macro implementations. +/// +/// Throw to stop the current macro execution and report a [Diagnostic]. +class DiagnosticException implements Exception { + final Diagnostic diagnostic; + DiagnosticException(this.diagnostic); +} + +/// Base class for exceptions thrown by the host implementation during macro +/// execution. +/// +/// Macro implementations can catch these exceptions to provide more +/// information to the user. In case an exception results from user error, they +/// can provide a pointer to the likely fix. If the exception results from an +/// implementation error or unknown error, the macro implementation might give +/// the user information on where and how to file an issue. +/// +/// If a `MacroException` is not caught by a macro implementation then it will +/// be reported in a user-oriented way, for example for +/// `MacroImplementationException` the displayed message suggests that there +/// is a bug in the macro implementation. +abstract interface class MacroException implements Exception { + String get message; + String? get stackTrace; +} + +/// Something unexpected happened during macro execution. +/// +/// For example, a bug in the SDK. +abstract interface class UnexpectedMacroException implements MacroException {} + +/// An error due to incorrect implementation was thrown during macro execution. +/// +/// For example, an incorrect argument was passed to the macro API. +/// +/// The type `Error` is usually used for such throwables, and it's common to +/// allow the program to crash when one is thrown. +/// +/// In the case of macros, however, type `Exception` is used because the macro +/// implementation can usefully catch it in order to give the user information +/// about how to notify the macro author about the bug. +abstract interface class MacroImplementationException + implements MacroException {} + +/// A cycle was detected in macro applications introspecting targets of other +/// macro applications. +/// +/// The order the macros should run in is not defined, so allowing +/// introspection in this case would make the macro output non-deterministic. +/// Instead, all the introspection calls in the cycle fail with this exception. +abstract interface class MacroIntrospectionCycleException + implements MacroException {} diff --git a/sdk/lib/_macros/macros.dart b/sdk/lib/_macros/macros.dart index 8d148f0c13a..b66da7fd8b3 100644 --- a/sdk/lib/_macros/macros.dart +++ b/sdk/lib/_macros/macros.dart @@ -10,5 +10,6 @@ import 'dart:collection' show UnmodifiableListView; part 'builders.dart'; part 'code.dart'; part 'diagnostic.dart'; +part 'exceptions.dart'; part 'introspection.dart'; part 'macro.dart';