blob: ffb2d2dde05087ce32b3589d934dd16fe1f72e83 [file]
// Copyright (c) 2025, 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.
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_environment.dart';
import '../../base/local_scope.dart';
import '../../base/messages.dart';
import '../../base/scope.dart';
import '../../base/uri_offset.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/metadata_builder.dart';
import '../../builder/type_builder.dart';
import '../../kernel/body_builder_context.dart';
import '../../kernel/hierarchy/class_member.dart';
import '../../kernel/hierarchy/members_builder.dart';
import '../../kernel/internal_ast.dart';
import '../../kernel/kernel_helper.dart';
import '../../kernel/type_algorithms.dart';
import '../../source/name_scheme.dart';
import '../../source/source_class_builder.dart';
import '../../source/source_library_builder.dart';
import '../../source/source_loader.dart';
import '../../source/source_member_builder.dart';
import '../../source/source_method_builder.dart';
import '../../source/stack_listener_impl.dart' show AsyncModifier;
import '../../source/type_parameter_factory.dart';
import '../../type_inference/context_allocation_strategy.dart';
import '../../type_inference/type_schema.dart';
import '../fragment.dart';
import 'body_builder_context.dart';
import 'encoding.dart';
/// Interface for the method declaration aspect of a [SourceMethodBuilder].
///
/// If a method is augmented, it will have multiple
/// [MethodDeclaration]s on a single [SourceMethodBuilder].
abstract class MethodDeclaration {
UriOffsetLength get uriOffset;
Uri get fileUri;
Procedure get invokeTarget;
bool get isOperator;
List<MetadataBuilder>? get metadata;
Procedure? get readTarget;
void buildOutlineExpressions({
required ClassHierarchy classHierarchy,
required SourceLibraryBuilder libraryBuilder,
required DeclarationBuilder? declarationBuilder,
required SourceMethodBuilder methodBuilder,
required Annotatable annotatable,
required Uri annotatableFileUri,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
});
void buildOutlineNode({
required SourceLibraryBuilder libraryBuilder,
required ProblemReporting problemReporting,
required NameScheme nameScheme,
required BuildNodesCallback callback,
required MethodReferences? references,
required List<TypeParameter>? classTypeParameters,
});
void checkTypes(
ProblemReporting problemReporting,
TypeEnvironment typeEnvironment,
);
void checkVariance(
SourceClassBuilder sourceClassBuilder,
TypeEnvironment typeEnvironment,
);
int computeDefaultTypes(ComputeDefaultTypeContext context);
void createEncoding({
required ProblemReporting problemReporting,
required SourceMethodBuilder builder,
required MethodEncodingStrategy encodingStrategy,
required TypeParameterFactory typeParameterFactory,
required bool isImplementation,
});
void ensureTypes(
ClassMembersBuilder membersBuilder,
SourceClassBuilder enclosingClassBuilder,
Set<ClassMember>? overrideDependencies,
);
}
class MethodDeclarationImpl
implements MethodDeclaration, MethodFragmentDeclaration {
final MethodFragment _fragment;
late final MethodEncoding _encoding;
late final bool _isImplementation;
new(this._fragment) {
_fragment.declaration = this;
}
@override
bool get isImplementation => _isImplementation;
@override
UriOffsetLength get uriOffset => _fragment.uriOffset;
@override
Uri get fileUri => _fragment.fileUri;
@override
// TODO: implement formals
List<FormalParameterBuilder>? get formals => _encoding.formals;
@override
bool get isNoSuchMethodForwarder => _encoding.isNoSuchMethodForwarder;
@override
Procedure get invokeTarget => _encoding.invokeTarget;
@override
bool get isOperator => _fragment.isOperator;
@override
// Coverage-ignore(suite): Not run.
List<MetadataBuilder>? get metadata => _fragment.metadata;
@override
Procedure? get readTarget => _encoding.readTarget;
@override
TypeBuilder get returnType => _fragment.returnType;
@override
List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
@override
InternalVariable? get thisVariable => _encoding.thisVariable;
@override
void becomeNative(SourceLoader loader) {
_encoding.becomeNative(loader);
}
@override
void buildOutlineExpressions({
required ClassHierarchy classHierarchy,
required SourceLibraryBuilder libraryBuilder,
required DeclarationBuilder? declarationBuilder,
required SourceMethodBuilder methodBuilder,
required Annotatable annotatable,
required Uri annotatableFileUri,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
}) {
_encoding.buildOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
methodBuilder: methodBuilder,
bodyBuilderContext: createBodyBuilderContext(methodBuilder),
annotatable: annotatable,
annotatableFileUri: annotatableFileUri,
delayedDefaultValueCloners: delayedDefaultValueCloners,
);
}
@override
void buildOutlineNode({
required SourceLibraryBuilder libraryBuilder,
required ProblemReporting problemReporting,
required NameScheme nameScheme,
required BuildNodesCallback callback,
required MethodReferences? references,
required List<TypeParameter>? classTypeParameters,
}) {
_encoding.buildOutlineNode(
libraryBuilder: libraryBuilder,
problemReporting: problemReporting,
nameScheme: nameScheme,
callback: callback,
references: references,
isAbstractOrExternal:
_fragment.modifiers.isAbstract || _fragment.modifiers.isExternal,
classTypeParameters: classTypeParameters,
);
}
@override
void checkTypes(
ProblemReporting problemReporting,
TypeEnvironment typeEnvironment,
) {
_encoding.checkTypes(problemReporting, typeEnvironment);
}
@override
void checkVariance(
SourceClassBuilder sourceClassBuilder,
TypeEnvironment typeEnvironment,
) {
_encoding.checkVariance(sourceClassBuilder, typeEnvironment);
}
@override
int computeDefaultTypes(ComputeDefaultTypeContext context) {
return _encoding.computeDefaultTypes(context);
}
@override
BodyBuilderContext createBodyBuilderContext(SourceMethodBuilder builder) {
return new MethodFragmentBodyBuilderContext(
_fragment,
this,
builder.libraryBuilder,
builder.declarationBuilder,
isDeclarationInstanceMember: builder.isDeclarationInstanceMember,
);
}
@override
void createEncoding({
required ProblemReporting problemReporting,
required SourceMethodBuilder builder,
required MethodEncodingStrategy encodingStrategy,
required TypeParameterFactory typeParameterFactory,
required bool isImplementation,
}) {
_isImplementation = isImplementation;
_encoding = encodingStrategy.createMethodEncoding(
builder,
_fragment,
typeParameterFactory,
);
_fragment.typeParameterNameSpace.addTypeParameters(
problemReporting,
_encoding.clonedAndDeclaredTypeParameters,
ownerName: _fragment.name,
allowNameConflict: true,
);
returnType.registerInferredTypeListener(_encoding);
}
@override
LocalScope createFormalParameterScope(LookupScope typeParameterScope) {
return _encoding.createFormalParameterScope(typeParameterScope);
}
@override
void ensureTypes(
ClassMembersBuilder membersBuilder,
SourceClassBuilder enclosingClassBuilder,
Set<ClassMember>? overrideDependencies,
) {
if (overrideDependencies != null) {
membersBuilder.inferMethodType(
enclosingClassBuilder,
_encoding.function,
returnType,
_fragment.declaredFormals,
overrideDependencies,
name: _fragment.name,
fileUri: fileUri,
nameOffset: _fragment.nameOffset,
nameLength: _fragment.name.length,
);
}
_encoding.ensureTypes(
enclosingClassBuilder.libraryBuilder,
membersBuilder.hierarchyBuilder,
);
}
@override
void registerFunctionBody({
required Statement? body,
required AsyncModifier asyncModifier,
required DartType? emittedValueType,
required ScopeProviderInfo? scopeProviderInfo,
}) {
_encoding.registerFunctionBody(
body: body,
asyncModifier: asyncModifier,
emittedValueType: emittedValueType,
scopeProviderInfo: scopeProviderInfo,
);
}
@override
DartType get returnTypeContext {
final bool isReturnTypeUndeclared =
_fragment.returnType is OmittedTypeBuilder &&
_encoding.function.returnType is DynamicType;
return isReturnTypeUndeclared
? const UnknownType()
: _encoding.function.returnType;
}
}
/// Interface for using a [MethodFragment] to create a [BodyBuilderContext].
abstract class MethodFragmentDeclaration {
List<FormalParameterBuilder>? get formals;
void registerFunctionBody({
required Statement? body,
required AsyncModifier asyncModifier,
required DartType? emittedValueType,
required ScopeProviderInfo? scopeProviderInfo,
});
DartType get returnTypeContext;
bool get isNoSuchMethodForwarder;
/// Whether this declaration hold the implementation for the method.
///
/// For augmentations, only one of the method declarations is considered
/// as the implementation. Other declarations can only provide annotations
/// for the generated AST node.
bool get isImplementation;
TypeBuilder get returnType;
List<TypeParameter>? get thisTypeParameters;
InternalVariable? get thisVariable;
void becomeNative(SourceLoader loader);
BodyBuilderContext createBodyBuilderContext(SourceMethodBuilder builder);
LocalScope createFormalParameterScope(LookupScope typeParameterScope);
}