7226c7245e
Closes #28421 Closes #29169 TEST=existing Change-Id: Iee7d84fadc10981648cb327589fd7aa15b9b3e12 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/308140 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Jens Johansen <jensj@google.com> Reviewed-by: Nicholas Shahan <nshahan@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
322 lines
12 KiB
Dart
322 lines
12 KiB
Dart
// Copyright (c) 2021, 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:expect/expect.dart';
|
|
import 'package:kernel/ast.dart';
|
|
import 'package:kernel/src/equivalence.dart';
|
|
|
|
void testReferenceNames(Map<ReferenceNameKind, List<ReferenceNameObject>> map1,
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> map2) {
|
|
Expect.setEquals(map1.keys, map2.keys);
|
|
map1.forEach((ReferenceNameKind kind1, List<ReferenceNameObject> list1) {
|
|
map1.forEach((ReferenceNameKind kind2, List<ReferenceNameObject> list2) {
|
|
for (int index1 = 0; index1 < list1.length; index1++) {
|
|
for (int index2 = 0; index2 < list2.length; index2++) {
|
|
ReferenceName name1 = list1[index1].referenceName;
|
|
Object object1 = list1[index1].object;
|
|
ReferenceName name2 = list2[index2].referenceName;
|
|
Object object2 = list2[index2].object;
|
|
if (kind1 == kind2 && index1 == index2) {
|
|
Expect.equals(
|
|
name1,
|
|
name2,
|
|
"Expected $name1 for ${object1} (${object1.runtimeType}) and "
|
|
"$name2 for $object2 (${object2.runtimeType}) to be equal.");
|
|
} else {
|
|
Expect.notEquals(
|
|
name1,
|
|
name2,
|
|
"Expected $name1 for ${object1} (${object1.runtimeType}) and "
|
|
"$name2 for $object2 (${object2.runtimeType}) to be unequal.");
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
void main() {
|
|
Component component1 = createComponent();
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> referenceNames1 =
|
|
computeReferenceNamesFromComponent(component1);
|
|
|
|
Component component2 = createComponent();
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> referenceNames2 =
|
|
computeReferenceNamesFromComponent(component2);
|
|
|
|
Component component3 = createComponent();
|
|
component3.computeCanonicalNames();
|
|
CanonicalName root3 = component3.root;
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> referenceNames3 =
|
|
computeReferenceNamesFromCanonicalName(root3);
|
|
|
|
Component component4 = createComponent();
|
|
component4.computeCanonicalNames();
|
|
CanonicalName root4 = component3.root;
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> referenceNames4 =
|
|
computeReferenceNamesFromCanonicalName(root4);
|
|
|
|
testReferenceNames(referenceNames1, referenceNames2);
|
|
testReferenceNames(referenceNames1, referenceNames3);
|
|
testReferenceNames(referenceNames3, referenceNames4);
|
|
}
|
|
|
|
Component createComponent() {
|
|
Component component = new Component();
|
|
Library library1 = new Library(Uri.parse('test:library1'), fileUri: dummyUri);
|
|
component.libraries.add(library1);
|
|
Library library2 = new Library(Uri.parse('test:library2'), fileUri: dummyUri);
|
|
component.libraries.add(library2);
|
|
|
|
library1.addProcedure(new Procedure(
|
|
new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
library1.addProcedure(new Procedure(
|
|
new Name('bar'), ProcedureKind.Operator, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
library1.addProcedure(new Procedure(
|
|
new Name('baz'), ProcedureKind.Factory, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
library1.addProcedure(new Procedure(
|
|
new Name('boz'), ProcedureKind.Getter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
// The setter should be distinct from the getter even when they have the same
|
|
// name.
|
|
library1.addProcedure(new Procedure(
|
|
new Name('boz'), ProcedureKind.Setter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
|
|
library1.addProcedure(new Procedure(
|
|
new Name('_boz', library2), ProcedureKind.Getter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
// The setter should be distinct from the getter even when they have the same
|
|
// name.
|
|
library1.addProcedure(new Procedure(
|
|
new Name('_boz', library2), ProcedureKind.Setter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
|
|
library1.addField(
|
|
new Field.immutable(new Name('_foo', library1), fileUri: dummyUri));
|
|
library1.addField(
|
|
new Field.mutable(new Name('_bar', library2), fileUri: dummyUri));
|
|
|
|
Class class1 = new Class(name: 'Foo', fileUri: dummyUri);
|
|
library2.addClass(class1);
|
|
Class class2 = new Class(name: 'Bar', fileUri: dummyUri);
|
|
library2.addClass(class2);
|
|
|
|
class2.addConstructor(new Constructor(new FunctionNode(null),
|
|
name: new Name(''), fileUri: dummyUri));
|
|
class2.addConstructor(new Constructor(new FunctionNode(null),
|
|
name: new Name('_', library1), fileUri: dummyUri));
|
|
|
|
class2.addProcedure(new Procedure(
|
|
new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
class2.addProcedure(new Procedure(
|
|
new Name('bar'), ProcedureKind.Operator, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
class2.addProcedure(new Procedure(
|
|
new Name('baz'), ProcedureKind.Factory, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
class2.addProcedure(new Procedure(
|
|
new Name('boz'), ProcedureKind.Getter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
// The setter should be distinct from the getter even when they have the same
|
|
// name.
|
|
class2.addProcedure(new Procedure(
|
|
new Name('boz'), ProcedureKind.Setter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
|
|
class2.addProcedure(new Procedure(
|
|
new Name('_boz', library2), ProcedureKind.Getter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
// The setter should be distinct from the getter even when they have the same
|
|
// name.
|
|
class2.addProcedure(new Procedure(
|
|
new Name('_boz', library2), ProcedureKind.Setter, new FunctionNode(null),
|
|
fileUri: dummyUri));
|
|
|
|
class2.addField(
|
|
new Field.immutable(new Name('_foo', library1), fileUri: dummyUri));
|
|
class2.addField(
|
|
new Field.mutable(new Name('_bar', library2), fileUri: dummyUri));
|
|
|
|
library1.addExtension(new Extension(name: 'Baz', fileUri: dummyUri));
|
|
|
|
library1.addTypedef(new Typedef('Boz', dummyDartType, fileUri: dummyUri));
|
|
|
|
return component;
|
|
}
|
|
|
|
void sortReferenceNames(Map<ReferenceNameKind, List<ReferenceNameObject>> map) {
|
|
map.forEach((key, value) {
|
|
value.sort(
|
|
(n1, n2) => n1.referenceName.name!.compareTo(n2.referenceName.name!));
|
|
});
|
|
}
|
|
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>>
|
|
computeReferenceNamesFromComponent(Component component) {
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> map = {};
|
|
void add(ReferenceNameKind kind, ReferenceNameObject object) {
|
|
(map[kind] ??= []).add(object);
|
|
}
|
|
|
|
for (Library library in component.libraries) {
|
|
add(ReferenceNameKind.Library,
|
|
new ReferenceNameObject(ReferenceName.fromNamedNode(library), library));
|
|
for (Typedef typedef in library.typedefs) {
|
|
add(
|
|
ReferenceNameKind.Typedef,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(typedef), typedef));
|
|
}
|
|
for (Field field in library.fields) {
|
|
add(
|
|
ReferenceNameKind.Field,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(field, ReferenceNameKind.Field),
|
|
field));
|
|
add(
|
|
ReferenceNameKind.Getter,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(field, ReferenceNameKind.Getter),
|
|
field));
|
|
if (field.hasSetter) {
|
|
add(
|
|
ReferenceNameKind.Setter,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(field, ReferenceNameKind.Setter),
|
|
field));
|
|
}
|
|
}
|
|
for (Procedure procedure in library.procedures) {
|
|
ReferenceNameKind kind;
|
|
if (procedure.isGetter) {
|
|
kind = ReferenceNameKind.Getter;
|
|
} else if (procedure.isSetter) {
|
|
kind = ReferenceNameKind.Setter;
|
|
} else {
|
|
kind = ReferenceNameKind.Function;
|
|
}
|
|
add(
|
|
kind,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(procedure), procedure));
|
|
}
|
|
for (Class cls in library.classes) {
|
|
add(ReferenceNameKind.Declaration,
|
|
new ReferenceNameObject(ReferenceName.fromNamedNode(cls), cls));
|
|
|
|
for (Constructor constructor in cls.constructors) {
|
|
add(
|
|
ReferenceNameKind.Function,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(constructor), constructor));
|
|
}
|
|
for (Procedure procedure in cls.procedures) {
|
|
ReferenceNameKind kind;
|
|
if (procedure.isGetter) {
|
|
kind = ReferenceNameKind.Getter;
|
|
} else if (procedure.isSetter) {
|
|
kind = ReferenceNameKind.Setter;
|
|
} else {
|
|
kind = ReferenceNameKind.Function;
|
|
}
|
|
add(
|
|
kind,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(procedure), procedure));
|
|
}
|
|
for (Field field in cls.fields) {
|
|
add(ReferenceNameKind.Field,
|
|
new ReferenceNameObject(ReferenceName.fromNamedNode(field), field));
|
|
add(
|
|
ReferenceNameKind.Getter,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(field, ReferenceNameKind.Getter),
|
|
field));
|
|
if (field.hasSetter) {
|
|
add(
|
|
ReferenceNameKind.Setter,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(field, ReferenceNameKind.Setter),
|
|
field));
|
|
}
|
|
}
|
|
}
|
|
for (Extension extension in library.extensions) {
|
|
add(
|
|
ReferenceNameKind.Declaration,
|
|
new ReferenceNameObject(
|
|
ReferenceName.fromNamedNode(extension), extension));
|
|
}
|
|
}
|
|
sortReferenceNames(map);
|
|
return map;
|
|
}
|
|
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>>
|
|
computeReferenceNamesFromCanonicalName(CanonicalName root) {
|
|
Map<ReferenceNameKind, List<ReferenceNameObject>> map = {};
|
|
|
|
void visit(CanonicalName canonicalName, ReferenceNameKind kind) {
|
|
void addObject() {
|
|
(map[kind] ??= []).add(new ReferenceNameObject(
|
|
ReferenceName.fromCanonicalName(canonicalName), canonicalName));
|
|
}
|
|
|
|
switch (kind) {
|
|
case ReferenceNameKind.Unknown:
|
|
for (CanonicalName child in canonicalName.children) {
|
|
visit(child, ReferenceNameKind.Library);
|
|
}
|
|
break;
|
|
case ReferenceNameKind.Library:
|
|
addObject();
|
|
for (CanonicalName child in canonicalName.children) {
|
|
ReferenceNameKind childKind = ReferenceNameKind.Declaration;
|
|
if (CanonicalName.isSymbolicName(child.name)) {
|
|
childKind = ReferenceName.kindFromSymbolicName(child.name);
|
|
}
|
|
visit(child, childKind);
|
|
}
|
|
break;
|
|
case ReferenceNameKind.Declaration:
|
|
addObject();
|
|
for (CanonicalName child in canonicalName.children) {
|
|
visit(child, ReferenceName.kindFromSymbolicName(child.name));
|
|
}
|
|
break;
|
|
case ReferenceNameKind.Typedef:
|
|
case ReferenceNameKind.Function:
|
|
case ReferenceNameKind.Field:
|
|
case ReferenceNameKind.Getter:
|
|
case ReferenceNameKind.Setter:
|
|
if (canonicalName.childrenOrNull != null) {
|
|
// Private name
|
|
for (CanonicalName child in canonicalName.children) {
|
|
visit(child, kind);
|
|
}
|
|
} else {
|
|
addObject();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
visit(root, ReferenceNameKind.Unknown);
|
|
|
|
sortReferenceNames(map);
|
|
return map;
|
|
}
|
|
|
|
class ReferenceNameObject {
|
|
final ReferenceName referenceName;
|
|
final Object object;
|
|
|
|
ReferenceNameObject(this.referenceName, this.object);
|
|
}
|