Use 'augmented' for ClassHierarchy.

Change-Id: Id4b9fb27990dd02f4c1d94faf11c6e25f056a5a7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/313221
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2023-07-17 21:12:49 +00:00 committed by Commit Queue
parent 82b25b2703
commit 87c49d9848
3 changed files with 144 additions and 5 deletions

View file

@ -32,8 +32,16 @@ class ClassHierarchy {
}
_Hierarchy _getHierarchy(InterfaceElement element) {
var hierarchy = _map[element];
if (element.isAugmentation) {
throw StateError('Expected a declaration, not augmentations.');
}
final augmented = element.augmented;
if (augmented == null) {
throw StateError('Declarations always have augmented state.');
}
var hierarchy = _map[element];
if (hierarchy != null) {
return hierarchy;
}
@ -67,15 +75,15 @@ class ClassHierarchy {
}
append(element.supertype);
if (element is MixinElement) {
for (var type in element.superclassConstraints) {
if (augmented is AugmentedMixinElement) {
for (var type in augmented.superclassConstraints) {
append(type);
}
}
for (var type in element.interfaces) {
for (var type in augmented.interfaces) {
append(type);
}
for (var type in element.mixins) {
for (var type in augmented.mixins) {
append(type);
}

View file

@ -16,6 +16,7 @@ import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:test/test.dart';
mixin ElementsTypesMixin {
InterfaceType get boolNone {
@ -164,6 +165,7 @@ mixin ElementsTypesMixin {
ClassElementImpl class_({
required String name,
bool isAbstract = false,
bool isAugmentation = false,
bool isSealed = false,
InterfaceType? superType,
List<TypeParameterElement> typeParameters = const [],
@ -173,6 +175,7 @@ mixin ElementsTypesMixin {
}) {
var element = ClassElementImpl(name, 0);
element.isAbstract = isAbstract;
element.isAugmentation = isAugmentation;
element.isSealed = isSealed;
element.enclosingElement = testLibrary.definingCompilationUnit;
element.typeParameters = typeParameters;
@ -476,11 +479,13 @@ mixin ElementsTypesMixin {
MixinElementImpl mixin_({
required String name,
bool isAugmentation = false,
List<TypeParameterElement> typeParameters = const [],
List<InterfaceType>? constraints,
List<InterfaceType> interfaces = const [],
}) {
var element = MixinElementImpl(name, 0);
element.isAugmentation = isAugmentation;
element.enclosingElement = testLibrary.definingCompilationUnit;
element.typeParameters = typeParameters;
element.superclassConstraints = constraints ?? [typeProvider.objectType];
@ -735,3 +740,48 @@ class _MockSource implements Source {
@override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
extension ClassElementImplExtension on ClassElementImpl {
void addAugmentations(List<ClassElementImpl> augmentations) {
expect(this.augmented, TypeMatcher<NotAugmentedClassElementImpl>());
final augmented = AugmentedClassElementImpl(this);
augmentedInternal = augmented;
var augmentationTarget = this;
for (final augmentation in augmentations) {
expect(augmentation.isAugmentation, isTrue);
augmentationTarget.augmentation = augmentation;
augmentation.augmentationTarget = augmentationTarget;
augmentationTarget = augmentation;
expect(augmentation.typeParameters, isEmpty,
reason: 'Not supported in tests');
augmented.interfaces.addAll(augmentation.interfaces);
augmented.mixins.addAll(augmentation.mixins);
}
}
}
extension MixinElementImplExtension on MixinElementImpl {
void addAugmentations(List<MixinElementImpl> augmentations) {
expect(this.augmented, TypeMatcher<NotAugmentedMixinElementImpl>());
final augmented = AugmentedMixinElementImpl(this);
augmentedInternal = augmented;
var augmentationTarget = this;
for (final augmentation in augmentations) {
expect(augmentation.isAugmentation, isTrue);
augmentationTarget.augmentation = augmentation;
augmentation.augmentationTarget = augmentationTarget;
augmentationTarget = augmentation;
expect(augmentation.typeParameters, isEmpty,
reason: 'Not supported in tests');
augmented.superclassConstraints
.addAll(augmentation.superclassConstraints);
augmented.interfaces.addAll(augmentation.interfaces);
}
}
}

View file

@ -9,6 +9,7 @@ import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/elements_types_mixin.dart';
import '../../../generated/type_system_base.dart';
import 'string_types.dart';
@ -2620,6 +2621,46 @@ class SubtypeTest extends _SubtypingTestBase with StringTypes {
);
}
test_interfaceType_class_augmented_interfaces() {
final A = class_(name: 'A');
final I = class_(name: 'I');
final A1 = class_(
name: 'A',
isAugmentation: true,
interfaces: [
interfaceTypeNone(I),
],
);
A.addAugmentations([A1]);
final A_none = interfaceTypeNone(A);
final I_none = interfaceTypeNone(I);
isSubtype(A_none, I_none, strT0: 'A', strT1: 'I');
isNotSubtype(I_none, A_none, strT0: 'I', strT1: 'A');
}
test_interfaceType_class_augmented_mixins() {
final A = class_(name: 'A');
final M = mixin_(name: 'M');
final A1 = class_(
name: 'A',
isAugmentation: true,
mixins: [
interfaceTypeNone(M),
],
);
A.addAugmentations([A1]);
final A_none = interfaceTypeNone(A);
final M_none = interfaceTypeNone(M);
isSubtype(A_none, M_none, strT0: 'A', strT1: 'M');
isNotSubtype(M_none, A_none, strT0: 'M', strT1: 'A');
}
test_interfaceType_contravariant() {
var T = typeParameter('T', variance: Variance.contravariant);
var A = class_(name: 'A', typeParameters: [T]);
@ -2677,6 +2718,46 @@ class SubtypeTest extends _SubtypingTestBase with StringTypes {
isNotSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
}
test_interfaceType_mixin_augmented_interfaces() {
final M = mixin_(name: 'M');
final I = class_(name: 'I');
final M1 = mixin_(
name: 'M1',
isAugmentation: true,
interfaces: [
interfaceTypeNone(I),
],
);
M.addAugmentations([M1]);
final M_none = interfaceTypeNone(M);
final I_none = interfaceTypeNone(I);
isSubtype(M_none, I_none, strT0: 'M', strT1: 'I');
isNotSubtype(I_none, M_none, strT0: 'I', strT1: 'M');
}
test_interfaceType_mixin_augmented_superclassConstraints() {
final M = mixin_(name: 'M');
final C = class_(name: 'C');
final M1 = mixin_(
name: 'M1',
isAugmentation: true,
constraints: [
interfaceTypeNone(C),
],
);
M.addAugmentations([M1]);
final M_none = interfaceTypeNone(M);
final C_none = interfaceTypeNone(C);
isSubtype(M_none, C_none, strT0: 'M', strT1: 'C');
isNotSubtype(C_none, M_none, strT0: 'C', strT1: 'M');
}
test_invalidType() {
isSubtype2('InvalidType', 'int');
isSubtype2('int', 'InvalidType');