Files
sdk/pkg/kernel/lib/reference_from_index.dart
T
Johnni Winther 6795c753fd [cfe] Handle unnamed extensions in parts
This introduces a MemberName abstraction that supports the late
computation of member names, taking privacy and synthesized names
of unnamed extensions into account. With this feature, the unnamed
extension are now more directly handled as having no (known) name
which avoids the clash between the eagerly synthesized named of
unnamed extensions in different parts.

Closes #48765

TEST=existing

Change-Id: I62c00ace017141ecbc61eeecb275d0211f341c82
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/258800
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2022-09-14 14:44:12 +00:00

166 lines
5.7 KiB
Dart

// 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.
import "ast.dart"
show
Class,
Constructor,
Extension,
ExtensionMemberDescriptor,
Field,
Library,
Member,
Name,
Procedure,
ProcedureKind,
Reference,
Typedef;
class ReferenceFromIndex {
Map<Library, IndexedLibrary> _indexedLibraries =
new Map<Library, IndexedLibrary>.identity();
/// Add an entry mapping from *new* [library] to an index of the old library.
void addIndexedLibrary(Library library, IndexedLibrary indexedLibrary) {
assert(!_indexedLibraries.containsKey(library));
_indexedLibraries[library] = indexedLibrary;
}
/// Lookup the new library and get an index of the old library.
IndexedLibrary? lookupLibrary(Library library) => _indexedLibraries[library];
}
abstract class IndexedContainer {
final Map<Name, Reference> _fieldReferences = new Map<Name, Reference>();
final Map<Name, Reference> _getterReferences = new Map<Name, Reference>();
final Map<Name, Reference> _setterReferences = new Map<Name, Reference>();
Reference? lookupFieldReference(Name name) => _fieldReferences[name];
Reference? lookupGetterReference(Name name) => _getterReferences[name];
Reference? lookupSetterReference(Name name) => _setterReferences[name];
Library get library;
void _addProcedures(List<Procedure> procedures) {
for (int i = 0; i < procedures.length; i++) {
_addProcedure(procedures[i]);
}
}
void _addProcedure(Procedure procedure) {
Name name = procedure.name;
if (procedure.isSetter) {
assert(_setterReferences[name] == null);
_setterReferences[name] = procedure.reference;
} else {
assert(_getterReferences[name] == null);
assert(procedure.kind == ProcedureKind.Method ||
procedure.kind == ProcedureKind.Getter ||
procedure.kind == ProcedureKind.Operator);
_getterReferences[name] = procedure.reference;
}
}
void _addFields(List<Field> fields) {
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Name name = field.name;
assert(_fieldReferences[name] == null);
_fieldReferences[name] = field.fieldReference;
assert(_getterReferences[name] == null);
_getterReferences[name] = field.getterReference;
if (field.hasSetter) {
assert(_setterReferences[name] == null);
_setterReferences[name] = field.setterReference!;
}
}
}
}
class IndexedLibrary extends IndexedContainer {
final Map<String, Typedef> _typedefs = new Map<String, Typedef>();
final Map<String, Class> _classes = new Map<String, Class>();
final Map<String, IndexedClass> _indexedClasses =
new Map<String, IndexedClass>();
final Map<String, Extension> _extensions = new Map<String, Extension>();
@override
final Library library;
IndexedLibrary(this.library) {
for (int i = 0; i < library.typedefs.length; i++) {
Typedef typedef = library.typedefs[i];
assert(_typedefs[typedef.name] == null);
_typedefs[typedef.name] = typedef;
}
for (int i = 0; i < library.classes.length; i++) {
Class c = library.classes[i];
assert(_classes[c.name] == null);
_classes[c.name] = c;
assert(_indexedClasses[c.name] == null);
_indexedClasses[c.name] = new IndexedClass._(c, library);
}
List<Extension> unnamedExtensions = [];
for (int i = 0; i < library.extensions.length; i++) {
Extension extension = library.extensions[i];
if (extension.isUnnamedExtension) {
unnamedExtensions.add(extension);
} else {
assert(_extensions[extension.name] == null);
_extensions[extension.name] = extension;
}
}
_addProcedures(library.procedures);
_addFields(library.fields);
// Unnamed extensions and their members cannot be looked up and reused and
// their references should not therefore not be bound to the canonical names
// as it would otherwise prevent (new) unnamed extensions and member from
// repurposing these canonical names.
for (Extension extension in unnamedExtensions) {
extension.reference.canonicalName?.unbind();
for (ExtensionMemberDescriptor descriptor in extension.members) {
Reference reference = descriptor.member;
Member member = reference.asMember;
if (member is Field) {
member.fieldReference.canonicalName?.unbind();
member.getterReference.canonicalName?.unbind();
member.setterReference?.canonicalName?.unbind();
} else {
member.reference.canonicalName?.unbind();
}
}
}
}
Typedef? lookupTypedef(String name) => _typedefs[name];
Class? lookupClass(String name) => _classes[name];
IndexedClass? lookupIndexedClass(String name) => _indexedClasses[name];
Extension? lookupExtension(String name) => _extensions[name];
}
class IndexedClass extends IndexedContainer {
final Class cls;
final Map<Name, Reference> _constructors = new Map<Name, Reference>();
@override
final Library library;
IndexedClass._(this.cls, this.library) {
for (int i = 0; i < cls.constructors.length; i++) {
Constructor constructor = cls.constructors[i];
_constructors[constructor.name] = constructor.reference;
}
for (int i = 0; i < cls.procedures.length; i++) {
Procedure procedure = cls.procedures[i];
if (procedure.isFactory) {
_constructors[procedure.name] = procedure.reference;
} else {
_addProcedure(procedure);
}
}
_addFields(cls.fields);
}
Reference? lookupConstructorReference(Name name) => _constructors[name];
}