| // Copyright (c) 2021, 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 '../api.dart'; |
| |
| /// The base interface used to add declarations to the program as well |
| /// as augment existing ones. |
| abstract class Builder {} |
| |
| /// Allows you to resolve arbitrary [Identifier]s. |
| /// |
| /// This class will likely disappear entirely once we have a different |
| /// mechanism. |
| abstract class IdentifierResolver { |
| /// 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. |
| @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 class TypeBuilder implements Builder, IdentifierResolver { |
| /// 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 interface used to create [StaticType] instances, which are used to |
| /// examine type relationships. |
| /// |
| /// This api is only available to the declaration and definition phases of |
| /// macro expansion. |
| abstract class TypeResolver { |
| /// Instantiates a new [StaticType] for a given [type] annotation. |
| /// |
| /// 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 api used to introspect on a [ClassDeclaration]. |
| /// |
| /// Available in the declaration and definition phases, but limited in the |
| /// declaration phase to immediately annotated [ClassDeclaration]s. This is |
| /// done by limiting the access to the [TypeDeclarationResolver] to the |
| /// definition phase. |
| abstract class ClassIntrospector { |
| /// The fields available for [clazz]. |
| /// |
| /// This may be incomplete if in the declaration phase and additional macros |
| /// are going to run on this class. |
| Future<List<FieldDeclaration>> fieldsOf(covariant ClassDeclaration clazz); |
| |
| /// The methods available so far for the current class. |
| /// |
| /// This may be incomplete if additional declaration macros are running on |
| /// this class. |
| Future<List<MethodDeclaration>> methodsOf(covariant ClassDeclaration clazz); |
| |
| /// The constructors available so far for the current class. |
| /// |
| /// This may be incomplete if additional declaration macros are running on |
| /// this class. |
| Future<List<ConstructorDeclaration>> constructorsOf( |
| covariant ClassDeclaration clazz); |
| |
| /// The class that is directly extended via an `extends` clause. |
| Future<ClassDeclaration?> superclassOf(covariant ClassDeclaration clazz); |
| |
| /// All of the classes that are mixed in with `with` clauses. |
| Future<List<ClassDeclaration>> mixinsOf(covariant ClassDeclaration clazz); |
| |
| /// All of the classes that are implemented with an `implements` clause. |
| Future<List<ClassDeclaration>> interfacesOf(covariant ClassDeclaration clazz); |
| } |
| |
| /// 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 class DeclarationBuilder |
| implements Builder, IdentifierResolver, TypeResolver, ClassIntrospector { |
| /// 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 class. |
| abstract class ClassMemberDeclarationBuilder implements DeclarationBuilder { |
| /// Adds a new declaration to the surrounding class. |
| void declareInClass(DeclarationCode declaration); |
| } |
| |
| /// The interface used by [Macro]s to resolve any [Identifier]s pointing to |
| /// types to their type declarations. |
| /// |
| /// Only available in the definition phase of macro expansion. |
| abstract class TypeDeclarationResolver { |
| /// Resolves an [identifier] to its [TypeDeclaration]. |
| /// |
| /// If [identifier] does resolve to a [TypeDeclaration], then an |
| /// [ArgumentError] is thrown. |
| Future<TypeDeclaration> declarationOf(covariant Identifier identifier); |
| } |
| |
| /// The interface used by [Macro]s to get the inferred type for an |
| /// [OmittedTypeAnnotation]. |
| /// |
| /// Only available in the definition phase of macro expansion. |
| abstract class TypeInferrer { |
| /// 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); |
| } |
| |
| /// 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 class DefinitionBuilder |
| implements |
| Builder, |
| IdentifierResolver, |
| TypeResolver, |
| ClassIntrospector, |
| TypeDeclarationResolver, |
| TypeInferrer {} |
| |
| /// The apis used by [Macro]s that run on classes, to fill in the definitions |
| /// of any external declarations within that class. |
| abstract class ClassDefinitionBuilder 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 to define the body of a constructor |
| /// or wrap the body of an existing constructor with additional statements. |
| abstract class ConstructorDefinitionBuilder implements DefinitionBuilder { |
| /// Augments an existing constructor body with [body] and [initializers]. |
| /// |
| /// The [initializers] should not contain trailing or preceding commas. |
| /// |
| /// TODO: Link the library augmentations proposal to describe the semantics. |
| void augment({FunctionBodyCode? body, List<Code>? initializers}); |
| } |
| |
| /// The apis used by [Macro]s to augment functions or methods. |
| abstract class FunctionDefinitionBuilder implements DefinitionBuilder { |
| /// Augments the function. |
| /// |
| /// TODO: Link the library augmentations proposal to describe the semantics. |
| void augment(FunctionBodyCode body); |
| } |
| |
| /// The api used by [Macro]s to augment a top level variable or instance field. |
| abstract 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). |
| /// |
| /// TODO: Link the library augmentations proposal to describe the semantics. |
| void augment({ |
| DeclarationCode? getter, |
| DeclarationCode? setter, |
| ExpressionCode? initializer, |
| }); |
| } |