blob: 3deaa368e3fbba113897cdd3c2b245a7dc847e77 [file] [log] [blame]
// 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.
import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
show resolveRelativeUri;
import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
import 'package:kernel/names.dart' show indexSetName;
import 'package:kernel/reference_from_index.dart'
show IndexedClass, IndexedContainer, IndexedLibrary;
import 'package:kernel/src/bounds_checks.dart' show VarianceCalculationValue;
import '../api_prototype/experimental_flags.dart';
import '../api_prototype/lowering_predicates.dart';
import '../base/combinator.dart' show CombinatorBuilder;
import '../base/configuration.dart' show Configuration;
import '../base/export.dart' show Export;
import '../base/identifiers.dart' show Identifier, QualifiedNameIdentifier;
import '../base/import.dart' show Import;
import '../base/messages.dart';
import '../base/modifier.dart'
show
abstractMask,
augmentMask,
constMask,
externalMask,
finalMask,
declaresConstConstructorMask,
hasInitializerMask,
initializingFormalMask,
superInitializingFormalMask,
lateMask,
namedMixinApplicationMask,
staticMask;
import '../base/problems.dart' show internalProblem, unhandled;
import '../base/scope.dart';
import '../base/uris.dart';
import '../builder/builder.dart';
import '../builder/constructor_reference_builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/mixin_application_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/prefix_builder.dart';
import '../builder/synthesized_type_builder.dart';
import '../builder/type_builder.dart';
import '../builder/void_type_declaration_builder.dart';
import '../util/local_stack.dart';
import 'builder_factory.dart';
import 'name_scheme.dart';
import 'offset_map.dart';
import 'source_class_builder.dart' show SourceClassBuilder;
import 'source_constructor_builder.dart';
import 'source_enum_builder.dart';
import 'source_extension_builder.dart';
import 'source_extension_type_declaration_builder.dart';
import 'source_factory_builder.dart';
import 'source_field_builder.dart';
import 'source_function_builder.dart';
import 'source_library_builder.dart';
import 'source_loader.dart' show SourceLoader;
import 'source_procedure_builder.dart';
import 'source_type_alias_builder.dart';
import 'type_parameter_scope_builder.dart';
class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
final SourceCompilationUnit _compilationUnit;
final ProblemReporting _problemReporting;
/// The object used as the root for creating augmentation libraries.
// TODO(johnniwinther): Remove this once parts support augmentations.
final SourceLibraryBuilder _augmentationRoot;
/// [SourceLibraryBuilder] used for passing a parent [Builder] to created
/// [Builder]s. These uses are only needed because we creating [Builder]s
/// instead of fragments.
// TODO(johnniwinther): Remove this when we no longer create [Builder]s in
// the outline builder.
final SourceLibraryBuilder _parent;
final LibraryNameSpaceBuilder _libraryNameSpaceBuilder;
/// Index of the library we use references for.
final IndexedLibrary? indexedLibrary;
String? _name;
Uri? _partOfUri;
String? _partOfName;
List<MetadataBuilder>? _metadata;
/// The part directives in this compilation unit.
final List<Part> _parts = [];
final List<LibraryPart> _libraryParts = [];
@override
final List<Import> imports = <Import>[];
@override
final List<Export> exports = <Export>[];
/// Map from synthesized names used for omitted types to their corresponding
/// synthesized type declarations.
///
/// This is used in macro generated code to create type annotations from
/// inferred types in the original code.
final Map<String, Builder>? _omittedTypeDeclarationBuilders;
Map<SourceClassBuilder, TypeBuilder>? _mixinApplications = {};
final List<NominalVariableBuilder> _unboundNominalVariables = [];
final List<StructuralVariableBuilder> _unboundStructuralVariables = [];
final List<SourceFunctionBuilder> _nativeMethods = [];
final LibraryName libraryName;
final LookupScope _scope;
/// Index for building unique lowered names for wildcard variables.
int wildcardVariableIndex = 0;
final LocalStack<TypeScope> _typeScopes;
final LocalStack<NominalParameterNameSpace> _nominalParameterNameSpaces =
new LocalStack([]);
final LocalStack<Map<String, StructuralVariableBuilder>>
_structuralParameterScopes = new LocalStack([]);
final LocalStack<DeclarationFragment> _declarationFragments =
new LocalStack([]);
BuilderFactoryImpl(
{required SourceCompilationUnit compilationUnit,
required SourceLibraryBuilder augmentationRoot,
required SourceLibraryBuilder parent,
required LibraryNameSpaceBuilder libraryNameSpaceBuilder,
required ProblemReporting problemReporting,
required LookupScope scope,
required LibraryName libraryName,
required IndexedLibrary? indexedLibrary,
required Map<String, Builder>? omittedTypeDeclarationBuilders})
: _compilationUnit = compilationUnit,
_augmentationRoot = augmentationRoot,
_libraryNameSpaceBuilder = libraryNameSpaceBuilder,
_problemReporting = problemReporting,
_parent = parent,
_scope = scope,
libraryName = libraryName,
indexedLibrary = indexedLibrary,
_omittedTypeDeclarationBuilders = omittedTypeDeclarationBuilders,
_typeScopes =
new LocalStack([new TypeScope(TypeScopeKind.library, scope)]);
SourceLoader get loader => _compilationUnit.loader;
LibraryFeatures get libraryFeatures => _compilationUnit.libraryFeatures;
final List<ConstructorReferenceBuilder> _constructorReferences = [];
@override
void beginClassOrNamedMixinApplicationHeader() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.declarationTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void beginClassDeclaration(String name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {
_declarationFragments.push(new ClassFragment(
name, charOffset, typeVariables, _typeScopes.current.lookupScope));
}
@override
void beginClassBody() {
_typeScopes.push(new TypeScope(TypeScopeKind.classDeclaration,
_declarationFragments.current.bodyScope, _typeScopes.current));
}
@override
void endClassDeclaration(String name) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.classDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endClassDeclarationForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope bodyScope = _typeScopes.pop();
assert(bodyScope.kind == TypeScopeKind.classDeclaration,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_declarationFragments.pop();
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginMixinDeclaration(String name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {
_declarationFragments.push(new MixinFragment(
name, charOffset, typeVariables, _typeScopes.current.lookupScope));
}
@override
void beginMixinBody() {
_typeScopes.push(new TypeScope(TypeScopeKind.mixinDeclaration,
_declarationFragments.current.bodyScope, _typeScopes.current));
}
@override
void endMixinDeclaration(String name) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.mixinDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endMixinDeclarationForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope bodyScope = _typeScopes.pop();
assert(bodyScope.kind == TypeScopeKind.mixinDeclaration,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_declarationFragments.pop();
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginNamedMixinApplication(String name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {}
@override
void endNamedMixinApplication(String name) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
void endNamedMixinApplicationForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginEnumDeclarationHeader(String name) {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.declarationTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void beginEnumDeclaration(String name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {
_declarationFragments.push(new EnumFragment(
name, charOffset, typeVariables, _typeScopes.current.lookupScope));
}
@override
void beginEnumBody() {
_typeScopes.push(new TypeScope(TypeScopeKind.enumDeclaration,
_declarationFragments.current.bodyScope, _typeScopes.current));
}
@override
void endEnumDeclaration(String name) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.enumDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
void endEnumDeclarationForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.enumDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
_declarationFragments.pop();
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginExtensionOrExtensionTypeHeader() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.declarationTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void beginExtensionDeclaration(String? name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {
_declarationFragments.push(new ExtensionFragment(
name, charOffset, typeVariables, _typeScopes.current.lookupScope));
}
@override
void beginExtensionBody(TypeBuilder? extensionThisType) {
ExtensionFragment declarationFragment =
_declarationFragments.current as ExtensionFragment;
_typeScopes.push(new TypeScope(TypeScopeKind.extensionDeclaration,
declarationFragment.bodyScope, _typeScopes.current));
if (extensionThisType != null) {
declarationFragment.registerExtensionThisType(extensionThisType);
}
}
@override
void endExtensionDeclaration(String? name) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.extensionDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
void beginExtensionTypeDeclaration(String name, int charOffset,
List<NominalVariableBuilder>? typeVariables) {
_declarationFragments.push(new ExtensionTypeFragment(
name, charOffset, typeVariables, _typeScopes.current.lookupScope));
}
@override
void beginExtensionTypeBody() {
_typeScopes.push(new TypeScope(TypeScopeKind.extensionTypeDeclaration,
_declarationFragments.current.bodyScope, _typeScopes.current));
}
@override
void endExtensionTypeDeclaration(String name) {
TypeScope bodyScope = _typeScopes.pop();
assert(
bodyScope.kind == TypeScopeKind.extensionTypeDeclaration,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(
typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeParameterScope.");
}
@override
void beginFactoryMethod() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endFactoryMethod() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endFactoryMethodForParserRecovery() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(_problemReporting, null,
ownerName: null, allowNameConflict: true);
}
@override
void beginConstructor() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endConstructor() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
void endConstructorForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginStaticMethod() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endStaticMethod() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endStaticMethodForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeVariableScope = _typeScopes.pop();
assert(typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginInstanceMethod() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endInstanceMethod() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
void endInstanceMethodForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginTopLevelMethod() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endTopLevelMethod() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
void endTopLevelMethodForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.memberTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginTypedef() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.declarationTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
@override
void endTypedef() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.declarationTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endTypedefForParserRecovery(
List<NominalVariableBuilder>? typeVariables) {
TypeScope typeVariableScope = _typeScopes.pop();
assert(typeVariableScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeVariableScope.");
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: null, allowNameConflict: true);
}
@override
void beginFunctionType() {
Map<String, StructuralVariableBuilder> structuralParameterScope = {};
_structuralParameterScopes.push(structuralParameterScope);
_typeScopes.push(new TypeScope(
TypeScopeKind.functionTypeParameters,
new TypeParameterScope(
_typeScopes.current.lookupScope, structuralParameterScope),
_typeScopes.current));
}
@override
void endFunctionType() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.functionTypeParameters,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
}
void beginUnnamedMixinApplication() {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.unnamedMixinApplication,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
}
void endUnnamedMixinApplication() {
TypeScope typeVariableScope = _typeScopes.pop();
assert(
typeVariableScope.kind == TypeScopeKind.unnamedMixinApplication,
// Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope.");
assert(
typeVariableScope.isEmpty, // Coverage-ignore(suite): Not run.
"Unexpected type scope: $typeVariableScope");
}
@override
void checkStacks() {
assert(
_typeScopes.isSingular,
// Coverage-ignore(suite): Not run.
"Unexpected type scope stack: "
"$_typeScopes.");
assert(
_declarationFragments.isEmpty,
// Coverage-ignore(suite): Not run.
"Unexpected declaration fragment stack: "
"$_declarationFragments.");
assert(
_nominalParameterNameSpaces.isEmpty,
// Coverage-ignore(suite): Not run.
"Unexpected nominal parameter name space stack : "
"$_nominalParameterNameSpaces.");
assert(
_structuralParameterScopes.isEmpty,
// Coverage-ignore(suite): Not run.
"Unexpected structural parameter scope stack : "
"$_structuralParameterScopes.");
}
// TODO(johnniwinther): Use [_indexedContainer] for library members and make
// it [null] when there is null corresponding [IndexedContainer].
IndexedContainer? _indexedContainer;
@override
void beginIndexedContainer(String name,
{required bool isExtensionTypeDeclaration}) {
if (indexedLibrary != null) {
if (isExtensionTypeDeclaration) {
_indexedContainer =
indexedLibrary!.lookupIndexedExtensionTypeDeclaration(name);
} else {
_indexedContainer = indexedLibrary!.lookupIndexedClass(name);
}
}
}
@override
void endIndexedContainer() {
_indexedContainer = null;
}
@override
// Coverage-ignore(suite): Not run.
void registerUnboundStructuralVariables(
List<StructuralVariableBuilder> variableBuilders) {
_unboundStructuralVariables.addAll(variableBuilders);
}
Uri _resolve(Uri baseUri, String? uri, int uriOffset, {isPart = false}) {
if (uri == null) {
// Coverage-ignore-block(suite): Not run.
_problemReporting.addProblem(
messageExpectedUri, uriOffset, noLength, _compilationUnit.fileUri);
return new Uri(scheme: MALFORMED_URI_SCHEME);
}
Uri parsedUri;
try {
parsedUri = Uri.parse(uri);
} on FormatException catch (e) {
// Point to position in string indicated by the exception,
// or to the initial quote if no position is given.
// (Assumes the directive is using a single-line string.)
_problemReporting.addProblem(
templateCouldNotParseUri.withArguments(uri, e.message),
uriOffset +
1 +
(e.offset ?? // Coverage-ignore(suite): Not run.
-1),
1,
_compilationUnit.fileUri);
return new Uri(
scheme: MALFORMED_URI_SCHEME, query: Uri.encodeQueryComponent(uri));
}
if (isPart && baseUri.isScheme("dart")) {
// Coverage-ignore-block(suite): Not run.
// Resolve using special rules for dart: URIs
return resolveRelativeUri(baseUri, parsedUri);
} else {
return baseUri.resolveUri(parsedUri);
}
}
@override
void addPart(OffsetMap offsetMap, Token partKeyword,
List<MetadataBuilder>? metadata, String uri, int charOffset) {
Uri resolvedUri =
_resolve(_compilationUnit.importUri, uri, charOffset, isPart: true);
// To support absolute paths from within packages in the part uri, we try to
// translate the file uri from the resolved import uri before resolving
// through the file uri of this library. See issue #52964.
Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
_resolve(_compilationUnit.fileUri, uri, charOffset);
// TODO(johnniwinther): Add a LibraryPartBuilder instead of using
// [LibraryBuilder] to represent both libraries and parts.
CompilationUnit compilationUnit = loader.read(resolvedUri, charOffset,
origin: _compilationUnit.isAugmenting ? _augmentationRoot.origin : null,
originImportUri: _compilationUnit.originImportUri,
fileUri: newFileUri,
accessor: _compilationUnit,
isPatch: _compilationUnit.isAugmenting);
_parts.add(new Part(charOffset, compilationUnit));
// TODO(ahe): [metadata] should be stored, evaluated, and added to [part].
LibraryPart part = new LibraryPart(<Expression>[], uri)
..fileOffset = charOffset;
_libraryParts.add(part);
offsetMap.registerPart(partKeyword, part);
}
@override
void addPartOf(List<MetadataBuilder>? metadata, String? name, String? uri,
int uriOffset) {
_partOfName = name;
if (uri != null) {
Uri resolvedUri =
_partOfUri = _resolve(_compilationUnit.importUri, uri, uriOffset);
// To support absolute paths from within packages in the part of uri, we
// try to translate the file uri from the resolved import uri before
// resolving through the file uri of this library. See issue #52964.
Uri newFileUri = loader.target.uriTranslator.translate(resolvedUri) ??
_resolve(_compilationUnit.fileUri, uri, uriOffset);
loader.read(partOfUri!, uriOffset,
fileUri: newFileUri, accessor: _compilationUnit);
}
if (_scriptTokenOffset != null) {
_problemReporting.addProblem(messageScriptTagInPartFile,
_scriptTokenOffset!, noLength, _compilationUnit.fileUri);
}
}
/// Offset of the first script tag (`#!...`) in this library or part.
int? _scriptTokenOffset;
@override
void addScriptToken(int charOffset) {
_scriptTokenOffset ??= charOffset;
}
@override
void addImport(
{OffsetMap? offsetMap,
Token? importKeyword,
required List<MetadataBuilder>? metadata,
required bool isAugmentationImport,
required String uri,
required List<Configuration>? configurations,
required String? prefix,
required List<CombinatorBuilder>? combinators,
required bool deferred,
required int charOffset,
required int prefixCharOffset,
required int uriOffset,
required int importIndex}) {
if (configurations != null) {
for (Configuration config in configurations) {
if (loader.getLibrarySupportValue(config.dottedName) ==
config.condition) {
uri = config.importUri;
break;
}
}
}
CompilationUnit? compilationUnit = null;
Uri? resolvedUri;
String? nativePath;
const String nativeExtensionScheme = "dart-ext:";
if (uri.startsWith(nativeExtensionScheme)) {
_problemReporting.addProblem(messageUnsupportedDartExt, charOffset,
noLength, _compilationUnit.fileUri);
String strippedUri = uri.substring(nativeExtensionScheme.length);
if (strippedUri.startsWith("package")) {
// Coverage-ignore-block(suite): Not run.
resolvedUri = _resolve(_compilationUnit.importUri, strippedUri,
uriOffset + nativeExtensionScheme.length);
resolvedUri = loader.target.translateUri(resolvedUri);
nativePath = resolvedUri.toString();
} else {
resolvedUri = new Uri(scheme: "dart-ext", pathSegments: [uri]);
nativePath = uri;
}
} else {
resolvedUri = _resolve(_compilationUnit.importUri, uri, uriOffset);
compilationUnit = loader.read(resolvedUri, uriOffset,
origin: isAugmentationImport ? _augmentationRoot : null,
accessor: _compilationUnit,
isAugmentation: isAugmentationImport,
referencesFromIndex: isAugmentationImport ? indexedLibrary : null);
}
Import import = new Import(
_parent,
compilationUnit,
isAugmentationImport,
deferred,
prefix,
combinators,
configurations,
charOffset,
prefixCharOffset,
importIndex,
nativeImportPath: nativePath);
imports.add(import);
offsetMap?.registerImport(importKeyword!, import);
}
@override
void addExport(
OffsetMap offsetMap,
Token exportKeyword,
List<MetadataBuilder>? metadata,
String uri,
List<Configuration>? configurations,
List<CombinatorBuilder>? combinators,
int charOffset,
int uriOffset) {
if (configurations != null) {
// Coverage-ignore-block(suite): Not run.
for (Configuration config in configurations) {
if (loader.getLibrarySupportValue(config.dottedName) ==
config.condition) {
uri = config.importUri;
break;
}
}
}
CompilationUnit exportedLibrary = loader.read(
_resolve(_compilationUnit.importUri, uri, uriOffset), charOffset,
accessor: _compilationUnit);
exportedLibrary.addExporter(_compilationUnit, combinators, charOffset);
Export export =
new Export(_compilationUnit, exportedLibrary, combinators, charOffset);
exports.add(export);
offsetMap.registerExport(exportKeyword, export);
}
@override
void addClass(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier identifier,
List<NominalVariableBuilder>? typeVariables,
TypeBuilder? supertype,
MixinApplicationBuilder? mixins,
List<TypeBuilder>? interfaces,
int startOffset,
int nameOffset,
int endOffset,
int supertypeOffset,
{required bool isMacro,
required bool isSealed,
required bool isBase,
required bool isInterface,
required bool isFinal,
required bool isAugmentation,
required bool isMixinClass}) {
_addClass(
offsetMap,
metadata,
modifiers,
identifier,
typeVariables,
supertype,
mixins,
interfaces,
startOffset,
nameOffset,
endOffset,
supertypeOffset,
isMacro: isMacro,
isSealed: isSealed,
isBase: isBase,
isInterface: isInterface,
isFinal: isFinal,
isAugmentation: isAugmentation,
isMixinDeclaration: false,
isMixinClass: isMixinClass);
}
@override
void addEnum(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
Identifier identifier,
List<NominalVariableBuilder>? typeVariables,
MixinApplicationBuilder? supertypeBuilder,
List<TypeBuilder>? interfaceBuilders,
List<EnumConstantInfo?>? enumConstantInfos,
int startCharOffset,
int charEndOffset) {
String name = identifier.name;
int charOffset = identifier.nameOffset;
IndexedClass? referencesFromIndexedClass;
if (indexedLibrary != null) {
referencesFromIndexedClass = indexedLibrary!.lookupIndexedClass(name);
}
// Nested declaration began in `OutlineBuilder.beginEnum`.
endEnumDeclaration(name);
DeclarationFragment declarationFragment = _declarationFragments.pop();
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeVariables(_problemReporting, typeVariables,
ownerName: name, allowNameConflict: false);
LookupScope typeParameterScope = declarationFragment.typeParameterScope;
DeclarationNameSpaceBuilder nameSpaceBuilder = declarationFragment
.toDeclarationNameSpaceBuilder(nominalParameterNameSpace);
SourceEnumBuilder enumBuilder = new SourceEnumBuilder(
metadata,
name,
typeVariables,
loader.target.underscoreEnumType,
_applyMixins(
loader.target.underscoreEnumType,
supertypeBuilder,
startCharOffset,
charOffset,
charEndOffset,
name,
/* isMixinDeclaration = */
false,
typeVariables: typeVariables,
isMacro: false,
isSealed: false,
isBase: false,
isInterface: false,
isFinal: false,
isAugmentation: false,
isMixinClass: false),
interfaceBuilders,
enumConstantInfos,
_parent,
new List<ConstructorReferenceBuilder>.of(_constructorReferences),
startCharOffset,
charOffset,
charEndOffset,
referencesFromIndexedClass,
typeParameterScope,
nameSpaceBuilder);
declarationFragment.bodyScope.declarationBuilder = enumBuilder;
_constructorReferences.clear();
_addBuilderInternal(name, enumBuilder, charOffset,
getterReference: referencesFromIndexedClass?.cls.reference);
offsetMap.registerNamedDeclaration(identifier, enumBuilder);
}
@override
void addMixinDeclaration(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
Identifier identifier,
List<NominalVariableBuilder>? typeVariables,
List<TypeBuilder>? supertypeConstraints,
List<TypeBuilder>? interfaces,
int startOffset,
int nameOffset,
int endOffset,
int supertypeOffset,
{required bool isBase,
required bool isAugmentation}) {
TypeBuilder? supertype;
MixinApplicationBuilder? mixinApplication;
if (supertypeConstraints != null && supertypeConstraints.isNotEmpty) {
supertype = supertypeConstraints.first;
if (supertypeConstraints.length > 1) {
mixinApplication = new MixinApplicationBuilder(
supertypeConstraints.skip(1).toList(),
supertype.fileUri!,
supertype.charOffset!);
}
}
_addClass(
offsetMap,
metadata,
0,
identifier,
typeVariables,
supertype,
mixinApplication,
interfaces,
startOffset,
nameOffset,
endOffset,
supertypeOffset,
isMacro: false,
isSealed: false,
isBase: isBase,
isInterface: false,
isFinal: false,
isAugmentation: isAugmentation,
isMixinDeclaration: true,
isMixinClass: false);
}
void _addClass(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier identifier,
List<NominalVariableBuilder>? typeVariables,
TypeBuilder? supertype,
MixinApplicationBuilder? mixins,
List<TypeBuilder>? interfaces,
int startOffset,
int nameOffset,
int endOffset,
int supertypeOffset,
{required bool isMacro,
required bool isSealed,
required bool isBase,
required bool isInterface,
required bool isFinal,
required bool isAugmentation,
required bool isMixinDeclaration,
required bool isMixinClass}) {
String className = identifier.name;
// Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
if (isMixinDeclaration) {
endMixinDeclaration(className);
} else {
endClassDeclaration(className);
}
DeclarationFragment declarationFragment = _declarationFragments.pop();
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeVariables(_problemReporting, typeVariables,
ownerName: className, allowNameConflict: false);
LookupScope typeParameterScope = declarationFragment.typeParameterScope;
DeclarationNameSpaceBuilder nameSpaceBuilder = declarationFragment
.toDeclarationNameSpaceBuilder(nominalParameterNameSpace);
if (isMixinDeclaration) {
modifiers = abstractMask;
}
if (declarationFragment.declaresConstConstructor) {
modifiers |= declaresConstConstructorMask;
}
SourceClassBuilder classBuilder = new SourceClassBuilder(
metadata,
modifiers,
className,
typeVariables,
_applyMixins(supertype, mixins, startOffset, nameOffset, endOffset,
className, isMixinDeclaration,
typeVariables: typeVariables,
isMacro: false,
isSealed: false,
isBase: false,
isInterface: false,
isFinal: false,
// TODO(johnniwinther): How can we support class with mixins?
isAugmentation: false,
isMixinClass: false),
interfaces,
// TODO(johnniwinther): Add the `on` clause types of a mixin declaration
// here.
null,
typeParameterScope,
nameSpaceBuilder,
_parent,
new List<ConstructorReferenceBuilder>.of(_constructorReferences),
startOffset,
nameOffset,
endOffset,
_indexedContainer as IndexedClass?,
isMixinDeclaration: isMixinDeclaration,
isMacro: isMacro,
isSealed: isSealed,
isBase: isBase,
isInterface: isInterface,
isFinal: isFinal,
isAugmentation: isAugmentation,
isMixinClass: isMixinClass);
declarationFragment.bodyScope.declarationBuilder = classBuilder;
_constructorReferences.clear();
_addBuilderInternal(className, classBuilder, nameOffset,
getterReference: _indexedContainer?.reference);
offsetMap.registerNamedDeclaration(identifier, classBuilder);
}
@override
MixinApplicationBuilder addMixinApplication(
List<TypeBuilder> mixins, int charOffset) {
return new MixinApplicationBuilder(
mixins, _compilationUnit.fileUri, charOffset);
}
@override
void addNamedMixinApplication(
List<MetadataBuilder>? metadata,
String name,
List<NominalVariableBuilder>? typeVariables,
int modifiers,
TypeBuilder? supertype,
MixinApplicationBuilder mixinApplication,
List<TypeBuilder>? interfaces,
int startCharOffset,
int charOffset,
int charEndOffset,
{required bool isMacro,
required bool isSealed,
required bool isBase,
required bool isInterface,
required bool isFinal,
required bool isAugmentation,
required bool isMixinClass}) {
// Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
endNamedMixinApplication(name);
supertype = _applyMixins(supertype, mixinApplication, startCharOffset,
charOffset, charEndOffset, name, false,
metadata: metadata,
name: name,
typeVariables: typeVariables,
modifiers: modifiers,
interfaces: interfaces,
isMacro: isMacro,
isSealed: isSealed,
isBase: isBase,
isInterface: isInterface,
isFinal: isFinal,
isAugmentation: isAugmentation,
isMixinClass: isMixinClass)!;
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: supertype.declaration!.name, allowNameConflict: false);
}
TypeBuilder? _applyMixins(
TypeBuilder? supertype,
MixinApplicationBuilder? mixinApplications,
int startCharOffset,
int charOffset,
int charEndOffset,
String subclassName,
bool isMixinDeclaration,
{List<MetadataBuilder>? metadata,
String? name,
List<NominalVariableBuilder>? typeVariables,
int modifiers = 0,
List<TypeBuilder>? interfaces,
required bool isMacro,
required bool isSealed,
required bool isBase,
required bool isInterface,
required bool isFinal,
required bool isAugmentation,
required bool isMixinClass}) {
if (name == null) {
// The following parameters should only be used when building a named
// mixin application.
if (metadata != null) {
unhandled("metadata", "unnamed mixin application", charOffset,
_compilationUnit.fileUri);
} else if (interfaces != null) {
unhandled("interfaces", "unnamed mixin application", charOffset,
_compilationUnit.fileUri);
}
}
if (mixinApplications != null) {
// Documentation below assumes the given mixin application is in one of
// these forms:
//
// class C extends S with M1, M2, M3;
// class Named = S with M1, M2, M3;
//
// When we refer to the subclass, we mean `C` or `Named`.
/// The current supertype.
///
/// Starts out having the value `S` and on each iteration of the loop
/// below, it will take on the value corresponding to:
///
/// 1. `S with M1`.
/// 2. `(S with M1) with M2`.
/// 3. `((S with M1) with M2) with M3`.
supertype ??= loader.target.objectType;
/// The variable part of the mixin application's synthetic name. It
/// starts out as the name of the superclass, but is only used after it
/// has been combined with the name of the current mixin. In the examples
/// from above, it will take these values:
///
/// 1. `S&M1`
/// 2. `S&M1&M2`
/// 3. `S&M1&M2&M3`.
///
/// The full name of the mixin application is obtained by prepending the
/// name of the subclass (`C` or `Named` in the above examples) to the
/// running name. For the example `C`, that leads to these full names:
///
/// 1. `_C&S&M1`
/// 2. `_C&S&M1&M2`
/// 3. `_C&S&M1&M2&M3`.
///
/// For a named mixin application, the last name has been given by the
/// programmer, so for the example `Named` we see these full names:
///
/// 1. `_Named&S&M1`
/// 2. `_Named&S&M1&M2`
/// 3. `Named`.
String runningName;
if (supertype.typeName == null) {
assert(supertype is FunctionTypeBuilder);
// Function types don't have names, and we can supply any string that
// doesn't have to be unique. The actual supertype of the mixin will
// not be built in that case.
runningName = "";
} else {
runningName = supertype.typeName!.name;
}
/// True when we're building a named mixin application. Notice that for
/// the `Named` example above, this is only true on the last
/// iteration because only the full mixin application is named.
bool isNamedMixinApplication;
/// The names of the type variables of the subclass.
Set<String>? typeVariableNames;
if (typeVariables != null) {
typeVariableNames = new Set<String>();
for (NominalVariableBuilder typeVariable in typeVariables) {
typeVariableNames.add(typeVariable.name);
}
}
/// Iterate over the mixins from left to right. At the end of each
/// iteration, a new [supertype] is computed that is the mixin
/// application of [supertype] with the current mixin.
for (int i = 0; i < mixinApplications.mixins.length; i++) {
TypeBuilder mixin = mixinApplications.mixins[i];
isNamedMixinApplication =
name != null && mixin == mixinApplications.mixins.last;
bool isGeneric = false;
if (!isNamedMixinApplication) {
if (typeVariableNames != null) {
if (supertype != null) {
isGeneric =
isGeneric || supertype.usesTypeVariables(typeVariableNames);
}
isGeneric = isGeneric || mixin.usesTypeVariables(typeVariableNames);
}
TypeName? typeName = mixin.typeName;
if (typeName != null) {
runningName += "&${typeName.name}";
}
}
String fullname =
isNamedMixinApplication ? name : "_$subclassName&$runningName";
List<NominalVariableBuilder>? applicationTypeVariables;
List<TypeBuilder>? applicationTypeArguments;
if (isNamedMixinApplication) {
// If this is a named mixin application, it must be given all the
// declared type variables.
applicationTypeVariables = typeVariables;
} else {
// Otherwise, we pass the fresh type variables to the mixin
// application in the same order as they're declared on the subclass.
if (isGeneric) {
beginUnnamedMixinApplication();
NominalVariableCopy nominalVariableCopy = copyTypeVariables(
typeVariables,
kind: TypeVariableKind.extensionSynthesized,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed)!;
applicationTypeVariables = nominalVariableCopy.newVariableBuilders;
Map<NominalVariableBuilder, NominalVariableBuilder>
newToOldVariableMap = nominalVariableCopy.newToOldVariableMap;
Map<NominalVariableBuilder, TypeBuilder> substitutionMap =
nominalVariableCopy.substitutionMap;
endUnnamedMixinApplication();
applicationTypeArguments = [];
for (NominalVariableBuilder typeVariable in typeVariables!) {
TypeBuilder applicationTypeArgument =
new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
// The type variable types passed as arguments to the
// generic class representing the anonymous mixin
// application should refer back to the type variables of
// the class that extend the anonymous mixin application.
typeVariable,
const NullabilityBuilder.omitted(),
fileUri: _compilationUnit.fileUri,
charOffset: charOffset,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
applicationTypeArguments.add(applicationTypeArgument);
}
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, applicationTypeVariables,
ownerName: fullname, allowNameConflict: true);
if (supertype != null) {
supertype = new SynthesizedTypeBuilder(
supertype, newToOldVariableMap, substitutionMap);
}
mixin = new SynthesizedTypeBuilder(
mixin, newToOldVariableMap, substitutionMap);
}
}
final int computedStartCharOffset =
!isNamedMixinApplication || metadata == null
? startCharOffset
: metadata.first.charOffset;
IndexedClass? referencesFromIndexedClass;
if (indexedLibrary != null) {
referencesFromIndexedClass =
indexedLibrary!.lookupIndexedClass(fullname);
}
LookupScope typeParameterScope =
TypeParameterScope.fromList(_scope, typeVariables);
DeclarationNameSpaceBuilder nameSpaceBuilder =
new DeclarationNameSpaceBuilder.empty();
SourceClassBuilder application = new SourceClassBuilder(
isNamedMixinApplication ? metadata : null,
isNamedMixinApplication
? modifiers | namedMixinApplicationMask
: abstractMask,
fullname,
applicationTypeVariables,
isMixinDeclaration ? null : supertype,
isNamedMixinApplication
? interfaces
: isMixinDeclaration
? [supertype!, mixin]
: null,
null,
// No `on` clause types.
typeParameterScope,
nameSpaceBuilder,
_parent,
<ConstructorReferenceBuilder>[],
computedStartCharOffset,
charOffset,
charEndOffset,
referencesFromIndexedClass,
mixedInTypeBuilder: isMixinDeclaration ? null : mixin,
isMacro: isNamedMixinApplication && isMacro,
isSealed: isNamedMixinApplication && isSealed,
isBase: isNamedMixinApplication && isBase,
isInterface: isNamedMixinApplication && isInterface,
isFinal: isNamedMixinApplication && isFinal,
isAugmentation: isNamedMixinApplication && isAugmentation,
isMixinClass: isNamedMixinApplication && isMixinClass);
// TODO(ahe, kmillikin): Should always be true?
// pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
// handle that :(
application.cls.isAnonymousMixin = !isNamedMixinApplication;
_addBuilderInternal(fullname, application, charOffset,
getterReference: referencesFromIndexedClass?.cls.reference);
supertype = new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
application, const NullabilityBuilder.omitted(),
arguments: applicationTypeArguments,
fileUri: _compilationUnit.fileUri,
charOffset: charOffset,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
_registerMixinApplication(application, mixin);
}
return supertype;
} else {
return supertype;
}
}
/// Registers that [mixinApplication] is a mixin application introduced by
/// the [mixedInType] in a with-clause.
///
/// This is used to check that super access in mixin declarations have a
/// concrete target.
void _registerMixinApplication(
SourceClassBuilder mixinApplication, TypeBuilder mixedInType) {
assert(
_mixinApplications != null, "Late registration of mixin application.");
_mixinApplications![mixinApplication] = mixedInType;
}
@override
void addExtensionDeclaration(
OffsetMap offsetMap,
Token beginToken,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier? identifier,
List<NominalVariableBuilder>? typeVariables,
TypeBuilder type,
int startOffset,
int nameOffset,
int endOffset) {
String? name = identifier?.name;
// Nested declaration began in
// `OutlineBuilder.beginExtensionDeclarationPrelude`.
endExtensionDeclaration(name);
ExtensionFragment declarationFragment =
_declarationFragments.pop() as ExtensionFragment;
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeVariables(_problemReporting, typeVariables,
ownerName: name, allowNameConflict: false);
LookupScope typeParameterScope = declarationFragment.typeParameterScope;
DeclarationNameSpaceBuilder nameSpaceBuilder = declarationFragment
.toDeclarationNameSpaceBuilder(nominalParameterNameSpace);
Extension? referenceFrom;
ExtensionName extensionName = declarationFragment.extensionName;
if (name != null) {
referenceFrom = indexedLibrary?.lookupExtension(name);
}
ExtensionBuilder extensionBuilder = new SourceExtensionBuilder(
metadata,
modifiers,
extensionName,
typeVariables,
type,
typeParameterScope,
nameSpaceBuilder,
_parent,
startOffset,
nameOffset,
endOffset,
referenceFrom);
declarationFragment.bodyScope.declarationBuilder = extensionBuilder;
_constructorReferences.clear();
_addBuilderInternal(extensionBuilder.name, extensionBuilder, nameOffset,
getterReference: referenceFrom?.reference);
if (identifier != null) {
offsetMap.registerNamedDeclaration(identifier, extensionBuilder);
} else {
offsetMap.registerUnnamedDeclaration(beginToken, extensionBuilder);
}
}
@override
void addExtensionTypeDeclaration(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier identifier,
List<NominalVariableBuilder>? typeVariables,
List<TypeBuilder>? interfaces,
int startOffset,
int endOffset) {
String name = identifier.name;
// Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
endExtensionTypeDeclaration(name);
DeclarationFragment declarationFragment = _declarationFragments.pop();
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeVariables(_problemReporting, typeVariables,
ownerName: name, allowNameConflict: false);
LookupScope typeParameterScope = declarationFragment.typeParameterScope;
DeclarationNameSpaceBuilder nameSpaceBuilder = declarationFragment
.toDeclarationNameSpaceBuilder(nominalParameterNameSpace);
IndexedContainer? indexedContainer =
indexedLibrary?.lookupIndexedExtensionTypeDeclaration(name);
List<SourceFieldBuilder>? primaryConstructorFields =
declarationFragment.primaryConstructorFields;
SourceFieldBuilder? representationFieldBuilder;
if (primaryConstructorFields != null &&
primaryConstructorFields.isNotEmpty) {
representationFieldBuilder = primaryConstructorFields.first;
}
ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
new SourceExtensionTypeDeclarationBuilder(
metadata,
modifiers,
declarationFragment.name,
typeVariables,
interfaces,
typeParameterScope,
nameSpaceBuilder,
_parent,
new List<ConstructorReferenceBuilder>.of(_constructorReferences),
startOffset,
identifier.nameOffset,
endOffset,
indexedContainer,
representationFieldBuilder);
declarationFragment.bodyScope.declarationBuilder =
extensionTypeDeclarationBuilder;
_constructorReferences.clear();
_addBuilderInternal(extensionTypeDeclarationBuilder.name,
extensionTypeDeclarationBuilder, identifier.nameOffset,
getterReference: indexedContainer?.reference);
offsetMap.registerNamedDeclaration(
identifier, extensionTypeDeclarationBuilder);
}
@override
void addFunctionTypeAlias(
List<MetadataBuilder>? metadata,
String name,
List<NominalVariableBuilder>? typeVariables,
TypeBuilder type,
int charOffset) {
if (typeVariables != null) {
for (NominalVariableBuilder typeVariable in typeVariables) {
typeVariable.varianceCalculationValue =
VarianceCalculationValue.pending;
}
}
Typedef? referenceFrom = indexedLibrary?.lookupTypedef(name);
TypeAliasBuilder typedefBuilder = new SourceTypeAliasBuilder(
metadata, name, typeVariables, type, _parent, charOffset,
referenceFrom: referenceFrom);
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: name, allowNameConflict: true);
// Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
endTypedef();
_addBuilderInternal(name, typedefBuilder, charOffset,
getterReference: referenceFrom?.reference);
}
@override
void addClassMethod(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Identifier identifier,
required String name,
required TypeBuilder? returnType,
required List<FormalParameterBuilder>? formals,
required List<NominalVariableBuilder>? typeVariables,
required Token? beginInitializers,
required int startCharOffset,
required int endCharOffset,
required int charOffset,
required int formalsOffset,
required int modifiers,
required bool inConstructor,
required bool isStatic,
required bool isConstructor,
required bool forAbstractClassOrMixin,
required bool isExtensionMember,
required bool isExtensionTypeMember,
required AsyncMarker asyncModifier,
required String? nativeMethodName,
required ProcedureKind? kind}) {
DeclarationFragment declarationFragment = _declarationFragments.current;
// TODO(johnniwinther): Avoid discrepancy between [inConstructor] and
// [isConstructor]. The former is based on the enclosing declaration name
// and get/set keyword. The latter also takes initializers into account.
if (inConstructor) {
endConstructor();
} else if (isStatic) {
endStaticMethod();
} else {
endInstanceMethod();
}
if (isConstructor) {
switch (declarationFragment) {
case ExtensionFragment():
case ExtensionTypeFragment():
NominalVariableCopy? nominalVariableCopy = copyTypeVariables(
declarationFragment.typeParameters,
kind: TypeVariableKind.extensionSynthesized,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
if (nominalVariableCopy != null) {
if (typeVariables != null) {
// Coverage-ignore-block(suite): Not run.
typeVariables = nominalVariableCopy.newVariableBuilders
..addAll(typeVariables);
} else {
typeVariables = nominalVariableCopy.newVariableBuilders;
}
}
case ClassFragment():
case MixinFragment():
case EnumFragment():
}
} else if (!isStatic) {
switch (declarationFragment) {
case ExtensionFragment():
NominalVariableCopy? nominalVariableCopy = copyTypeVariables(
declarationFragment.typeParameters,
kind: TypeVariableKind.extensionSynthesized,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
if (nominalVariableCopy != null) {
if (typeVariables != null) {
typeVariables = nominalVariableCopy.newVariableBuilders
..addAll(typeVariables);
} else {
typeVariables = nominalVariableCopy.newVariableBuilders;
}
}
TypeBuilder thisType = declarationFragment.extensionThisType;
if (nominalVariableCopy != null) {
thisType = new SynthesizedTypeBuilder(
thisType,
nominalVariableCopy.newToOldVariableMap,
nominalVariableCopy.substitutionMap);
}
List<FormalParameterBuilder> synthesizedFormals = [
new FormalParameterBuilder(FormalParameterKind.requiredPositional,
finalMask, thisType, syntheticThisName, null, charOffset,
fileUri: _compilationUnit.fileUri,
isExtensionThis: true,
hasImmediatelyDeclaredInitializer: false)
];
if (formals != null) {
synthesizedFormals.addAll(formals);
}
formals = synthesizedFormals;
case ExtensionTypeFragment():
NominalVariableCopy? nominalVariableCopy = copyTypeVariables(
declarationFragment.typeParameters,
kind: TypeVariableKind.extensionSynthesized,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
if (nominalVariableCopy != null) {
if (typeVariables != null) {
typeVariables = nominalVariableCopy.newVariableBuilders
..addAll(typeVariables);
} else {
typeVariables = nominalVariableCopy.newVariableBuilders;
}
}
TypeBuilder thisType = addNamedType(
new SyntheticTypeName(declarationFragment.name, charOffset),
const NullabilityBuilder.omitted(),
declarationFragment.typeParameters != null
? new List<TypeBuilder>.generate(
declarationFragment.typeParameters!.length,
(int index) =>
new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
typeVariables![index],
const NullabilityBuilder.omitted(),
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed))
: null,
charOffset,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed);
if (nominalVariableCopy != null) {
thisType = new SynthesizedTypeBuilder(
thisType,
nominalVariableCopy.newToOldVariableMap,
nominalVariableCopy.substitutionMap);
}
List<FormalParameterBuilder> synthesizedFormals = [
new FormalParameterBuilder(FormalParameterKind.requiredPositional,
finalMask, thisType, syntheticThisName, null, charOffset,
fileUri: _compilationUnit.fileUri,
isExtensionThis: true,
hasImmediatelyDeclaredInitializer: false)
];
if (formals != null) {
synthesizedFormals.addAll(formals);
}
formals = synthesizedFormals;
case ClassFragment():
case MixinFragment():
case EnumFragment():
}
}
if (isConstructor) {
String constructorName =
computeAndValidateConstructorName(declarationFragment, identifier) ??
name;
addConstructor(
offsetMap,
metadata,
modifiers,
identifier,
constructorName,
typeVariables,
formals,
startCharOffset,
charOffset,
formalsOffset,
endCharOffset,
nativeMethodName,
beginInitializers: beginInitializers,
forAbstractClassOrMixin: forAbstractClassOrMixin);
} else {
addProcedure(
offsetMap,
metadata,
modifiers,
returnType,
identifier,
name,
typeVariables,
formals,
kind!,
startCharOffset,
charOffset,
formalsOffset,
endCharOffset,
nativeMethodName,
asyncModifier,
isInstanceMember: !isStatic,
isExtensionMember: isExtensionMember,
isExtensionTypeMember: isExtensionTypeMember);
}
}
@override
void addConstructor(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier identifier,
String constructorName,
List<NominalVariableBuilder>? typeVariables,
List<FormalParameterBuilder>? formals,
int startCharOffset,
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String? nativeMethodName,
{Token? beginInitializers,
required bool forAbstractClassOrMixin}) {
SourceFunctionBuilder builder = _addConstructor(
metadata,
modifiers,
constructorName,
typeVariables,
formals,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
nativeMethodName,
beginInitializers: beginInitializers,
forAbstractClassOrMixin: forAbstractClassOrMixin);
offsetMap.registerConstructor(identifier, builder);
}
@override
void addPrimaryConstructor(
{required OffsetMap offsetMap,
required Token beginToken,
required String constructorName,
required List<FormalParameterBuilder>? formals,
required int charOffset,
required bool isConst}) {
beginConstructor();
endConstructor();
NominalVariableCopy? nominalVariableCopy = copyTypeVariables(
_declarationFragments.current.typeParameters,
kind: TypeVariableKind.extensionSynthesized,
instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed);
List<NominalVariableBuilder>? typeVariables =
nominalVariableCopy?.newVariableBuilders;
SourceFunctionBuilder builder = _addConstructor(
null,
isConst ? constMask : 0,
constructorName,
typeVariables,
formals,
/* startCharOffset = */
charOffset,
charOffset,
/* charOpenParenOffset = */
charOffset,
/* charEndOffset = */
charOffset,
/* nativeMethodName = */
null,
forAbstractClassOrMixin: false);
offsetMap.registerPrimaryConstructor(beginToken, builder);
}
@override
void addPrimaryConstructorField(
{required List<MetadataBuilder>? metadata,
required TypeBuilder type,
required String name,
required int charOffset}) {
_declarationFragments.current.addPrimaryConstructorField(_addField(
metadata,
finalMask,
/* isTopLevel = */
false,
type,
name,
/* charOffset = */
charOffset,
/* charEndOffset = */
charOffset,
/* initializerToken = */
null,
/* hasInitializer = */
false));
}
SourceFunctionBuilder _addConstructor(
List<MetadataBuilder>? metadata,
int modifiers,
String constructorName,
List<NominalVariableBuilder>? typeVariables,
List<FormalParameterBuilder>? formals,
int startCharOffset,
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String? nativeMethodName,
{Token? beginInitializers,
required bool forAbstractClassOrMixin}) {
ContainerType containerType = _declarationFragments.current.containerType;
ContainerName? containerName = _declarationFragments.current.containerName;
NameScheme nameScheme = new NameScheme(
isInstanceMember: false,
containerName: containerName,
containerType: containerType,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary!.library.reference)
: libraryName);
Reference? constructorReference;
Reference? tearOffReference;
IndexedContainer? indexedContainer = _indexedContainer;
if (indexedContainer != null) {
constructorReference = indexedContainer.lookupConstructorReference(
nameScheme
.getConstructorMemberName(constructorName, isTearOff: false)
.name);
tearOffReference = indexedContainer.lookupGetterReference(nameScheme
.getConstructorMemberName(constructorName, isTearOff: true)
.name);
}
AbstractSourceConstructorBuilder constructorBuilder;
if (_declarationFragments.current.kind ==
DeclarationFragmentKind.extensionTypeDeclaration) {
constructorBuilder = new SourceExtensionTypeConstructorBuilder(
metadata,
modifiers & ~abstractMask,
addInferableType(),
constructorName,
typeVariables,
formals,
_parent,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
constructorReference,
tearOffReference,
nameScheme,
nativeMethodName: nativeMethodName,
forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
} else {
constructorBuilder = new DeclaredSourceConstructorBuilder(
metadata,
modifiers & ~abstractMask,
addInferableType(),
constructorName,
typeVariables,
formals,
_parent,
_compilationUnit.fileUri,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
constructorReference,
tearOffReference,
nameScheme,
nativeMethodName: nativeMethodName,
forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
}
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: constructorBuilder.name, allowNameConflict: true);
// TODO(johnniwinther): There is no way to pass the tear off reference here.
_addBuilderInternal(constructorName, constructorBuilder, charOffset,
getterReference: constructorReference);
if (nativeMethodName != null) {
_addNativeMethod(constructorBuilder);
}
if (constructorBuilder.isConst) {
_declarationFragments.current.declaresConstConstructor = true;
}
if (constructorBuilder.isConst ||
libraryFeatures.superParameters.isEnabled) {
// const constructors will have their initializers compiled and written
// into the outline. In case of super-parameters language feature, the
// super initializers are required to infer the types of super parameters.
constructorBuilder.beginInitializers =
beginInitializers ?? new Token.eof(-1);
}
return constructorBuilder;
}
@override
void addFactoryMethod(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
Identifier identifier,
List<FormalParameterBuilder>? formals,
ConstructorReferenceBuilder? redirectionTarget,
int startCharOffset,
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String? nativeMethodName,
AsyncMarker asyncModifier) {
TypeBuilder returnType;
List<TypeBuilder>? returnTypeArguments;
DeclarationFragment enclosingDeclaration = _declarationFragments.current;
if (enclosingDeclaration.kind ==
DeclarationFragmentKind.extensionDeclaration) {
// Make the synthesized return type invalid for extensions.
String name = enclosingDeclaration.name;
returnType = new NamedTypeBuilderImpl.forInvalidType(
name,
const NullabilityBuilder.omitted(),
messageExtensionDeclaresConstructor.withLocation(
_compilationUnit.fileUri, charOffset, name.length));
} else {
returnType = addNamedType(
new SyntheticTypeName(enclosingDeclaration.name, charOffset),
const NullabilityBuilder.omitted(),
returnTypeArguments = [],
charOffset,
instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed);
}
// Prepare the simple procedure name.
String procedureName;
String? constructorName = computeAndValidateConstructorName(
enclosingDeclaration, identifier,
isFactory: true);
if (constructorName != null) {
procedureName = constructorName;
} else {
procedureName = identifier.name;
}
ContainerType containerType = enclosingDeclaration.containerType;
ContainerName containerName = enclosingDeclaration.containerName;
NameScheme procedureNameScheme = new NameScheme(
containerName: containerName,
containerType: containerType,
isInstanceMember: false,
libraryName: indexedLibrary != null
? new LibraryName(
(_indexedContainer ?? // Coverage-ignore(suite): Not run.
indexedLibrary)!
.library
.reference)
: libraryName);
Reference? constructorReference;
Reference? tearOffReference;
if (_indexedContainer != null) {
constructorReference = _indexedContainer!.lookupConstructorReference(
procedureNameScheme
.getConstructorMemberName(procedureName, isTearOff: false)
.name);
tearOffReference = _indexedContainer!.lookupGetterReference(
procedureNameScheme
.getConstructorMemberName(procedureName, isTearOff: true)
.name);
} else if (indexedLibrary != null) {
// Coverage-ignore-block(suite): Not run.
constructorReference = indexedLibrary!.lookupGetterReference(
procedureNameScheme
.getConstructorMemberName(procedureName, isTearOff: false)
.name);
tearOffReference = indexedLibrary!.lookupGetterReference(
procedureNameScheme
.getConstructorMemberName(procedureName, isTearOff: true)
.name);
}
SourceFactoryBuilder procedureBuilder;
List<NominalVariableBuilder>? typeVariables;
if (redirectionTarget != null) {
procedureBuilder = new RedirectingFactoryBuilder(
metadata,
staticMask | modifiers,
returnType,
procedureName,
typeVariables = copyTypeVariables(enclosingDeclaration.typeParameters,
kind: TypeVariableKind.function,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed)
?.newVariableBuilders,
formals,
_parent,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
constructorReference,
tearOffReference,
procedureNameScheme,
nativeMethodName,
redirectionTarget);
(_parent.redirectingFactoryBuilders ??= [])
.add(procedureBuilder as RedirectingFactoryBuilder);
} else {
procedureBuilder = new SourceFactoryBuilder(
metadata,
staticMask | modifiers,
returnType,
procedureName,
typeVariables = copyTypeVariables(enclosingDeclaration.typeParameters,
kind: TypeVariableKind.function,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed)
?.newVariableBuilders,
formals,
_parent,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
constructorReference,
tearOffReference,
asyncModifier,
procedureNameScheme,
nativeMethodName: nativeMethodName);
}
if (returnTypeArguments != null && typeVariables != null) {
for (TypeVariableBuilder typeVariable in typeVariables) {
returnTypeArguments.add(addNamedType(
new SyntheticTypeName(
typeVariable.name, procedureBuilder.charOffset),
const NullabilityBuilder.omitted(),
null,
procedureBuilder.charOffset,
instanceTypeVariableAccess:
InstanceTypeVariableAccessState.Allowed));
}
}
// Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
endFactoryMethod();
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: identifier.name, allowNameConflict: true);
_addBuilderInternal(procedureName, procedureBuilder, charOffset,
getterReference: constructorReference);
if (nativeMethodName != null) {
_addNativeMethod(procedureBuilder);
}
offsetMap.registerConstructor(identifier, procedureBuilder);
}
@override
ConstructorReferenceBuilder addConstructorReference(TypeName name,
List<TypeBuilder>? typeArguments, String? suffix, int charOffset) {
ConstructorReferenceBuilder ref = new ConstructorReferenceBuilder(
name, typeArguments, suffix, _compilationUnit.fileUri, charOffset);
_constructorReferences.add(ref);
return ref;
}
@override
ConstructorReferenceBuilder? addUnnamedConstructorReference(
List<TypeBuilder>? typeArguments, Identifier? suffix, int charOffset) {
// At the moment, the name of the type in a constructor reference can be
// omitted only within an enum element declaration.
DeclarationFragment enclosingDeclaration = _declarationFragments.current;
if (enclosingDeclaration.kind == DeclarationFragmentKind.enumDeclaration) {
if (libraryFeatures.enhancedEnums.isEnabled) {
int constructorNameOffset = suffix?.nameOffset ?? charOffset;
return addConstructorReference(
new SyntheticTypeName(
enclosingDeclaration.name, constructorNameOffset),
typeArguments,
suffix?.name,
constructorNameOffset);
} else {
// Coverage-ignore-block(suite): Not run.
// For entries that consist of their name only, all of the elements
// of the constructor reference should be null.
if (typeArguments != null || suffix != null) {
_compilationUnit.reportFeatureNotEnabled(
libraryFeatures.enhancedEnums,
_compilationUnit.fileUri,
charOffset,
noLength);
}
return null;
}
} else {
internalProblem(
messageInternalProblemOmittedTypeNameInConstructorReference,
charOffset,
_compilationUnit.fileUri);
}
}
@override
String? computeAndValidateConstructorName(
DeclarationFragment enclosingDeclaration, Identifier identifier,
{isFactory = false}) {
String className = enclosingDeclaration.name;
String prefix;
String? suffix;
int charOffset;
if (identifier is QualifiedNameIdentifier) {
Identifier qualifier = identifier.qualifier;
prefix = qualifier.name;
suffix = identifier.name;
charOffset = qualifier.nameOffset;
} else {
prefix = identifier.name;
suffix = null;
charOffset = identifier.nameOffset;
}
if (libraryFeatures.constructorTearoffs.isEnabled) {
suffix = suffix == "new" ? "" : suffix;
}
if (prefix == className) {
return suffix ?? "";
}
if (suffix == null && !isFactory) {
// A legal name for a regular method, but not for a constructor.
return null;
}
_problemReporting.addProblem(messageConstructorWithWrongName, charOffset,
prefix.length, _compilationUnit.fileUri,
context: [
templateConstructorWithWrongNameContext
.withArguments(enclosingDeclaration.name)
.withLocation(
_compilationUnit.importUri,
enclosingDeclaration.nameOffset,
enclosingDeclaration.name.length)
]);
return suffix;
}
void _addNativeMethod(SourceFunctionBuilder method) {
_nativeMethods.add(method);
}
@override
void addProcedure(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
TypeBuilder? returnType,
Identifier identifier,
String name,
List<NominalVariableBuilder>? typeVariables,
List<FormalParameterBuilder>? formals,
ProcedureKind kind,
int startCharOffset,
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String? nativeMethodName,
AsyncMarker asyncModifier,
{required bool isInstanceMember,
required bool isExtensionMember,
required bool isExtensionTypeMember}) {
DeclarationFragment? enclosingDeclaration =
_declarationFragments.currentOrNull;
assert(!isExtensionMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionDeclaration);
assert(!isExtensionTypeMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionTypeDeclaration);
ContainerType containerType =
enclosingDeclaration?.containerType ?? ContainerType.Library;
ContainerName? containerName = enclosingDeclaration?.containerName;
NameScheme nameScheme = new NameScheme(
containerName: containerName,
containerType: containerType,
isInstanceMember: isInstanceMember,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary!.library.reference)
: libraryName);
if (returnType == null) {
if (kind == ProcedureKind.Operator &&
identical(name, indexSetName.text)) {
returnType = addVoidType(charOffset);
} else if (kind == ProcedureKind.Setter) {
returnType = addVoidType(charOffset);
}
}
Reference? procedureReference;
Reference? tearOffReference;
IndexedContainer? indexedContainer = _indexedContainer ?? indexedLibrary;
bool isAugmentation =
_compilationUnit.isAugmenting && (modifiers & augmentMask) != 0;
if (indexedContainer != null && !isAugmentation) {
Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
if (kind == ProcedureKind.Setter) {
if ((isExtensionMember || isExtensionTypeMember) && isInstanceMember) {
// Extension (type) instance setters are encoded as methods.
procedureReference =
indexedContainer.lookupGetterReference(nameToLookup);
} else {
procedureReference =
indexedContainer.lookupSetterReference(nameToLookup);
}
} else {
procedureReference =
indexedContainer.lookupGetterReference(nameToLookup);
if ((isExtensionMember || isExtensionTypeMember) &&
kind == ProcedureKind.Method) {
tearOffReference = indexedContainer.lookupGetterReference(nameScheme
.getProcedureMemberName(ProcedureKind.Getter, name)
.name);
}
}
}
SourceProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
metadata,
modifiers,
returnType ?? addInferableType(),
name,
typeVariables,
formals,
kind,
_parent,
_compilationUnit.fileUri,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
procedureReference,
tearOffReference,
asyncModifier,
nameScheme,
nativeMethodName: nativeMethodName);
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
ownerName: procedureBuilder.name, allowNameConflict: true);
_addBuilderInternal(name, procedureBuilder, charOffset,
getterReference: procedureReference);
if (nativeMethodName != null) {
_addNativeMethod(procedureBuilder);
}
offsetMap.registerProcedure(identifier, procedureBuilder);
}
@override
void addFields(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
int modifiers,
bool isTopLevel,
TypeBuilder? type,
List<FieldInfo> fieldInfos) {
for (FieldInfo info in fieldInfos) {
bool isConst = modifiers & constMask != 0;
bool isFinal = modifiers & finalMask != 0;
bool potentiallyNeedInitializerInOutline = isConst || isFinal;
Token? startToken;
if (potentiallyNeedInitializerInOutline || type == null) {
startToken = info.initializerToken;
}
if (startToken != null) {
// Extract only the tokens for the initializer expression from the
// token stream.
Token endToken = info.beforeLast!;
endToken.setNext(new Token.eof(endToken.next!.offset));
new Token.eof(startToken.previous!.offset).setNext(startToken);
}
bool hasInitializer = info.initializerToken != null;
offsetMap.registerField(
info.identifier,
_addField(
metadata,
modifiers,
isTopLevel,
type ?? addInferableType(),
info.identifier.name,
info.identifier.nameOffset,
info.charEndOffset,
startToken,
hasInitializer,
constInitializerToken:
potentiallyNeedInitializerInOutline ? startToken : null));
}
}
SourceFieldBuilder _addField(
List<MetadataBuilder>? metadata,
int modifiers,
bool isTopLevel,
TypeBuilder type,
String name,
int charOffset,
int charEndOffset,
Token? initializerToken,
bool hasInitializer,
{Token? constInitializerToken}) {
if (hasInitializer) {
modifiers |= hasInitializerMask;
}
bool isLate = (modifiers & lateMask) != 0;
bool isFinal = (modifiers & finalMask) != 0;
bool isStatic = (modifiers & staticMask) != 0;
bool isExternal = (modifiers & externalMask) != 0;
final bool fieldIsLateWithLowering = isLate &&
(loader.target.backendTarget.isLateFieldLoweringEnabled(
hasInitializer: hasInitializer,
isFinal: isFinal,
isStatic: isTopLevel || isStatic) ||
(loader.target.backendTarget.useStaticFieldLowering &&
(isStatic || isTopLevel)));
DeclarationFragment? enclosingDeclaration =
_declarationFragments.currentOrNull;
final bool isInstanceMember = enclosingDeclaration != null && !isStatic;
final bool isExtensionMember = enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionDeclaration;
final bool isExtensionTypeMember = enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionTypeDeclaration;
ContainerType containerType =
enclosingDeclaration?.containerType ?? ContainerType.Library;
ContainerName? containerName = enclosingDeclaration?.containerName;
Reference? fieldReference;
Reference? fieldGetterReference;
Reference? fieldSetterReference;
Reference? lateIsSetFieldReference;
Reference? lateIsSetGetterReference;
Reference? lateIsSetSetterReference;
Reference? lateGetterReference;
Reference? lateSetterReference;
NameScheme nameScheme = new NameScheme(
isInstanceMember: isInstanceMember,
containerName: containerName,
containerType: containerType,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary!.reference)
: libraryName);
IndexedContainer? indexedContainer = _indexedContainer ?? indexedLibrary;
if (indexedContainer != null) {
if ((isExtensionMember || isExtensionTypeMember) &&
isInstanceMember &&
isExternal) {
/// An external extension (type) instance field is special. It is
/// treated as an external getter/setter pair and is therefore encoded
/// as a pair of top level methods using the extension instance member
/// naming convention.
fieldGetterReference = indexedContainer.lookupGetterReference(
nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name);
fieldSetterReference = indexedContainer.lookupGetterReference(
nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name);
} else if (isExtensionTypeMember && isInstanceMember) {
Name nameToLookup = nameScheme
.getFieldMemberName(FieldNameType.RepresentationField, name,
isSynthesized: true)
.name;
fieldGetterReference =
indexedContainer.lookupGetterReference(nameToLookup);
} else {
Name nameToLookup = nameScheme
.getFieldMemberName(FieldNameType.Field, name,
isSynthesized: fieldIsLateWithLowering)
.name;
fieldReference = indexedContainer.lookupFieldReference(nameToLookup);
fieldGetterReference =
indexedContainer.lookupGetterReference(nameToLookup);
fieldSetterReference =
indexedContainer.lookupSetterReference(nameToLookup);
}
if (fieldIsLateWithLowering) {
Name lateIsSetName = nameScheme
.getFieldMemberName(FieldNameType.IsSetField, name,
isSynthesized: fieldIsLateWithLowering)
.name;
lateIsSetFieldReference =
indexedContainer.lookupFieldReference(lateIsSetName);
lateIsSetGetterReference =
indexedContainer.lookupGetterReference(lateIsSetName);
lateIsSetSetterReference =
indexedContainer.lookupSetterReference(lateIsSetName);
lateGetterReference = indexedContainer.lookupGetterReference(nameScheme
.getFieldMemberName(FieldNameType.Getter, name,
isSynthesized: fieldIsLateWithLowering)
.name);
lateSetterReference = indexedContainer.lookupSetterReference(nameScheme
.getFieldMemberName(FieldNameType.Setter, name,
isSynthesized: fieldIsLateWithLowering)
.name);
}
}
SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
metadata,
type,
name,
modifiers,
isTopLevel,
_parent,
_compilationUnit.fileUri,
charOffset,
charEndOffset,
nameScheme,
fieldReference: fieldReference,
fieldGetterReference: fieldGetterReference,
fieldSetterReference: fieldSetterReference,
lateIsSetFieldReference: lateIsSetFieldReference,
lateIsSetGetterReference: lateIsSetGetterReference,
lateIsSetSetterReference: lateIsSetSetterReference,
lateGetterReference: lateGetterReference,
lateSetterReference: lateSetterReference,
initializerToken: initializerToken,
constInitializerToken: constInitializerToken);
_addBuilderInternal(name, fieldBuilder, charOffset,
getterReference: fieldGetterReference,
setterReference: fieldSetterReference);
return fieldBuilder;
}
@override
FormalParameterBuilder addFormalParameter(
List<MetadataBuilder>? metadata,
FormalParameterKind kind,
int modifiers,
TypeBuilder type,
String name,
bool hasThis,
bool hasSuper,
int charOffset,
Token? initializerToken,
{bool lowerWildcard = false}) {
assert(
!hasThis || !hasSuper,
// Coverage-ignore(suite): Not run.
"Formal parameter '${name}' has both 'this' and 'super' prefixes.");
if (hasThis) {
modifiers |= initializingFormalMask;
}
if (hasSuper) {
modifiers |= superInitializingFormalMask;
}
String formalName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && formalName == '_';
if (isWildcard && lowerWildcard) {
formalName = createWildcardFormalParameterName(wildcardVariableIndex);
wildcardVariableIndex++;
}
FormalParameterBuilder formal = new FormalParameterBuilder(
kind, modifiers, type, formalName, _parent, charOffset,
fileUri: _compilationUnit.fileUri,
hasImmediatelyDeclaredInitializer: initializerToken != null,
isWildcard: isWildcard)
..initializerToken = initializerToken;
return formal;
}
@override
TypeBuilder addNamedType(
TypeName typeName,
NullabilityBuilder nullabilityBuilder,
List<TypeBuilder>? arguments,
int charOffset,
{required InstanceTypeVariableAccessState instanceTypeVariableAccess}) {
if (_omittedTypeDeclarationBuilders != null) {
// Coverage-ignore-block(suite): Not run.
Builder? builder = _omittedTypeDeclarationBuilders[typeName.name];
if (builder is OmittedTypeDeclarationBuilder) {
return new DependentTypeBuilder(builder.omittedTypeBuilder);
}
}
return _registerUnresolvedNamedType(new NamedTypeBuilderImpl(
typeName, nullabilityBuilder,
arguments: arguments,
fileUri: _compilationUnit.fileUri,
charOffset: charOffset,
instanceTypeVariableAccess: instanceTypeVariableAccess));
}
NamedTypeBuilder _registerUnresolvedNamedType(NamedTypeBuilder type) {
_typeScopes.current.registerUnresolvedNamedType(type);
return type;
}
@override
FunctionTypeBuilder addFunctionType(
TypeBuilder returnType,
List<StructuralVariableBuilder>? structuralVariableBuilders,
List<FormalParameterBuilder>? formals,
NullabilityBuilder nullabilityBuilder,
Uri fileUri,
int charOffset,
{required bool hasFunctionFormalParameterSyntax}) {
FunctionTypeBuilder builder = new FunctionTypeBuilderImpl(
returnType,
structuralVariableBuilders,
formals,
nullabilityBuilder,
fileUri,
charOffset,
hasFunctionFormalParameterSyntax: hasFunctionFormalParameterSyntax);
_checkStructuralVariables(structuralVariableBuilders);
if (structuralVariableBuilders != null) {
for (StructuralVariableBuilder builder in structuralVariableBuilders) {
if (builder.metadata != null) {
if (!libraryFeatures.genericMetadata.isEnabled) {
_problemReporting.addProblem(
messageAnnotationOnFunctionTypeTypeVariable,
builder.charOffset,
builder.name.length,
builder.fileUri);
}
}
}
}
// Nested declaration began in `OutlineBuilder.beginFunctionType` or
// `OutlineBuilder.beginFunctionTypedFormalParameter`.
endFunctionType();
return builder;
}
void _checkStructuralVariables(
List<StructuralVariableBuilder>? typeVariables) {
Map<String, StructuralVariableBuilder> typeVariablesByName =
_structuralParameterScopes.pop();
if (typeVariables == null || typeVariables.isEmpty) return null;
for (StructuralVariableBuilder tv in typeVariables) {
if (tv.isWildcard) continue;
StructuralVariableBuilder? existing = typeVariablesByName[tv.name];
if (existing != null) {
// Coverage-ignore-block(suite): Not run.
_problemReporting.addProblem(messageTypeVariableDuplicatedName,
tv.charOffset, tv.name.length, _compilationUnit.fileUri,
context: [
templateTypeVariableDuplicatedNameCause
.withArguments(tv.name)
.withLocation(_compilationUnit.fileUri, existing.charOffset,
existing.name.length)
]);
} else {
typeVariablesByName[tv.name] = tv;
}
}
}
@override
TypeBuilder addVoidType(int charOffset) {
// 'void' is always nullable.
return new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
new VoidTypeDeclarationBuilder(const VoidType(), _parent, charOffset),
const NullabilityBuilder.inherent(),
charOffset: charOffset,
fileUri: _compilationUnit.fileUri,
instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected);
}
@override
NominalVariableBuilder addNominalTypeVariable(List<MetadataBuilder>? metadata,
String name, TypeBuilder? bound, int charOffset, Uri fileUri,
{required TypeVariableKind kind}) {
String variableName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && variableName == '_';
if (isWildcard) {
variableName = createWildcardTypeVariableName(wildcardVariableIndex);
wildcardVariableIndex++;
}
NominalVariableBuilder builder = new NominalVariableBuilder(
variableName, _parent, charOffset, fileUri,
bound: bound, metadata: metadata, kind: kind, isWildcard: isWildcard);
_unboundNominalVariables.add(builder);
return builder;
}
@override
StructuralVariableBuilder addStructuralTypeVariable(
List<MetadataBuilder>? metadata,
String name,
TypeBuilder? bound,
int charOffset,
Uri fileUri) {
String variableName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && variableName == '_';
if (isWildcard) {
variableName = createWildcardTypeVariableName(wildcardVariableIndex);
wildcardVariableIndex++;
}
StructuralVariableBuilder builder = new StructuralVariableBuilder(
variableName, _parent, charOffset, fileUri,
bound: bound, metadata: metadata, isWildcard: isWildcard);
_unboundStructuralVariables.add(builder);
return builder;
}
@override
NominalVariableCopy? copyTypeVariables(
List<NominalVariableBuilder>? oldVariableBuilders,
{required TypeVariableKind kind,
required InstanceTypeVariableAccessState instanceTypeVariableAccess}) {
if (oldVariableBuilders == null || oldVariableBuilders.isEmpty) {
return null;
}
List<TypeBuilder> newTypeArguments = [];
Map<NominalVariableBuilder, TypeBuilder> substitutionMap =
new Map.identity();
Map<NominalVariableBuilder, NominalVariableBuilder> newToOldVariableMap =
new Map.identity();
List<NominalVariableBuilder> newVariableBuilders =
<NominalVariableBuilder>[];
for (NominalVariableBuilder oldVariable in oldVariableBuilders) {
NominalVariableBuilder newVariable = new NominalVariableBuilder(
oldVariable.name,
_parent,
oldVariable.charOffset,
oldVariable.fileUri,
kind: kind,
variableVariance: oldVariable.parameter.isLegacyCovariant
? null
:
// Coverage-ignore(suite): Not run.
oldVariable.variance,
isWildcard: oldVariable.isWildcard);
newVariableBuilders.add(newVariable);
newToOldVariableMap[newVariable] = oldVariable;
_unboundNominalVariables.add(newVariable);
}
for (int i = 0; i < newVariableBuilders.length; i++) {
NominalVariableBuilder oldVariableBuilder = oldVariableBuilders[i];
TypeBuilder newTypeArgument =
new NamedTypeBuilderImpl.fromTypeDeclarationBuilder(
newVariableBuilders[i], const NullabilityBuilder.omitted(),
instanceTypeVariableAccess: instanceTypeVariableAccess);
substitutionMap[oldVariableBuilder] = newTypeArgument;
newTypeArguments.add(newTypeArgument);
if (oldVariableBuilder.bound != null) {
newVariableBuilders[i].bound = new SynthesizedTypeBuilder(
oldVariableBuilder.bound!, newToOldVariableMap, substitutionMap);
}
}
return new NominalVariableCopy(newVariableBuilders, newTypeArguments,
substitutionMap, newToOldVariableMap);
}
@override
void addLibraryDirective(
{required String? libraryName,
required List<MetadataBuilder>? metadata,
required bool isAugment}) {
_name = libraryName;
_metadata = metadata;
}
@override
InferableTypeBuilder addInferableType() {
return _compilationUnit.loader.inferableTypes.addInferableType();
}
@override
Builder addBuilder(String name, Builder declaration, int charOffset) {
return _addBuilderToLibrary(name, declaration, charOffset);
}
void _addBuilderInternal(String name, Builder declaration, int charOffset,
{Reference? getterReference, Reference? setterReference}) {
if (getterReference != null) {
loader.buildersCreatedWithReferences[getterReference] = declaration;
}
if (setterReference != null) {
loader.buildersCreatedWithReferences[setterReference] = declaration;
}
_addBuilder(name, declaration, charOffset);
}
void _addBuilder(String name, Builder declaration, int charOffset) {
if (_declarationFragments.isEmpty) {
_addBuilderToLibrary(name, declaration, charOffset);
} else {
_addBuilderToDeclaration(name, declaration, charOffset);
}
}
Builder _addBuilderToLibrary(
String name, Builder declaration, int charOffset) {
assert(_declarationFragments.isEmpty);
return _libraryNameSpaceBuilder.addBuilder(_parent, _problemReporting, name,
declaration, _compilationUnit.fileUri, charOffset);
}
void _addBuilderToDeclaration(
String name, Builder declaration, int charOffset) {
assert(_declarationFragments.hasCurrent);
_declarationFragments.current
.addBuilder(name, declaration, _compilationUnit.fileUri, charOffset);
}
@override
void takeMixinApplications(
Map<SourceClassBuilder, TypeBuilder> mixinApplications) {
assert(_mixinApplications != null,
"Mixin applications have already been processed.");
mixinApplications.addAll(_mixinApplications!);
_mixinApplications = null;
}
@override
void collectUnboundTypeVariables(
SourceLibraryBuilder libraryBuilder,
Map<NominalVariableBuilder, SourceLibraryBuilder> nominalVariables,
Map<StructuralVariableBuilder, SourceLibraryBuilder>
structuralVariables) {
for (NominalVariableBuilder builder in _unboundNominalVariables) {
nominalVariables[builder] = libraryBuilder;
}
for (StructuralVariableBuilder builder in _unboundStructuralVariables) {
structuralVariables[builder] = libraryBuilder;
}
_unboundStructuralVariables.clear();
_unboundNominalVariables.clear();
}
@override
TypeScope get typeScope => _typeScopes.current;
@override
String? get name => _name;
@override
List<MetadataBuilder>? get metadata => _metadata;
@override
Iterable<Builder> get builders => _libraryNameSpaceBuilder.builders;
@override
bool get isPart => _partOfName != null || _partOfUri != null;
@override
String? get partOfName => _partOfName;
@override
Uri? get partOfUri => _partOfUri;
@override
List<Part> get parts => _parts;
@override
List<PrefixBuilder>? get prefixBuilders =>
_libraryNameSpaceBuilder.prefixBuilders;
@override
void registerUnresolvedNamedTypes(List<NamedTypeBuilder> unboundTypes) {
for (NamedTypeBuilder unboundType in unboundTypes) {
// Coverage-ignore-block(suite): Not run.
_registerUnresolvedNamedType(unboundType);
}
}
@override
void registerUnresolvedStructuralVariables(
List<StructuralVariableBuilder> unboundTypeVariables) {
this._unboundStructuralVariables.addAll(unboundTypeVariables);
}
@override
int finishNativeMethods() {
for (SourceFunctionBuilder method in _nativeMethods) {
method.becomeNative(loader);
}
return _nativeMethods.length;
}
@override
List<LibraryPart> get libraryParts => _libraryParts;
}