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:
Konstantin Shcheglov 2019-12-17 18:42:26 +00:00 committed by commit-bot@chromium.org
parent c7965b2cf9
commit d940075e6c
2 changed files with 97 additions and 12 deletions

View file

@ -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);
}
}

View file

@ -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',