blob: 995d96e2e6a67e171d48ee1145b83b0cc4a9bd27 [file] [log] [blame]
// Copyright (c) 2016, 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/messages/severity.dart' show Severity;
import 'package:kernel/ast.dart' show Library, Version;
import '../base/export.dart' show Export;
import '../base/loader.dart' show Loader;
import '../base/messages.dart'
show
FormattedMessage,
LocatedMessage,
Message,
ProblemReporting,
templateInternalProblemConstructorNotFound,
templateInternalProblemNotFoundIn,
templateInternalProblemPrivateConstructorAccess;
import '../base/name_space.dart';
import '../base/problems.dart' show internalProblem;
import '../source/name_scheme.dart';
import 'builder.dart';
import 'compilation_unit.dart';
import 'constructor_builder.dart';
import 'declaration_builders.dart';
import 'factory_builder.dart';
import 'member_builder.dart';
import 'type_builder.dart';
abstract class LibraryBuilder implements Builder, ProblemReporting {
NameSpace get libraryNameSpace;
ComputedNameSpace get exportNameSpace;
List<Export> get exporters;
LibraryBuilder? get partOfLibrary;
LibraryBuilder get nameOriginBuilder;
bool get mayImplementRestrictedTypes;
bool get isPart;
Loader get loader;
/// Returns the [Library] built by this builder.
Library get library;
LibraryName get libraryName;
@override
Uri get fileUri;
/// Returns the [Uri]s for the libraries that this library depend upon, either
/// through import or export.
Iterable<Uri> get dependencies;
/// Returns the import uri for the library.
///
/// This is the canonical uri for the library, for instance 'dart:core'.
Uri get importUri;
/// Returns the language [Version] used for this library.
Version get languageVersion;
/// If true, the library is not supported through the 'dart.library.*' value
/// used in conditional imports and `bool.fromEnvironment` constants.
bool get isUnsupported;
/// [Iterator] for all declarations declared in this library of type [T].
///
/// If [includeDuplicates] is `true`, duplicate declarations are included.
Iterator<T> filteredMembersIterator<T extends NamedBuilder>(
{required bool includeDuplicates});
/// Looks up [constructorName] in the class named [className].
///
/// The class is looked up in this library's export scope unless
/// [bypassLibraryPrivacy] is true, in which case it is looked up in the
/// library scope of this library.
///
/// It is an error if no such class is found, or if the class doesn't have a
/// matching constructor (or factory).
///
/// If [constructorName] is null or the empty string, it's assumed to be an
/// unnamed constructor. it's an error if [constructorName] starts with
/// `"_"`, and [bypassLibraryPrivacy] is false.
MemberBuilder getConstructor(String className,
{String constructorName, bool bypassLibraryPrivacy = false});
void becomeCoreLibrary();
/// Lookups the member [name] declared in this library.
///
/// If [required] is `true` and no member is found an internal problem is
/// reported.
NamedBuilder? lookupLocalMember(String name, {bool required = false});
void recordAccess(
CompilationUnit accessor, int charOffset, int length, Uri fileUri);
/// Returns `true` if [typeDeclarationBuilder] is the 'Function' class defined
/// in [coreLibrary].
static bool isFunction(TypeDeclarationBuilder? typeDeclarationBuilder,
LibraryBuilder coreLibrary) {
return typeDeclarationBuilder is ClassBuilder &&
typeDeclarationBuilder.name == 'Function' &&
typeDeclarationBuilder.libraryBuilder == coreLibrary;
}
/// Returns `true` if [typeDeclarationBuilder] is the 'Record' class defined
/// in [coreLibrary].
static bool isRecord(TypeDeclarationBuilder? typeDeclarationBuilder,
LibraryBuilder coreLibrary) {
return typeDeclarationBuilder is ClassBuilder &&
typeDeclarationBuilder.name == 'Record' &&
typeDeclarationBuilder.libraryBuilder == coreLibrary;
}
}
abstract class LibraryBuilderImpl extends BuilderImpl
implements LibraryBuilder {
@override
final Uri fileUri;
LibraryBuilderImpl(this.fileUri);
@override
// Coverage-ignore(suite): Not run.
bool get isSynthetic => false;
@override
// Coverage-ignore(suite): Not run.
Builder? get parent => null;
@override
int get fileOffset => -1;
@override
bool get isPart => false;
@override
Loader get loader;
@override
Uri get importUri;
@override
FormattedMessage? addProblem(
Message message, int charOffset, int length, Uri? fileUri,
{bool wasHandled = false,
List<LocatedMessage>? context,
Severity? severity,
bool problemOnLibrary = false}) {
fileUri ??= this.fileUri;
return loader.addProblem(message, charOffset, length, fileUri,
wasHandled: wasHandled,
context: context,
severity: severity,
problemOnLibrary: true);
}
@override
MemberBuilder getConstructor(String className,
{String? constructorName, bool bypassLibraryPrivacy = false}) {
constructorName ??= "";
if (constructorName.startsWith("_") && !bypassLibraryPrivacy) {
return internalProblem(
templateInternalProblemPrivateConstructorAccess
.withArguments(constructorName),
-1,
null);
}
Builder? cls = (bypassLibraryPrivacy ? libraryNameSpace : exportNameSpace)
.lookupLocalMember(className)
?.getable;
if (cls is TypeAliasBuilder) {
// Coverage-ignore-block(suite): Not run.
TypeAliasBuilder aliasBuilder = cls;
// No type arguments are available, but this method is only called in
// order to find constructors of specific non-generic classes (errors),
// so we can pass the empty list.
cls = aliasBuilder.unaliasDeclaration(const <TypeBuilder>[]);
}
if (cls is ClassBuilder) {
// TODO(ahe): This code is similar to code in `endNewExpression` in
// `body_builder.dart`, try to share it.
MemberBuilder? constructor =
cls.findConstructorOrFactory(constructorName, -1, fileUri, this);
if (constructor == null) {
// Fall-through to internal error below.
} else if (constructor is ConstructorBuilder) {
if (!cls.isAbstract) {
return constructor;
}
}
// Coverage-ignore(suite): Not run.
else if (constructor is FactoryBuilder) {
return constructor;
}
}
// Coverage-ignore-block(suite): Not run.
throw internalProblem(
templateInternalProblemConstructorNotFound.withArguments(
"$className.$constructorName", importUri),
-1,
null);
}
@override
NamedBuilder? lookupLocalMember(String name, {bool required = false}) {
NamedBuilder? builder = libraryNameSpace.lookupLocalMember(name)?.getable;
if (required && builder == null) {
internalProblem(
templateInternalProblemNotFoundIn.withArguments(
name, fullNameForErrors),
-1,
null);
}
return builder;
}
@override
void recordAccess(
CompilationUnit accessor, int charOffset, int length, Uri fileUri) {}
@override
String toString() {
return '$runtimeType(${isPart ? fileUri : importUri})';
}
}