mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
Extension type. Tests for type hierarchy.
Change-Id: Ic0e31bb13efd68a3413429d1ff9110bb9b268e2e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323432 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
5926a7301b
commit
bbc3dcbe30
|
@ -4307,7 +4307,7 @@ a:focus, a:hover {
|
|||
An enumeration of the kinds of elements.
|
||||
</p>
|
||||
|
||||
<dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_ExecutableFile">ExecutableFile: object</a></dt><dd>
|
||||
<dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">EXTENSION_TYPE</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_ExecutableFile">ExecutableFile: object</a></dt><dd>
|
||||
<p>
|
||||
A description of an executable file.
|
||||
</p>
|
||||
|
|
|
@ -64,6 +64,9 @@ ElementKind convertElementKind(engine.ElementKind kind) {
|
|||
if (kind == engine.ElementKind.EXTENSION) {
|
||||
return ElementKind.EXTENSION;
|
||||
}
|
||||
if (kind == engine.ElementKind.EXTENSION_TYPE) {
|
||||
return ElementKind.EXTENSION_TYPE;
|
||||
}
|
||||
if (kind == engine.ElementKind.FIELD) {
|
||||
return ElementKind.FIELD;
|
||||
}
|
||||
|
|
|
@ -184,6 +184,12 @@ class TypeHierarchyComputerHelper {
|
|||
}
|
||||
|
||||
ExecutableElement? findMemberElement(InterfaceElement clazz) {
|
||||
// Members of extension types don't override anything.
|
||||
// They redeclare, and resolved statically.
|
||||
if (pivotClass is ExtensionTypeElement || clazz is ExtensionTypeElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var pivotName = this.pivotName;
|
||||
if (pivotName == null) {
|
||||
return null;
|
||||
|
|
|
@ -442,6 +442,7 @@ final Matcher isElementDeclaration =
|
|||
/// ENUM
|
||||
/// ENUM_CONSTANT
|
||||
/// EXTENSION
|
||||
/// EXTENSION_TYPE
|
||||
/// FIELD
|
||||
/// FILE
|
||||
/// FUNCTION
|
||||
|
@ -472,6 +473,7 @@ final Matcher isElementKind = MatchesEnum('ElementKind', [
|
|||
'ENUM',
|
||||
'ENUM_CONSTANT',
|
||||
'EXTENSION',
|
||||
'EXTENSION_TYPE',
|
||||
'FIELD',
|
||||
'FILE',
|
||||
'FUNCTION',
|
||||
|
|
|
@ -524,6 +524,10 @@ class ElementKindTest {
|
|||
ElementKind.COMPILATION_UNIT);
|
||||
expect(convertElementKind(engine.ElementKind.CONSTRUCTOR),
|
||||
ElementKind.CONSTRUCTOR);
|
||||
expect(convertElementKind(engine.ElementKind.EXTENSION),
|
||||
ElementKind.EXTENSION);
|
||||
expect(convertElementKind(engine.ElementKind.EXTENSION_TYPE),
|
||||
ElementKind.EXTENSION_TYPE);
|
||||
expect(convertElementKind(engine.ElementKind.FIELD), ElementKind.FIELD);
|
||||
expect(
|
||||
convertElementKind(engine.ElementKind.FUNCTION), ElementKind.FUNCTION);
|
||||
|
@ -555,6 +559,10 @@ class ElementKindTest {
|
|||
expect(ElementKind(ElementKind.COMPILATION_UNIT.name),
|
||||
ElementKind.COMPILATION_UNIT);
|
||||
expect(ElementKind(ElementKind.CONSTRUCTOR.name), ElementKind.CONSTRUCTOR);
|
||||
expect(ElementKind(ElementKind.CONSTRUCTOR.name), ElementKind.CONSTRUCTOR);
|
||||
expect(ElementKind(ElementKind.EXTENSION.name), ElementKind.EXTENSION);
|
||||
expect(ElementKind(ElementKind.EXTENSION_TYPE.name),
|
||||
ElementKind.EXTENSION_TYPE);
|
||||
expect(ElementKind(ElementKind.FIELD.name), ElementKind.FIELD);
|
||||
expect(ElementKind(ElementKind.FUNCTION.name), ElementKind.FUNCTION);
|
||||
expect(ElementKind(ElementKind.FUNCTION_TYPE_ALIAS.name),
|
||||
|
|
|
@ -246,7 +246,6 @@ class EnumTest {
|
|||
engine.ElementKind.EXPORT: ElementKind.UNKNOWN,
|
||||
engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.FUNCTION_TYPE_ALIAS,
|
||||
engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
|
||||
engine.ElementKind.EXTENSION_TYPE: ElementKind.UNKNOWN,
|
||||
engine.ElementKind.LIBRARY_AUGMENTATION: ElementKind.UNKNOWN,
|
||||
engine.ElementKind.NAME: ElementKind.UNKNOWN,
|
||||
engine.ElementKind.NEVER: ElementKind.UNKNOWN,
|
||||
|
|
|
@ -1354,6 +1354,177 @@ enum E with M {
|
|||
]);
|
||||
}
|
||||
|
||||
Future<void> test_extensionType_implements_class() async {
|
||||
addTestFile('''
|
||||
class A {}
|
||||
class B extends A {}
|
||||
extension type E(B it) implements A {}
|
||||
''');
|
||||
var items = await _getTypeHierarchy('E(B it)');
|
||||
expect(_toJson(items), [
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'EXTENSION_TYPE',
|
||||
'name': 'E',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [1],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'CLASS',
|
||||
'name': 'A',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'superclass': 2,
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'CLASS',
|
||||
'name': 'Object',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_extensionType_implements_class2() async {
|
||||
addTestFile('''
|
||||
class A {}
|
||||
extension type E(A it) implements A {}
|
||||
''');
|
||||
var items = await _getTypeHierarchy('A {}');
|
||||
expect(_toJson(items), [
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'CLASS',
|
||||
'name': 'A',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'superclass': 1,
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': [2]
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'CLASS',
|
||||
'name': 'Object',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'EXTENSION_TYPE',
|
||||
'name': 'E',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'superclass': 0,
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_extensionType_implements_extensionType() async {
|
||||
addTestFile('''
|
||||
class A {}
|
||||
extension type E1(A it) {}
|
||||
extension type E2(A it) implements E1 {}
|
||||
''');
|
||||
var items = await _getTypeHierarchy('E2(A it)');
|
||||
expect(_toJson(items), [
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'EXTENSION_TYPE',
|
||||
'name': 'E2',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [1],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'EXTENSION_TYPE',
|
||||
'name': 'E1',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [2],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
},
|
||||
{
|
||||
'classElement': {
|
||||
'kind': 'CLASS',
|
||||
'name': 'Object',
|
||||
'location': anything,
|
||||
'flags': 0
|
||||
},
|
||||
'interfaces': [],
|
||||
'mixins': [],
|
||||
'subclasses': []
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> test_extensionType_member_method() async {
|
||||
addTestFile('''
|
||||
class A {
|
||||
void test() {} // in A
|
||||
}
|
||||
extension type E(A it) implements A {
|
||||
void test() {} // in E
|
||||
}
|
||||
''');
|
||||
var items = await _getTypeHierarchy('test() {} // in E');
|
||||
var itemE = items[0];
|
||||
var itemA = items[itemE.interfaces.single];
|
||||
expect(itemA.classElement.name, 'A');
|
||||
expect(itemE.classElement.name, 'E');
|
||||
expect(itemA.memberElement, isNull);
|
||||
expect(itemE.memberElement, isNull);
|
||||
}
|
||||
|
||||
Future<void> test_extensionType_member_method2() async {
|
||||
addTestFile('''
|
||||
class A {
|
||||
void test() {} // in A
|
||||
}
|
||||
extension type E(A it) implements A {
|
||||
void test() {} // in E
|
||||
}
|
||||
''');
|
||||
var items = await _getTypeHierarchy('test() {} // in A');
|
||||
var itemA = items[0];
|
||||
var itemE = items[itemA.subclasses.single];
|
||||
expect(itemA.classElement.name, 'A');
|
||||
expect(itemE.classElement.name, 'E');
|
||||
expect(
|
||||
itemA.memberElement!.location!.offset, findOffset('test() {} // in A'));
|
||||
expect(itemE.memberElement, isNull);
|
||||
}
|
||||
|
||||
void _assertMember(TypeHierarchyItem item, String search) {
|
||||
expect(item.memberElement!.location!.offset, findOffset(search));
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ public class ElementKind {
|
|||
|
||||
public static final String EXTENSION = "EXTENSION";
|
||||
|
||||
public static final String EXTENSION_TYPE = "EXTENSION_TYPE";
|
||||
|
||||
public static final String FIELD = "FIELD";
|
||||
|
||||
public static final String FILE = "FILE";
|
||||
|
|
|
@ -1409,6 +1409,7 @@ class Element implements HasToJson {
|
|||
/// ENUM
|
||||
/// ENUM_CONSTANT
|
||||
/// EXTENSION
|
||||
/// EXTENSION_TYPE
|
||||
/// FIELD
|
||||
/// FILE
|
||||
/// FUNCTION
|
||||
|
@ -1450,6 +1451,8 @@ class ElementKind implements Enum {
|
|||
|
||||
static const ElementKind EXTENSION = ElementKind._('EXTENSION');
|
||||
|
||||
static const ElementKind EXTENSION_TYPE = ElementKind._('EXTENSION_TYPE');
|
||||
|
||||
static const ElementKind FIELD = ElementKind._('FIELD');
|
||||
|
||||
static const ElementKind FILE = ElementKind._('FILE');
|
||||
|
@ -1503,6 +1506,7 @@ class ElementKind implements Enum {
|
|||
ENUM,
|
||||
ENUM_CONSTANT,
|
||||
EXTENSION,
|
||||
EXTENSION_TYPE,
|
||||
FIELD,
|
||||
FILE,
|
||||
FUNCTION,
|
||||
|
@ -1548,6 +1552,8 @@ class ElementKind implements Enum {
|
|||
return ENUM_CONSTANT;
|
||||
case 'EXTENSION':
|
||||
return EXTENSION;
|
||||
case 'EXTENSION_TYPE':
|
||||
return EXTENSION_TYPE;
|
||||
case 'FIELD':
|
||||
return FIELD;
|
||||
case 'FILE':
|
||||
|
|
|
@ -1355,7 +1355,7 @@ a:focus, a:hover {
|
|||
An enumeration of the kinds of elements.
|
||||
</p>
|
||||
|
||||
<dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_FilePath">FilePath: String</a></dt><dd>
|
||||
<dl><dt class="value">CLASS</dt><dt class="value">CLASS_TYPE_ALIAS</dt><dt class="value">COMPILATION_UNIT</dt><dt class="value">CONSTRUCTOR</dt><dt class="value">CONSTRUCTOR_INVOCATION</dt><dt class="value">ENUM</dt><dt class="value">ENUM_CONSTANT</dt><dt class="value">EXTENSION</dt><dt class="value">EXTENSION_TYPE</dt><dt class="value">FIELD</dt><dt class="value">FILE</dt><dt class="value">FUNCTION</dt><dt class="value">FUNCTION_INVOCATION</dt><dt class="value">FUNCTION_TYPE_ALIAS</dt><dt class="value">GETTER</dt><dt class="value">LABEL</dt><dt class="value">LIBRARY</dt><dt class="value">LOCAL_VARIABLE</dt><dt class="value">METHOD</dt><dt class="value">MIXIN</dt><dt class="value">PARAMETER</dt><dt class="value">PREFIX</dt><dt class="value">SETTER</dt><dt class="value">TOP_LEVEL_VARIABLE</dt><dt class="value">TYPE_ALIAS</dt><dt class="value">TYPE_PARAMETER</dt><dt class="value">UNIT_TEST_GROUP</dt><dt class="value">UNIT_TEST_TEST</dt><dt class="value">UNKNOWN</dt></dl></dd><dt class="typeDefinition"><a name="type_FilePath">FilePath: String</a></dt><dd>
|
||||
|
||||
<p>
|
||||
The absolute, normalized path of a file.
|
||||
|
|
|
@ -1409,6 +1409,7 @@ class Element implements HasToJson {
|
|||
/// ENUM
|
||||
/// ENUM_CONSTANT
|
||||
/// EXTENSION
|
||||
/// EXTENSION_TYPE
|
||||
/// FIELD
|
||||
/// FILE
|
||||
/// FUNCTION
|
||||
|
@ -1450,6 +1451,8 @@ class ElementKind implements Enum {
|
|||
|
||||
static const ElementKind EXTENSION = ElementKind._('EXTENSION');
|
||||
|
||||
static const ElementKind EXTENSION_TYPE = ElementKind._('EXTENSION_TYPE');
|
||||
|
||||
static const ElementKind FIELD = ElementKind._('FIELD');
|
||||
|
||||
static const ElementKind FILE = ElementKind._('FILE');
|
||||
|
@ -1503,6 +1506,7 @@ class ElementKind implements Enum {
|
|||
ENUM,
|
||||
ENUM_CONSTANT,
|
||||
EXTENSION,
|
||||
EXTENSION_TYPE,
|
||||
FIELD,
|
||||
FILE,
|
||||
FUNCTION,
|
||||
|
@ -1548,6 +1552,8 @@ class ElementKind implements Enum {
|
|||
return ENUM_CONSTANT;
|
||||
case 'EXTENSION':
|
||||
return EXTENSION;
|
||||
case 'EXTENSION_TYPE':
|
||||
return EXTENSION_TYPE;
|
||||
case 'FIELD':
|
||||
return FIELD;
|
||||
case 'FILE':
|
||||
|
|
|
@ -254,6 +254,7 @@ final Matcher isElement = LazyMatcher(() => MatchesJsonObject('Element', {
|
|||
/// ENUM
|
||||
/// ENUM_CONSTANT
|
||||
/// EXTENSION
|
||||
/// EXTENSION_TYPE
|
||||
/// FIELD
|
||||
/// FILE
|
||||
/// FUNCTION
|
||||
|
@ -284,6 +285,7 @@ final Matcher isElementKind = MatchesEnum('ElementKind', [
|
|||
'ENUM',
|
||||
'ENUM_CONSTANT',
|
||||
'EXTENSION',
|
||||
'EXTENSION_TYPE',
|
||||
'FIELD',
|
||||
'FILE',
|
||||
'FUNCTION',
|
||||
|
|
|
@ -601,6 +601,7 @@
|
|||
<value><code>ENUM</code></value>
|
||||
<value><code>ENUM_CONSTANT</code></value>
|
||||
<value><code>EXTENSION</code></value>
|
||||
<value><code>EXTENSION_TYPE</code></value>
|
||||
<value><code>FIELD</code></value>
|
||||
<value><code>FILE</code></value>
|
||||
<value><code>FUNCTION</code></value>
|
||||
|
|
Loading…
Reference in a new issue