|  | // 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:kernel/ast.dart' show LibraryDependency; | 
|  |  | 
|  | import '../base/combinator.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 'declaration_builders.dart'; | 
|  | import 'library_builder.dart'; | 
|  |  | 
|  | class PrefixBuilder extends BuilderImpl { | 
|  | final String name; | 
|  |  | 
|  | final NameSpace _prefixNameSpace = new NameSpaceImpl(); | 
|  |  | 
|  | late final LookupScope _prefixScope = | 
|  | new NameSpaceLookupScope(_prefixNameSpace, ScopeKind.library, "top"); | 
|  |  | 
|  | @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('loadLibrary', 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. | 
|  | Builder? lookup(String name, int charOffset, Uri fileUri) { | 
|  | return _prefixScope.lookupGetable(name, charOffset, fileUri); | 
|  | } | 
|  |  | 
|  | void addToPrefixScope(String name, Builder member, | 
|  | {required int importOffset, required int prefixOffset}) { | 
|  | if (deferred && member is ExtensionBuilder) { | 
|  | parent.addProblem(templateDeferredExtensionImport.withArguments(name), | 
|  | importOffset, noLength, fileUri); | 
|  | } | 
|  |  | 
|  | Builder? existing = | 
|  | _prefixNameSpace.lookupLocalMember(name, setter: member.isSetter); | 
|  | Builder result; | 
|  | if (existing != null) { | 
|  | result = computeAmbiguousDeclarationForImport( | 
|  | parent, name, existing, member, | 
|  | uriOffset: new UriOffset(fileUri, prefixOffset)); | 
|  | } else { | 
|  | result = member; | 
|  | } | 
|  | _prefixNameSpace.addLocalMember(name, result, setter: member.isSetter); | 
|  | if (member is ExtensionBuilder) { | 
|  | _prefixNameSpace.addExtension(member); | 
|  | } | 
|  | } | 
|  |  | 
|  | @override | 
|  | // Coverage-ignore(suite): Not run. | 
|  | String get fullNameForErrors => name; | 
|  | } | 
|  |  | 
|  | 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)'; | 
|  | } |