blob: 99d1ace9da9998f0190b066baacc7778e71dad54 [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:front_end/src/builder/property_builder.dart';
import 'package:kernel/ast.dart' show LibraryDependency;
import '../base/combinator.dart';
import '../base/lookup_result.dart';
import '../base/messages.dart';
import '../base/name_space.dart';
import '../base/scope.dart';
import '../base/uri_offset.dart';
import '../kernel/load_library_builder.dart' show LoadLibraryBuilder;
import '../kernel/utils.dart';
import '../source/source_library_builder.dart';
import 'builder.dart';
import 'compilation_unit.dart';
import 'declaration_builders.dart';
class PrefixBuilder extends NamedBuilderImpl
with LookupResultMixin
implements LookupResult {
@override
final String name;
final ComputedMutableNameSpace _prefixNameSpace =
new ComputedMutableNameSpace();
late final LookupScope _prefixScope = new NameSpaceLookupScope(
_prefixNameSpace,
ScopeKind.library,
);
@override
final SourceLibraryBuilder parent;
final bool deferred;
@override
final Uri fileUri;
@override
final int fileOffset;
final LoadLibraryBuilder? loadLibraryBuilder;
final bool isWildcard;
PrefixBuilder(
this.name,
this.deferred,
this.parent,
this.loadLibraryBuilder, {
required this.fileUri,
required int prefixOffset,
required int importOffset,
}) : fileOffset = prefixOffset,
isWildcard = name == '_' {
assert(
deferred == (loadLibraryBuilder != null),
"LoadLibraryBuilder must be provided iff prefix is deferred.",
);
if (loadLibraryBuilder != null) {
addToPrefixScope(
loadLibraryBuilder!.name,
loadLibraryBuilder!,
importOffset: importOffset,
prefixOffset: prefixOffset,
);
}
}
LookupScope get prefixScope => _prefixScope;
void forEachExtension(void Function(ExtensionBuilder) f) {
_prefixNameSpace.forEachLocalExtension(f);
}
LibraryDependency? get dependency => loadLibraryBuilder?.importDependency;
/// Lookup a member with [name] in the export scope.
LookupResult? lookup(String name) {
return _prefixScope.lookup(name);
}
void addToPrefixScope(
String name,
NamedBuilder member, {
required int importOffset,
required int prefixOffset,
}) {
if (deferred && member is ExtensionBuilder) {
parent.addProblem(
codeDeferredExtensionImport.withArguments(name),
importOffset,
noLength,
fileUri,
);
}
bool isSetter = isMappedAsSetter(member);
LookupResult? existingResult = _prefixNameSpace.lookup(name);
NamedBuilder? existing = isSetter
? existingResult?.setable
: existingResult?.getable;
if (existing != null) {
NamedBuilder result = computeAmbiguousDeclarationForImport(
parent,
name,
existing,
member,
uriOffset: new UriOffset(fileUri, prefixOffset),
);
_prefixNameSpace.replaceLocalMember(name, result, setter: isSetter);
} else {
_prefixNameSpace.addLocalMember(name, member, setter: isSetter);
}
if (member is ExtensionBuilder) {
_prefixNameSpace.addExtension(member);
}
}
@override
// Coverage-ignore(suite): Not run.
String get fullNameForErrors => name;
@override
NamedBuilder get getable => this;
@override
NamedBuilder? get setable => null;
}
class PrefixFragment {
final String name;
final SourceCompilationUnit importer;
final CompilationUnit? imported;
final List<CombinatorBuilder>? combinators;
final bool deferred;
final Uri fileUri;
final int importOffset;
final int prefixOffset;
PrefixBuilder? _builder;
PrefixFragment({
required this.name,
required this.importer,
required this.imported,
required this.combinators,
required this.deferred,
required this.fileUri,
required this.importOffset,
required this.prefixOffset,
});
PrefixBuilder createPrefixBuilder() {
LoadLibraryBuilder? loadLibraryBuilder;
if (deferred) {
loadLibraryBuilder = new LoadLibraryBuilder(
importer.libraryBuilder,
prefixOffset,
imported!,
name,
importOffset,
toCombinators(combinators),
);
}
return builder = new PrefixBuilder(
name,
deferred,
importer.libraryBuilder,
loadLibraryBuilder,
fileUri: fileUri,
prefixOffset: prefixOffset,
importOffset: importOffset,
);
}
PrefixBuilder get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
void set builder(PrefixBuilder value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
@override
String toString() => '$runtimeType($name,$fileUri,$importOffset)';
}