blob: 5c150adbba3e4a37182ac0d5792841c6cb55d5a5 [file] [log] [blame]
// Copyright (c) 2019, 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.
// @dart = 2.9
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import '../fasta_codes.dart' show templateInternalProblemNotFoundIn;
import '../scope.dart';
import '../problems.dart';
import '../util/helpers.dart';
import 'builder.dart';
import 'library_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
import 'nullability_builder.dart';
import 'type_builder.dart';
import 'type_variable_builder.dart';
import 'declaration_builder.dart';
abstract class ExtensionBuilder implements DeclarationBuilder {
List<TypeVariableBuilder> get typeParameters;
TypeBuilder get onType;
/// Return the [Extension] built by this builder.
Extension get extension;
void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
List<DelayedActionPerformer> delayedActionPerformers);
/// Looks up extension member by [name] taking privacy into account.
///
/// If [setter] is `true` the sought member is a setter or assignable field.
/// If [required] is `true` and no member is found an internal problem is
/// reported.
///
/// If the extension member is a duplicate, `null` is returned.
// TODO(johnniwinther): Support [AmbiguousBuilder] here and in instance
// member lookup to avoid reporting that the member doesn't exist when it is
// duplicate.
Builder lookupLocalMemberByName(Name name,
{bool setter: false, bool required: false});
/// Calls [f] for each member declared in this extension.
void forEach(void f(String name, Builder builder));
}
abstract class ExtensionBuilderImpl extends DeclarationBuilderImpl
implements ExtensionBuilder {
@override
final List<TypeVariableBuilder> typeParameters;
@override
final TypeBuilder onType;
ExtensionBuilderImpl(
List<MetadataBuilder> metadata,
int modifiers,
String name,
LibraryBuilder parent,
int charOffset,
Scope scope,
this.typeParameters,
this.onType)
: super(metadata, modifiers, name, parent, charOffset, scope);
/// Lookup a static member of this declaration.
@override
Builder findStaticBuilder(
String name, int charOffset, Uri fileUri, LibraryBuilder accessingLibrary,
{bool isSetter: false}) {
if (accessingLibrary.origin != library.origin && name.startsWith("_")) {
return null;
}
Builder declaration = isSetter
? scope.lookupSetter(name, charOffset, fileUri, isInstanceScope: false)
: scope.lookup(name, charOffset, fileUri, isInstanceScope: false);
// TODO(johnniwinther): Handle patched extensions.
return declaration;
}
@override
DartType buildType(LibraryBuilder library,
NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
[bool notInstanceContext]) {
throw new UnsupportedError("ExtensionBuilder.buildType is not supported.");
}
@override
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
throw new UnsupportedError("ExtensionBuilder.buildTypesWithBuiltArguments "
"is not supported.");
}
@override
void forEach(void f(String name, Builder builder)) {
scope.forEach(f);
}
@override
bool get isExtension => true;
@override
InterfaceType get thisType => null;
@override
Builder lookupLocalMember(String name,
{bool setter: false, bool required: false}) {
// TODO(johnniwinther): Support patching on extensions.
Builder builder = scope.lookupLocalMember(name, setter: setter);
if (required && builder == null) {
internalProblem(
templateInternalProblemNotFoundIn.withArguments(
name, fullNameForErrors),
-1,
null);
}
return builder;
}
@override
Builder lookupLocalMemberByName(Name name,
{bool setter: false, bool required: false}) {
Builder builder =
lookupLocalMember(name.text, setter: setter, required: required);
if (builder != null) {
if (name.isPrivate && library.library != name.library) {
builder = null;
} else if (builder.isDuplicate) {
// Duplicates are not visible in the instance scope.
builder = null;
} else if (builder is MemberBuilder && builder.isConflictingSetter) {
// Conflicting setters are not visible in the instance scope.
// TODO(johnniwinther): Should we return an [AmbiguousBuilder] here and
// above?
builder = null;
}
}
return builder;
}
@override
String get debugName => "ExtensionBuilder";
@override
void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
List<DelayedActionPerformer> delayedActionPerformers) {
void build(String ignore, Builder declaration) {
MemberBuilder member = declaration;
member.buildOutlineExpressions(
library, coreTypes, delayedActionPerformers);
}
// TODO(johnniwinther): Handle annotations on the extension declaration.
//MetadataBuilder.buildAnnotations(
// isPatch ? origin.extension : extension,
// metadata, library, this, null);
scope.forEach(build);
}
}