mirror of
https://github.com/dart-lang/sdk
synced 2024-10-02 23:59:16 +00:00
When building interfaces in legacy libraries, convert signatures from superinterfaces to legacy.
Change-Id: Ibcaea82b2825d37a5dc98ca1757af99e70e5b8d2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128578 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
c7965b2cf9
commit
d940075e6c
|
@ -5,8 +5,10 @@
|
|||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/dart/element/type_system.dart';
|
||||
import 'package:analyzer/src/dart/element/member.dart';
|
||||
import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
|
||||
import 'package:analyzer/src/generated/utilities_general.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
/// Description of a failure to find a valid override from superinterfaces.
|
||||
class Conflict {
|
||||
|
@ -94,7 +96,9 @@ class InheritanceManager3 {
|
|||
return Interface._empty;
|
||||
}
|
||||
|
||||
var typeSystem = classElement.library.typeSystem;
|
||||
var classLibrary = classElement.library;
|
||||
var isNonNullableByDefault = classLibrary.isNonNullableByDefault;
|
||||
var typeSystem = classLibrary.typeSystem;
|
||||
|
||||
Map<Name, List<ExecutableElement>> namedCandidates = {};
|
||||
List<Map<Name, ExecutableElement>> superImplemented = [];
|
||||
|
@ -109,15 +113,27 @@ class InheritanceManager3 {
|
|||
|
||||
for (var interface in type.interfaces) {
|
||||
var interfaceObj = getInterface(interface);
|
||||
_addCandidates(namedCandidates, interfaceObj);
|
||||
_addCandidates(
|
||||
namedCandidates,
|
||||
interfaceObj,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
);
|
||||
}
|
||||
|
||||
if (classElement.isMixin) {
|
||||
var superClassCandidates = <Name, List<ExecutableElement>>{};
|
||||
for (var constraint in type.superclassConstraints) {
|
||||
var interfaceObj = getInterface(constraint);
|
||||
_addCandidates(superClassCandidates, interfaceObj);
|
||||
_addCandidates(namedCandidates, interfaceObj);
|
||||
_addCandidates(
|
||||
superClassCandidates,
|
||||
interfaceObj,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
);
|
||||
_addCandidates(
|
||||
namedCandidates,
|
||||
interfaceObj,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
);
|
||||
}
|
||||
|
||||
implemented = {};
|
||||
|
@ -134,7 +150,11 @@ class InheritanceManager3 {
|
|||
} else {
|
||||
if (type.superclass != null) {
|
||||
superInterface = getInterface(type.superclass);
|
||||
_addCandidates(namedCandidates, superInterface);
|
||||
_addCandidates(
|
||||
namedCandidates,
|
||||
superInterface,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
);
|
||||
|
||||
implemented = superInterface.implemented;
|
||||
superImplemented.add(implemented);
|
||||
|
@ -145,7 +165,11 @@ class InheritanceManager3 {
|
|||
implementedForMixing = {};
|
||||
for (var mixin in type.mixins) {
|
||||
var interfaceObj = getInterface(mixin);
|
||||
_addCandidates(namedCandidates, interfaceObj);
|
||||
_addCandidates(
|
||||
namedCandidates,
|
||||
interfaceObj,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
);
|
||||
|
||||
implemented = <Name, ExecutableElement>{}
|
||||
..addAll(implemented)
|
||||
|
@ -261,23 +285,35 @@ class InheritanceManager3 {
|
|||
return interface._overridden[name];
|
||||
}
|
||||
|
||||
void _addCandidate(Map<Name, List<ExecutableElement>> namedCandidates,
|
||||
Name name, ExecutableElement candidate) {
|
||||
void _addCandidate(
|
||||
Map<Name, List<ExecutableElement>> namedCandidates,
|
||||
Name name,
|
||||
ExecutableElement candidate, {
|
||||
@required bool isNonNullableByDefault,
|
||||
}) {
|
||||
var candidates = namedCandidates[name];
|
||||
if (candidates == null) {
|
||||
candidates = <ExecutableElement>[];
|
||||
namedCandidates[name] = candidates;
|
||||
}
|
||||
|
||||
if (!isNonNullableByDefault) {
|
||||
candidate = Member.legacy(candidate);
|
||||
}
|
||||
|
||||
candidates.add(candidate);
|
||||
}
|
||||
|
||||
void _addCandidates(
|
||||
Map<Name, List<ExecutableElement>> namedCandidates, Interface interface) {
|
||||
Map<Name, List<ExecutableElement>> namedCandidates,
|
||||
Interface interface, {
|
||||
@required bool isNonNullableByDefault,
|
||||
}) {
|
||||
var map = interface.map;
|
||||
for (var name in map.keys) {
|
||||
var candidate = map[name];
|
||||
_addCandidate(namedCandidates, name, candidate);
|
||||
_addCandidate(namedCandidates, name, candidate,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1053,6 +1053,55 @@ class InheritanceManager3WithNnbdTest extends _InheritanceManager3Base {
|
|||
@override
|
||||
bool get typeToStringWithNullability => true;
|
||||
|
||||
test_getMember_optIn_inheritsOptIn() async {
|
||||
newFile('/test/lib/a.dart', content: r'''
|
||||
class A {
|
||||
int foo(int a, int? b) => 0;
|
||||
}
|
||||
''');
|
||||
await resolveTestCode('''
|
||||
import 'a.dart';
|
||||
class B extends A {
|
||||
int? bar(int a) => 0;
|
||||
}
|
||||
''');
|
||||
_assertGetMember(
|
||||
className: 'B',
|
||||
name: 'foo',
|
||||
expected: 'A.foo: int Function(int, int?)',
|
||||
);
|
||||
_assertGetMember(
|
||||
className: 'B',
|
||||
name: 'bar',
|
||||
expected: 'B.bar: int? Function(int)',
|
||||
);
|
||||
}
|
||||
|
||||
test_getMember_optIn_inheritsOptOut() async {
|
||||
newFile('/test/lib/a.dart', content: r'''
|
||||
// @dart = 2.6
|
||||
class A {
|
||||
int foo(int a, int b) => 0;
|
||||
}
|
||||
''');
|
||||
await resolveTestCode('''
|
||||
import 'a.dart';
|
||||
class B extends A {
|
||||
int? bar(int a) => 0;
|
||||
}
|
||||
''');
|
||||
_assertGetMember(
|
||||
className: 'B',
|
||||
name: 'foo',
|
||||
expected: 'A.foo: int* Function(int*, int*)*',
|
||||
);
|
||||
_assertGetMember(
|
||||
className: 'B',
|
||||
name: 'bar',
|
||||
expected: 'B.bar: int? Function(int)',
|
||||
);
|
||||
}
|
||||
|
||||
test_getMember_optOut_inheritsOptIn() async {
|
||||
newFile('/test/lib/a.dart', content: r'''
|
||||
class A {
|
||||
|
@ -1069,7 +1118,7 @@ class B extends A {
|
|||
_assertGetMember(
|
||||
className: 'B',
|
||||
name: 'foo',
|
||||
expected: 'A.foo: int Function(int, int?)',
|
||||
expected: 'A.foo: int* Function(int*, int*)*',
|
||||
);
|
||||
_assertGetMember(
|
||||
className: 'B',
|
||||
|
@ -1098,7 +1147,7 @@ class C extends B {}
|
|||
_assertGetMember(
|
||||
className: 'C',
|
||||
name: 'foo',
|
||||
expected: 'A.foo: int Function(int, int?)',
|
||||
expected: 'A.foo: int* Function(int*, int*)*',
|
||||
);
|
||||
_assertGetMember(
|
||||
className: 'C',
|
||||
|
|
Loading…
Reference in a new issue