blob: 322a61cc31f12857174f1a71f41883983bf52a05 [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 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/modifiers.dart' show Modifiers;
import '../base/problems.dart' show internalProblem;
import '../base/scope.dart';
import '../base/uris.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/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/type_builder.dart';
import '../builder/void_type_builder.dart';
import '../fragment/fragment.dart';
import '../util/local_stack.dart';
import 'builder_factory.dart';
import 'offset_map.dart';
import 'source_class_builder.dart' show SourceClassBuilder;
import 'source_library_builder.dart';
import 'source_loader.dart' show SourceLoader;
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 SourceCompilationUnit _augmentationRoot;
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 mixin application classes to their mixin types.
///
/// This is used to check that super access in mixin declarations have a
/// concrete target.
Map<SourceClassBuilder, TypeBuilder>? _mixinApplications = {};
final List<NominalParameterBuilder> _unboundNominalParameters = [];
final List<StructuralParameterBuilder> _unboundStructuralVariables = [];
final List<FactoryFragment> _nativeFactoryFragments = [];
final List<GetterFragment> _nativeGetterFragments = [];
final List<SetterFragment> _nativeSetterFragments = [];
final List<MethodFragment> _nativeMethodFragments = [];
final List<ConstructorFragment> _nativeConstructorFragments = [];
final LookupScope _compilationUnitScope;
/// 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, StructuralParameterBuilder>>
_structuralParameterScopes = new LocalStack([]);
final LocalStack<DeclarationFragment> _declarationFragments =
new LocalStack([]);
BuilderFactoryImpl(
{required SourceCompilationUnit compilationUnit,
required SourceCompilationUnit augmentationRoot,
required LibraryNameSpaceBuilder libraryNameSpaceBuilder,
required ProblemReporting problemReporting,
required LookupScope scope,
required IndexedLibrary? indexedLibrary})
: _compilationUnit = compilationUnit,
_augmentationRoot = augmentationRoot,
_libraryNameSpaceBuilder = libraryNameSpaceBuilder,
_problemReporting = problemReporting,
_compilationUnitScope = scope,
indexedLibrary = indexedLibrary,
_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 nameOffset,
List<NominalParameterBuilder>? typeParameters) {
_declarationFragments.push(new ClassFragment(
name,
_compilationUnit.fileUri,
nameOffset,
typeParameters,
_typeScopes.current.lookupScope,
_nominalParameterNameSpaces.current));
}
@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,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endClassDeclarationForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
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().addTypeParameters(
_problemReporting, typeParameters,
ownerName: null, allowNameConflict: true);
}
@override
void beginMixinDeclaration(String name, int nameOffset,
List<NominalParameterBuilder>? typeParameters) {
_declarationFragments.push(new MixinFragment(
name,
_compilationUnit.fileUri,
nameOffset,
typeParameters,
_typeScopes.current.lookupScope,
_nominalParameterNameSpaces.current));
}
@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,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endMixinDeclarationForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
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().addTypeParameters(
_problemReporting, typeParameters,
ownerName: null, allowNameConflict: true);
}
@override
void beginNamedMixinApplication(String name, int charOffset,
List<NominalParameterBuilder>? typeParameters) {}
@override
void endNamedMixinApplication(String name) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
void endNamedMixinApplicationForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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 nameOffset,
List<NominalParameterBuilder>? typeParameters) {
_declarationFragments.push(new EnumFragment(
name,
_compilationUnit.fileUri,
nameOffset,
typeParameters,
_typeScopes.current.lookupScope,
_nominalParameterNameSpaces.current));
}
@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,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
void endEnumDeclarationForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope bodyScope = _typeScopes.pop();
assert(bodyScope.kind == TypeScopeKind.enumDeclaration,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_declarationFragments.pop();
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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<NominalParameterBuilder>? typeParameters) {
_declarationFragments.push(new ExtensionFragment(
name,
_compilationUnit.fileUri,
charOffset,
typeParameters,
_typeScopes.current.lookupScope,
_nominalParameterNameSpaces.current));
}
@override
void beginExtensionBody() {
ExtensionFragment declarationFragment =
_declarationFragments.current as ExtensionFragment;
_typeScopes.push(new TypeScope(TypeScopeKind.extensionDeclaration,
declarationFragment.bodyScope, _typeScopes.current));
}
@override
void endExtensionDeclaration(String? name) {
TypeScope bodyScope = _typeScopes.pop();
assert(bodyScope.kind == TypeScopeKind.extensionDeclaration,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
void beginExtensionTypeDeclaration(String name, int nameOffset,
List<NominalParameterBuilder>? typeParameters) {
_declarationFragments.push(new ExtensionTypeFragment(
name,
_compilationUnit.fileUri,
nameOffset,
typeParameters,
_typeScopes.current.lookupScope,
_nominalParameterNameSpaces.current));
}
@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,
"Unexpected type scope: $bodyScope.");
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"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
// Coverage-ignore(suite): Not run.
void endFactoryMethodForParserRecovery() {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(_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 endConstructorForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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
// Coverage-ignore(suite): Not run.
void endStaticMethodForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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 endInstanceMethodForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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 endTopLevelMethodForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
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 typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
// Coverage-ignore(suite): Not run.
void endTypedefForParserRecovery(
List<NominalParameterBuilder>? typeParameters) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.declarationTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
ownerName: null, allowNameConflict: true);
}
@override
void beginFunctionType() {
Map<String, StructuralParameterBuilder> structuralParameterScope = {};
_structuralParameterScopes.push(structuralParameterScope);
_typeScopes.push(new TypeScope(
TypeScopeKind.functionTypeParameters,
new TypeParameterScope(
_typeScopes.current.lookupScope, structuralParameterScope),
_typeScopes.current));
}
@override
void endFunctionType() {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.functionTypeParameters,
"Unexpected type scope: $typeParameterScope.");
}
@override
void checkStacks() {
assert(
_typeScopes.isSingular,
"Unexpected type scope stack: "
"$_typeScopes.");
assert(
_declarationFragments.isEmpty,
"Unexpected declaration fragment stack: "
"$_declarationFragments.");
assert(
_nominalParameterNameSpaces.isEmpty,
"Unexpected nominal parameter name space stack : "
"$_nominalParameterNameSpaces.");
assert(
_structuralParameterScopes.isEmpty,
"Unexpected structural parameter scope stack : "
"$_structuralParameterScopes.");
}
@override
// Coverage-ignore(suite): Not run.
void registerUnboundStructuralParameters(
List<StructuralParameterBuilder> 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);
CompilationUnit compilationUnit = loader.read(resolvedUri, charOffset,
origin: _compilationUnit.isAugmenting ? _augmentationRoot : null,
originImportUri: _compilationUnit.originImportUri,
fileUri: newFileUri,
accessor: _compilationUnit,
isPatch: _compilationUnit.isAugmenting,
referencesFromIndex: indexedLibrary,
referenceIsPartOwner: indexedLibrary != null);
_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}) {
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(
_compilationUnit,
compilationUnit,
isAugmentationImport,
deferred,
prefix,
combinators,
configurations,
_compilationUnit.fileUri,
charOffset,
prefixCharOffset,
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(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier identifier,
required List<NominalParameterBuilder>? typeParameters,
required TypeBuilder? supertype,
required List<TypeBuilder>? mixins,
required List<TypeBuilder>? interfaces,
required int startOffset,
required int nameOffset,
required int endOffset,
required int supertypeOffset}) {
String className = identifier.name;
endClassDeclaration(className);
ClassFragment declarationFragment =
_declarationFragments.pop() as ClassFragment;
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeParameters(
_problemReporting, typeParameters,
ownerName: className, allowNameConflict: false);
if (declarationFragment.declaresConstConstructor) {
modifiers |= Modifiers.DeclaresConstConstructor;
}
declarationFragment.compilationUnitScope = _compilationUnitScope;
declarationFragment.metadata = metadata;
declarationFragment.modifiers = modifiers;
declarationFragment.supertype = supertype;
declarationFragment.mixins = mixins;
declarationFragment.interfaces = interfaces;
declarationFragment.constructorReferences =
new List<ConstructorReferenceBuilder>.of(_constructorReferences);
declarationFragment.startOffset = startOffset;
declarationFragment.endOffset = endOffset;
_constructorReferences.clear();
_addFragment(declarationFragment);
offsetMap.registerNamedDeclarationFragment(identifier, declarationFragment);
}
@override
void addEnum(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Identifier identifier,
required List<NominalParameterBuilder>? typeParameters,
required List<TypeBuilder>? mixins,
required List<TypeBuilder>? interfaces,
required int startOffset,
required int endOffset}) {
String name = identifier.name;
// Nested declaration began in `OutlineBuilder.beginEnum`.
endEnumDeclaration(name);
EnumFragment declarationFragment =
_declarationFragments.pop() as EnumFragment;
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeParameters(
_problemReporting, typeParameters,
ownerName: name, allowNameConflict: false);
declarationFragment.compilationUnitScope = _compilationUnitScope;
declarationFragment.metadata = metadata;
declarationFragment.mixins = mixins;
declarationFragment.interfaces = interfaces;
declarationFragment.constructorReferences =
new List<ConstructorReferenceBuilder>.of(_constructorReferences);
declarationFragment.startOffset = startOffset;
declarationFragment.endOffset = endOffset;
_constructorReferences.clear();
_addFragment(declarationFragment);
offsetMap.registerNamedDeclarationFragment(identifier, declarationFragment);
}
@override
void addEnumElement(
{required List<MetadataBuilder>? metadata,
required String name,
required int nameOffset,
required ConstructorReferenceBuilder? constructorReferenceBuilder,
required Token? argumentsBeginToken}) {
EnumElementFragment fragment = new EnumElementFragment(
metadata: metadata,
name: name,
nameOffset: nameOffset,
fileUri: _compilationUnit.fileUri,
constructorReferenceBuilder: constructorReferenceBuilder,
argumentsBeginToken: argumentsBeginToken);
_declarationFragments.current.addEnumElement(fragment);
_addFragment(fragment);
}
@override
void addMixinDeclaration(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier identifier,
required List<NominalParameterBuilder>? typeParameters,
required List<TypeBuilder>? supertypeConstraints,
required List<TypeBuilder>? interfaces,
required int startOffset,
required int nameOffset,
required int endOffset}) {
TypeBuilder? supertype;
List<TypeBuilder>? mixins;
if (supertypeConstraints != null && supertypeConstraints.isNotEmpty) {
supertype = supertypeConstraints.first;
if (supertypeConstraints.length > 1) {
mixins = supertypeConstraints.skip(1).toList();
}
}
String className = identifier.name;
endMixinDeclaration(className);
MixinFragment declarationFragment =
_declarationFragments.pop() as MixinFragment;
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeParameters(
_problemReporting, typeParameters,
ownerName: className, allowNameConflict: false);
modifiers |= Modifiers.Abstract;
if (declarationFragment.declaresConstConstructor) {
modifiers |= Modifiers.DeclaresConstConstructor;
}
declarationFragment.compilationUnitScope = _compilationUnitScope;
declarationFragment.metadata = metadata;
declarationFragment.modifiers = modifiers;
declarationFragment.supertype = supertype;
declarationFragment.mixins = mixins;
declarationFragment.interfaces = interfaces;
declarationFragment.constructorReferences =
new List<ConstructorReferenceBuilder>.of(_constructorReferences);
declarationFragment.startOffset = startOffset;
declarationFragment.endOffset = endOffset;
_constructorReferences.clear();
_addFragment(declarationFragment);
offsetMap.registerNamedDeclarationFragment(identifier, declarationFragment);
}
@override
void addNamedMixinApplication(
{required List<MetadataBuilder>? metadata,
required String name,
required List<NominalParameterBuilder>? typeParameters,
required Modifiers modifiers,
required TypeBuilder? supertype,
required List<TypeBuilder> mixins,
required List<TypeBuilder>? interfaces,
required int startOffset,
required int nameOffset,
required int endOffset}) {
// Nested declaration began in `OutlineBuilder.beginNamedMixinApplication`.
endNamedMixinApplication(name);
assert(
_mixinApplications != null, "Late registration of mixin application.");
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
ownerName: name, allowNameConflict: false);
_addFragment(new NamedMixinApplicationFragment(
name: name,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
nameOffset: nameOffset,
endOffset: endOffset,
modifiers: modifiers,
metadata: metadata,
typeParameters: typeParameters,
supertype: supertype,
mixins: mixins,
interfaces: interfaces,
compilationUnitScope: _compilationUnitScope));
}
@override
void addExtensionDeclaration(
{required OffsetMap offsetMap,
required Token beginToken,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier? identifier,
required List<NominalParameterBuilder>? typeParameters,
required TypeBuilder onType,
required int startOffset,
required int nameOrExtensionOffset,
required 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.addTypeParameters(
_problemReporting, typeParameters,
ownerName: name, allowNameConflict: false);
declarationFragment.metadata = metadata;
declarationFragment.modifiers = modifiers;
declarationFragment.onType = onType;
declarationFragment.startOffset = startOffset;
declarationFragment.nameOrExtensionOffset = nameOrExtensionOffset;
declarationFragment.endOffset = endOffset;
_constructorReferences.clear();
_addFragment(declarationFragment);
if (identifier != null) {
offsetMap.registerNamedDeclarationFragment(
identifier, declarationFragment);
} else {
offsetMap.registerUnnamedDeclaration(beginToken, declarationFragment);
}
}
@override
void addExtensionTypeDeclaration(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier identifier,
required List<NominalParameterBuilder>? typeParameters,
required List<TypeBuilder>? interfaces,
required int startOffset,
required int endOffset}) {
String name = identifier.name;
// Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
endExtensionTypeDeclaration(name);
ExtensionTypeFragment declarationFragment =
_declarationFragments.pop() as ExtensionTypeFragment;
NominalParameterNameSpace nominalParameterNameSpace =
_nominalParameterNameSpaces.pop();
nominalParameterNameSpace.addTypeParameters(
_problemReporting, typeParameters,
ownerName: name, allowNameConflict: false);
declarationFragment.metadata = metadata;
declarationFragment.modifiers = modifiers;
declarationFragment.interfaces = interfaces;
declarationFragment.constructorReferences =
new List<ConstructorReferenceBuilder>.of(_constructorReferences);
declarationFragment.startOffset = startOffset;
declarationFragment.endOffset = endOffset;
_constructorReferences.clear();
_addFragment(declarationFragment);
offsetMap.registerNamedDeclarationFragment(identifier, declarationFragment);
}
@override
void addFunctionTypeAlias(
List<MetadataBuilder>? metadata,
String name,
List<NominalParameterBuilder>? typeParameters,
TypeBuilder type,
int nameOffset) {
if (typeParameters != null) {
for (NominalParameterBuilder typeParameter in typeParameters) {
typeParameter.varianceCalculationValue =
VarianceCalculationValue.pending;
}
}
_nominalParameterNameSpaces.pop().addTypeParameters(
_problemReporting, typeParameters,
ownerName: name, allowNameConflict: true);
// Nested declaration began in `OutlineBuilder.beginFunctionTypeAlias`.
endTypedef();
TypedefFragment fragment = new TypedefFragment(
metadata: metadata,
name: name,
typeParameters: typeParameters,
type: type,
fileUri: _compilationUnit.fileUri,
nameOffset: nameOffset);
_addFragment(fragment);
}
@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<NominalParameterBuilder>? typeParameters,
required Token? beginInitializers,
required int startOffset,
required int endOffset,
required int nameOffset,
required int formalsOffset,
required Modifiers 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 (isConstructor) {
switch (declarationFragment) {
case ExtensionFragment():
case ExtensionTypeFragment():
// Discard type parameters declared on the constructor. It's not
// allowed, an error has already been issued and it will cause
// crashes later if they are kept/added to the ones from the parent.
// TODO(johnniwinther): This will cause us issuing errors about not
// knowing the names of what we discard here. Is there a way to
// preserve them?
typeParameters = null;
case ClassFragment():
case MixinFragment():
case EnumFragment():
}
ConstructorName constructorName =
computeAndValidateConstructorName(declarationFragment, identifier);
addConstructor(
offsetMap: offsetMap,
metadata: metadata,
modifiers: modifiers,
identifier: identifier,
constructorName: constructorName,
typeParameters: typeParameters,
formals: formals,
startOffset: startOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
nativeMethodName: nativeMethodName,
beginInitializers: beginInitializers,
forAbstractClassOrMixin: forAbstractClassOrMixin);
} else {
switch (kind!) {
case ProcedureKind.Method:
case ProcedureKind.Operator:
addMethod(
offsetMap: offsetMap,
metadata: metadata,
modifiers: modifiers,
returnType: returnType,
identifier: identifier,
name: name,
typeParameters: typeParameters,
formals: formals,
isOperator: kind == ProcedureKind.Operator,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
nativeMethodName: nativeMethodName,
asyncModifier: asyncModifier,
isInstanceMember: !isStatic,
isExtensionMember: isExtensionMember,
isExtensionTypeMember: isExtensionTypeMember);
case ProcedureKind.Getter:
addGetter(
offsetMap: offsetMap,
metadata: metadata,
modifiers: modifiers,
returnType: returnType,
identifier: identifier,
name: name,
typeParameters: typeParameters,
formals: formals,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
nativeMethodName: nativeMethodName,
asyncModifier: asyncModifier,
isInstanceMember: !isStatic,
isExtensionMember: isExtensionMember,
isExtensionTypeMember: isExtensionTypeMember);
case ProcedureKind.Setter:
addSetter(
offsetMap: offsetMap,
metadata: metadata,
modifiers: modifiers,
returnType: returnType,
identifier: identifier,
name: name,
typeParameters: typeParameters,
formals: formals,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
nativeMethodName: nativeMethodName,
asyncModifier: asyncModifier,
isInstanceMember: !isStatic,
isExtensionMember: isExtensionMember,
isExtensionTypeMember: isExtensionTypeMember);
// Coverage-ignore(suite): Not run.
case ProcedureKind.Factory:
throw new UnsupportedError("Unexpected procedure kind: $kind");
}
}
}
@override
void addPrimaryConstructor(
{required OffsetMap offsetMap,
required Token beginToken,
required String? name,
required List<FormalParameterBuilder>? formals,
required int startOffset,
required int? nameOffset,
required int formalsOffset,
required bool isConst}) {
NominalParameterNameSpace nominalParameterNameSpace =
new NominalParameterNameSpace();
_nominalParameterNameSpaces.push(nominalParameterNameSpace);
_typeScopes.push(new TypeScope(
TypeScopeKind.memberTypeParameters,
new NominalParameterScope(
_typeScopes.current.lookupScope, nominalParameterNameSpace),
_typeScopes.current));
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
ConstructorName constructorName;
String declarationName = _declarationFragments.current.name;
if (name == 'new') {
constructorName = new ConstructorName(
name: '',
nameOffset: nameOffset!,
fullName: declarationName,
fullNameOffset: nameOffset,
fullNameLength: noLength);
} else if (name != null) {
constructorName = new ConstructorName(
name: name,
nameOffset: nameOffset!,
fullName: '$declarationName.$name',
fullNameOffset: nameOffset,
fullNameLength: noLength);
} else {
constructorName = new ConstructorName(
name: '',
nameOffset: null,
fullName: declarationName,
fullNameOffset: formalsOffset,
fullNameLength: noLength);
}
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
PrimaryConstructorFragment fragment = new PrimaryConstructorFragment(
constructorName: constructorName,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
formalsOffset: formalsOffset,
modifiers: isConst ? Modifiers.Const : Modifiers.empty,
returnType: addInferableType(),
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: typeParameterScope.lookupScope,
formals: formals,
forAbstractClassOrMixin: false,
beginInitializers: 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.
// TODO(johnniwinther): Avoid using a dummy token to ensure building
// of constant constructors in the outline phase.
? new Token.eof(-1)
: null);
_addFragment(fragment);
if (isConst) {
_declarationFragments.current.declaresConstConstructor = true;
}
offsetMap.registerPrimaryConstructor(beginToken, fragment);
}
@override
void addConstructor(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier identifier,
required ConstructorName constructorName,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required int startOffset,
required int formalsOffset,
required int endOffset,
required String? nativeMethodName,
required Token? beginInitializers,
required bool forAbstractClassOrMixin}) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
ConstructorFragment fragment = new ConstructorFragment(
constructorName: constructorName,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
modifiers: modifiers - Modifiers.Abstract,
metadata: metadata,
returnType: addInferableType(),
typeParameters: typeParameters,
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: typeParameterScope.lookupScope,
formals: formals,
nativeMethodName: nativeMethodName,
forAbstractClassOrMixin: forAbstractClassOrMixin,
beginInitializers: modifiers.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.
// TODO(johnniwinther): Avoid using a dummy token to ensure building
// of constant constructors in the outline phase.
? (beginInitializers ?? new Token.eof(-1))
: null);
_addFragment(fragment);
if (nativeMethodName != null) {
_addNativeConstructorFragment(fragment);
}
if (modifiers.isConst) {
_declarationFragments.current.declaresConstConstructor = true;
}
offsetMap.registerConstructorFragment(identifier, fragment);
}
@override
void addPrimaryConstructorField(
{required List<MetadataBuilder>? metadata,
required TypeBuilder type,
required String name,
required int nameOffset}) {
_declarationFragments.current.addPrimaryConstructorField(_addField(
metadata: metadata,
modifiers: Modifiers.Final,
isTopLevel: false,
type: type,
name: name,
nameOffset: nameOffset,
endOffset: nameOffset,
initializerToken: null,
hasInitializer: false,
isPrimaryConstructorField: true));
}
@override
void addFactoryMethod(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required Identifier identifier,
required List<FormalParameterBuilder>? formals,
required ConstructorReferenceBuilder? redirectionTarget,
required int startOffset,
required int nameOffset,
required int formalsOffset,
required int endOffset,
required String? nativeMethodName,
required AsyncMarker asyncModifier}) {
DeclarationFragment enclosingDeclaration = _declarationFragments.current;
ConstructorName constructorName = computeAndValidateConstructorName(
enclosingDeclaration, identifier,
isFactory: true);
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
FactoryFragment fragment = new FactoryFragment(
constructorName: constructorName,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
modifiers: modifiers | Modifiers.Static,
metadata: metadata,
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: _typeScopes.current.lookupScope,
formals: formals,
asyncModifier: asyncModifier,
nativeMethodName: nativeMethodName,
redirectionTarget: redirectionTarget);
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
_addFragment(fragment);
if (nativeMethodName != null) {
_addNativeFactoryFragment(fragment);
}
offsetMap.registerFactoryFragment(identifier, fragment);
}
@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
ConstructorName computeAndValidateConstructorName(
DeclarationFragment enclosingDeclaration, Identifier identifier,
{isFactory = false}) {
String className = enclosingDeclaration.name;
String prefix;
String? suffix;
int? suffixOffset;
String fullName;
int fullNameOffset;
int fullNameLength;
int charOffset;
if (identifier is QualifiedNameIdentifier) {
Identifier qualifier = identifier.qualifier;
prefix = qualifier.name;
suffix = identifier.name;
suffixOffset = identifier.nameOffset;
charOffset = qualifier.nameOffset;
String prefixAndSuffix = '${prefix}.${suffix}';
fullNameOffset = qualifier.nameOffset;
// If the there is no space between the prefix and suffix we use the full
// length as the name length. Otherwise the full name has no length.
fullNameLength = fullNameOffset + prefix.length + 1 == suffixOffset
? prefixAndSuffix.length
: noLength;
if (suffix == "new") {
// Normalize `Class.new` to `Class`.
suffix = '';
fullName = className;
} else {
fullName = '$className.$suffix';
}
} else {
prefix = identifier.name;
suffix = null;
suffixOffset = null;
charOffset = identifier.nameOffset;
fullName = prefix;
fullNameOffset = identifier.nameOffset;
fullNameLength = prefix.length;
}
if (prefix == className) {
return new ConstructorName(
name: suffix ?? '',
nameOffset: suffixOffset,
fullName: fullName,
fullNameOffset: fullNameOffset,
fullNameLength: fullNameLength);
} else if (suffix == null) {
// Normalize `foo` in `Class` to `Class.foo`.
fullName = '$className.$prefix';
}
if (suffix == null && !isFactory) {
// This method is called because the syntax indicated that this is a
// constructor, either because it had qualified name or because the method
// had an initializer list.
//
// In either case this is reported elsewhere, and since the name is a
// legal name for a regular method, we don't remove an error on the name.
} else {
_problemReporting.addProblem(messageConstructorWithWrongName, charOffset,
prefix.length, _compilationUnit.fileUri,
context: [
templateConstructorWithWrongNameContext
.withArguments(enclosingDeclaration.name)
.withLocation(
_compilationUnit.importUri,
enclosingDeclaration.fileOffset,
enclosingDeclaration.name.length)
]);
}
return new ConstructorName(
name: suffix ?? prefix,
nameOffset: suffixOffset,
fullName: fullName,
fullNameOffset: fullNameOffset,
fullNameLength: fullNameLength);
}
void _addNativeGetterFragment(GetterFragment fragment) {
_nativeGetterFragments.add(fragment);
}
void _addNativeSetterFragment(SetterFragment fragment) {
_nativeSetterFragments.add(fragment);
}
void _addNativeMethodFragment(MethodFragment fragment) {
_nativeMethodFragments.add(fragment);
}
void _addNativeConstructorFragment(ConstructorFragment fragment) {
_nativeConstructorFragments.add(fragment);
}
void _addNativeFactoryFragment(FactoryFragment method) {
_nativeFactoryFragments.add(method);
}
@override
void addGetter(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required TypeBuilder? returnType,
required Identifier identifier,
required String name,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required int startOffset,
required int nameOffset,
required int formalsOffset,
required int endOffset,
required String? nativeMethodName,
required AsyncMarker asyncModifier,
required bool isInstanceMember,
required bool isExtensionMember,
required bool isExtensionTypeMember}) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
DeclarationFragment? enclosingDeclaration =
_declarationFragments.currentOrNull;
assert(!isExtensionMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionDeclaration);
assert(!isExtensionTypeMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionTypeDeclaration);
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
GetterFragment fragment = new GetterFragment(
name: name,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
isTopLevel: enclosingDeclaration == null,
metadata: metadata,
modifiers: modifiers,
returnType: returnType ?? addInferableType(),
declaredTypeParameters: typeParameters,
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: typeParameterScope.lookupScope,
declaredFormals: formals,
asyncModifier: asyncModifier,
nativeMethodName: nativeMethodName);
_addFragment(fragment);
if (nativeMethodName != null) {
_addNativeGetterFragment(fragment);
}
offsetMap.registerGetter(identifier, fragment);
}
@override
void addSetter(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required TypeBuilder? returnType,
required Identifier identifier,
required String name,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required int startOffset,
required int nameOffset,
required int formalsOffset,
required int endOffset,
required String? nativeMethodName,
required AsyncMarker asyncModifier,
required bool isInstanceMember,
required bool isExtensionMember,
required bool isExtensionTypeMember}) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
DeclarationFragment? enclosingDeclaration =
_declarationFragments.currentOrNull;
assert(!isExtensionMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionDeclaration);
assert(!isExtensionTypeMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionTypeDeclaration);
if (returnType == null) {
returnType = addVoidType(nameOffset);
}
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
SetterFragment fragment = new SetterFragment(
name: name,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
isTopLevel: enclosingDeclaration == null,
metadata: metadata,
modifiers: modifiers,
returnType: returnType,
declaredTypeParameters: typeParameters,
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: typeParameterScope.lookupScope,
declaredFormals: formals,
asyncModifier: asyncModifier,
nativeMethodName: nativeMethodName);
_addFragment(fragment);
if (nativeMethodName != null) {
_addNativeSetterFragment(fragment);
}
offsetMap.registerSetter(identifier, fragment);
}
@override
void addMethod(
{required OffsetMap offsetMap,
required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required TypeBuilder? returnType,
required Identifier identifier,
required String name,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required int startOffset,
required int nameOffset,
required int formalsOffset,
required int endOffset,
required String? nativeMethodName,
required AsyncMarker asyncModifier,
required bool isInstanceMember,
required bool isExtensionMember,
required bool isExtensionTypeMember,
required bool isOperator}) {
TypeScope typeParameterScope = _typeScopes.pop();
assert(typeParameterScope.kind == TypeScopeKind.memberTypeParameters,
"Unexpected type scope: $typeParameterScope.");
DeclarationFragment? enclosingDeclaration =
_declarationFragments.currentOrNull;
assert(!isExtensionMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionDeclaration);
assert(!isExtensionTypeMember ||
enclosingDeclaration?.kind ==
DeclarationFragmentKind.extensionTypeDeclaration);
if (returnType == null) {
if (isOperator && identical(name, indexSetName.text)) {
returnType = addVoidType(nameOffset);
}
}
NominalParameterNameSpace typeParameterNameSpace =
_nominalParameterNameSpaces.pop();
MethodFragment fragment = new MethodFragment(
name: name,
fileUri: _compilationUnit.fileUri,
startOffset: startOffset,
nameOffset: nameOffset,
formalsOffset: formalsOffset,
endOffset: endOffset,
isTopLevel: enclosingDeclaration == null,
metadata: metadata,
modifiers: modifiers,
returnType: returnType ?? addInferableType(),
declaredTypeParameters: typeParameters,
typeParameterNameSpace: typeParameterNameSpace,
typeParameterScope: typeParameterScope.lookupScope,
declaredFormals: formals,
isOperator: isOperator,
asyncModifier: asyncModifier,
nativeMethodName: nativeMethodName);
_addFragment(fragment);
if (nativeMethodName != null) {
_addNativeMethodFragment(fragment);
}
offsetMap.registerMethod(identifier, fragment);
}
@override
void addFields(
OffsetMap offsetMap,
List<MetadataBuilder>? metadata,
Modifiers modifiers,
bool isTopLevel,
TypeBuilder? type,
List<FieldInfo> fieldInfos) {
for (FieldInfo info in fieldInfos) {
bool isConst = modifiers.isConst;
bool isFinal = modifiers.isFinal;
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: metadata,
modifiers: modifiers,
isTopLevel: isTopLevel,
type: type ?? addInferableType(),
name: info.identifier.name,
nameOffset: info.identifier.nameOffset,
endOffset: info.endOffset,
initializerToken: startToken,
hasInitializer: hasInitializer,
constInitializerToken:
potentiallyNeedInitializerInOutline ? startToken : null,
isPrimaryConstructorField: false));
}
}
FieldFragment _addField(
{required List<MetadataBuilder>? metadata,
required Modifiers modifiers,
required bool isTopLevel,
required TypeBuilder type,
required String name,
required int nameOffset,
required int endOffset,
required Token? initializerToken,
required bool hasInitializer,
Token? constInitializerToken,
required bool isPrimaryConstructorField}) {
if (hasInitializer) {
modifiers |= Modifiers.HasInitializer;
}
FieldFragment fragment = new FieldFragment(
name: name,
fileUri: _compilationUnit.fileUri,
nameOffset: nameOffset,
endOffset: endOffset,
initializerToken: initializerToken,
constInitializerToken: constInitializerToken,
metadata: metadata,
type: type,
isTopLevel: isTopLevel,
modifiers: modifiers,
isPrimaryConstructorField: isPrimaryConstructorField);
_addFragment(fragment);
return fragment;
}
@override
FormalParameterBuilder addFormalParameter(
List<MetadataBuilder>? metadata,
FormalParameterKind kind,
Modifiers modifiers,
TypeBuilder type,
String name,
bool hasThis,
bool hasSuper,
int charOffset,
Token? initializerToken,
{bool lowerWildcard = false}) {
assert(!hasThis || !hasSuper,
"Formal parameter '${name}' has both 'this' and 'super' prefixes.");
if (hasThis) {
modifiers |= Modifiers.InitializingFormal;
}
if (hasSuper) {
modifiers |= Modifiers.SuperInitializingFormal;
}
String formalName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && formalName == '_';
if (isWildcard && lowerWildcard) {
formalName = createWildcardFormalParameterName(wildcardVariableIndex);
wildcardVariableIndex++;
}
FormalParameterBuilder formal = new FormalParameterBuilder(
kind, modifiers, type, formalName, 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 InstanceTypeParameterAccessState instanceTypeParameterAccess}) {
return _registerUnresolvedNamedType(new NamedTypeBuilderImpl(
typeName, nullabilityBuilder,
arguments: arguments,
fileUri: _compilationUnit.fileUri,
charOffset: charOffset,
instanceTypeParameterAccess: instanceTypeParameterAccess));
}
NamedTypeBuilder _registerUnresolvedNamedType(NamedTypeBuilder type) {
_typeScopes.current.registerUnresolvedNamedType(type);
return type;
}
@override
FunctionTypeBuilder addFunctionType(
TypeBuilder returnType,
List<StructuralParameterBuilder>? 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);
_checkStructuralParameters(structuralVariableBuilders);
if (structuralVariableBuilders != null) {
for (StructuralParameterBuilder builder in structuralVariableBuilders) {
if (builder.metadata != null) {
if (!libraryFeatures.genericMetadata.isEnabled) {
_problemReporting.addProblem(
messageAnnotationOnFunctionTypeTypeParameter,
builder.fileOffset,
builder.name.length,
builder.fileUri);
}
}
}
}
// Nested declaration began in `OutlineBuilder.beginFunctionType` or
// `OutlineBuilder.beginFunctionTypedFormalParameter`.
endFunctionType();
return builder;
}
void _checkStructuralParameters(
List<StructuralParameterBuilder>? typeParameters) {
Map<String, StructuralParameterBuilder> typeParametersByName =
_structuralParameterScopes.pop();
if (typeParameters == null || typeParameters.isEmpty) return null;
for (StructuralParameterBuilder tv in typeParameters) {
if (tv.isWildcard) continue;
StructuralParameterBuilder? existing = typeParametersByName[tv.name];
if (existing != null) {
// Coverage-ignore-block(suite): Not run.
_problemReporting.addProblem(messageTypeParameterDuplicatedName,
tv.fileOffset, tv.name.length, _compilationUnit.fileUri,
context: [
templateTypeParameterDuplicatedNameCause
.withArguments(tv.name)
.withLocation(_compilationUnit.fileUri, existing.fileOffset,
existing.name.length)
]);
} else {
typeParametersByName[tv.name] = tv;
}
}
}
@override
TypeBuilder addVoidType(int charOffset) {
return new VoidTypeBuilder(_compilationUnit.fileUri, charOffset);
}
@override
NominalParameterBuilder addNominalParameter(List<MetadataBuilder>? metadata,
String name, TypeBuilder? bound, int charOffset, Uri fileUri,
{required TypeParameterKind kind}) {
String variableName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && variableName == '_';
if (isWildcard) {
variableName = createWildcardTypeParameterName(wildcardVariableIndex);
wildcardVariableIndex++;
}
NominalParameterBuilder builder = new NominalParameterBuilder(
variableName, charOffset, fileUri,
bound: bound, metadata: metadata, kind: kind, isWildcard: isWildcard);
_unboundNominalParameters.add(builder);
return builder;
}
@override
StructuralParameterBuilder addStructuralParameter(
List<MetadataBuilder>? metadata,
String name,
TypeBuilder? bound,
int charOffset,
Uri fileUri) {
String variableName = name;
bool isWildcard =
libraryFeatures.wildcardVariables.isEnabled && variableName == '_';
if (isWildcard) {
variableName = createWildcardTypeParameterName(wildcardVariableIndex);
wildcardVariableIndex++;
}
StructuralParameterBuilder builder = new StructuralParameterBuilder(
variableName, charOffset, fileUri,
bound: bound, metadata: metadata, isWildcard: isWildcard);
_unboundStructuralVariables.add(builder);
return builder;
}
@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();
}
void _addFragment(Fragment fragment) {
if (_declarationFragments.isEmpty) {
_libraryNameSpaceBuilder.addFragment(fragment);
} else {
_declarationFragments.current.addFragment(fragment);
}
}
@override
void takeMixinApplications(
Map<SourceClassBuilder, TypeBuilder> mixinApplications) {
assert(_mixinApplications != null,
"Mixin applications have already been processed.");
mixinApplications.addAll(_mixinApplications!);
_mixinApplications = null;
}
@override
void collectUnboundTypeParameters(
SourceLibraryBuilder libraryBuilder,
Map<NominalParameterBuilder, SourceLibraryBuilder> nominalVariables,
Map<StructuralParameterBuilder, SourceLibraryBuilder>
structuralVariables) {
for (NominalParameterBuilder builder in _unboundNominalParameters) {
nominalVariables[builder] = libraryBuilder;
}
for (StructuralParameterBuilder builder in _unboundStructuralVariables) {
structuralVariables[builder] = libraryBuilder;
}
_unboundStructuralVariables.clear();
_unboundNominalParameters.clear();
}
@override
TypeScope get typeScope => _typeScopes.current;
@override
String? get name => _name;
@override
List<MetadataBuilder>? get metadata => _metadata;
@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
void registerUnresolvedStructuralParameters(
List<StructuralParameterBuilder> unboundTypeParameters) {
this._unboundStructuralVariables.addAll(unboundTypeParameters);
}
@override
int finishNativeMethods() {
for (FactoryFragment fragment in _nativeFactoryFragments) {
fragment.builder.becomeNative(loader);
}
for (GetterFragment fragment in _nativeGetterFragments) {
fragment.becomeNative(loader);
}
for (SetterFragment fragment in _nativeSetterFragments) {
fragment.becomeNative(loader);
}
for (MethodFragment fragment in _nativeMethodFragments) {
fragment.becomeNative(loader);
}
for (ConstructorFragment fragment in _nativeConstructorFragments) {
fragment.builder.becomeNative(loader);
}
return _nativeFactoryFragments.length;
}
@override
List<LibraryPart> get libraryParts => _libraryParts;
}