Add Element.aliasedType to the protocol.

R=brianwilkerson@google.com

Change-Id: I95fb2c9d50096f90913c4d6670ce0841095fe6a0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/181443
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-01-27 23:27:21 +00:00 committed by commit-bot@chromium.org
parent 974926e468
commit 5c426d8d43
19 changed files with 249 additions and 87 deletions

View file

@ -3764,6 +3764,12 @@ a:focus, a:hover {
The type parameter list for the element. If the element doesn't have
type parameters, this field will not be defined.
</p>
</dd><dt class="field"><b>aliasedType: String<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
If the element is a type alias, this field is the aliased type.
Otherwise this field will not be defined.
</p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_ElementDeclaration">ElementDeclaration: object</a></dt><dd>
<p>
A declaration - top-level (class, field, etc) or a class member (method,

View file

@ -10,25 +10,29 @@ import 'package:path/path.dart' as pathos;
/// Return a protocol [Element] corresponding to the given [engine.Element].
Element convertElement(engine.Element element) {
var kind = convertElementToElementKind(element);
var name = getElementDisplayName(element);
var elementTypeParameters = _getTypeParametersString(element);
var aliasedType = getAliasedTypeString(element);
var elementParameters = _getParametersString(element);
var elementReturnType = getReturnTypeString(element);
var kind = convertElementToElementKind(element);
return Element(
kind,
name,
Element.makeFlags(
isPrivate: element.isPrivate,
isDeprecated: element.hasDeprecated,
isAbstract: _isAbstract(element),
isConst: _isConst(element),
isFinal: _isFinal(element),
isStatic: _isStatic(element)),
location: newLocation_fromElement(element),
typeParameters: elementTypeParameters,
parameters: elementParameters,
returnType: elementReturnType);
kind,
name,
Element.makeFlags(
isPrivate: element.isPrivate,
isDeprecated: element.hasDeprecated,
isAbstract: _isAbstract(element),
isConst: _isConst(element),
isFinal: _isFinal(element),
isStatic: _isStatic(element),
),
location: newLocation_fromElement(element),
typeParameters: elementTypeParameters,
aliasedType: aliasedType,
parameters: elementParameters,
returnType: elementReturnType,
);
}
/// Return a protocol [ElementKind] corresponding to the given
@ -229,7 +233,15 @@ bool _isStatic(engine.Element element) {
/// Sort required named parameters before optional ones.
int _preferRequiredParams(
engine.ParameterElement e1, engine.ParameterElement e2) {
var rank1 = (e1.isRequiredNamed || e1.hasRequired) ? 0 : !e1.isNamed ? -1 : 1;
var rank2 = (e2.isRequiredNamed || e2.hasRequired) ? 0 : !e2.isNamed ? -1 : 1;
var rank1 = (e1.isRequiredNamed || e1.hasRequired)
? 0
: !e1.isNamed
? -1
: 1;
var rank2 = (e2.isRequiredNamed || e2.hasRequired)
? 0
: !e2.isNamed
? -1
: 1;
return rank1 - rank2;
}

View file

@ -46,6 +46,14 @@ void doSourceChange_addSourceEdit(
change.addEdit(file, isNewFile ? -1 : 0, edit);
}
String getAliasedTypeString(engine.Element element) {
if (element is engine.TypeAliasElement) {
var aliasedType = element.aliasedType;
return aliasedType.getDisplayString(withNullability: false);
}
return null;
}
String getReturnTypeString(engine.Element element) {
if (element is engine.ExecutableElement) {
if (element.kind == engine.ElementKind.SETTER) {
@ -63,12 +71,9 @@ String getReturnTypeString(engine.Element element) {
if (aliasedType is FunctionType) {
var returnType = aliasedType.returnType;
return returnType.getDisplayString(withNullability: false);
} else {
return aliasedType.getDisplayString(withNullability: false);
}
} else {
return null;
}
return null;
}
/// Translates engine errors through the ErrorProcessor.

View file

@ -379,6 +379,7 @@ final Matcher isDiagnosticMessage = LazyMatcher(() => MatchesJsonObject(
/// "parameters": optional String
/// "returnType": optional String
/// "typeParameters": optional String
/// "aliasedType": optional String
/// }
final Matcher isElement = LazyMatcher(() => MatchesJsonObject('Element', {
'kind': isElementKind,
@ -388,7 +389,8 @@ final Matcher isElement = LazyMatcher(() => MatchesJsonObject('Element', {
'location': isLocation,
'parameters': isString,
'returnType': isString,
'typeParameters': isString
'typeParameters': isString,
'aliasedType': isString
}));
/// ElementDeclaration

View file

@ -381,8 +381,9 @@ typedef F<T> = Map<int, T>;
expect(location.startLine, 1);
expect(location.startColumn, 9);
}
expect(element.aliasedType, 'Map<int, T>');
expect(element.parameters, isNull);
expect(element.returnType, 'Map<int, T>');
expect(element.returnType, isNull);
expect(element.flags, 0);
}

View file

@ -107,8 +107,10 @@ class CombinatorContributorTest extends DartCompletionContributorTest {
assertSuggestFunction('F1', 'PB',
kind: CompletionSuggestionKind.IDENTIFIER);
assertSuggestClass('Clz', kind: CompletionSuggestionKind.IDENTIFIER);
assertSuggestTypeAlias('F2', null,
kind: CompletionSuggestionKind.IDENTIFIER);
assertSuggestTypeAlias('F2',
kind: CompletionSuggestionKind.IDENTIFIER,
aliasedType: 'dynamic Function(int)',
returnType: 'dynamic');
assertNotSuggested('C');
assertNotSuggested('D');
assertNotSuggested('X');

View file

@ -501,14 +501,17 @@ abstract class _BaseDartCompletionContributorTest extends AbstractContextTest
}
CompletionSuggestion assertSuggestTypeAlias(
String name,
String returnType, {
String name, {
String aliasedType,
String returnType,
bool isDeprecated = false,
CompletionSuggestionKind kind = CompletionSuggestionKind.INVOCATION,
}) {
var cs = assertSuggest(name, csKind: kind, isDeprecated: isDeprecated);
if (returnType != null) {
expect(cs.returnType, returnType);
} else if (aliasedType != null) {
// Just to don't fall into the next 'if'.
} else if (isNullExpectedReturnTypeConsideredDynamic) {
expect(cs.returnType, 'dynamic');
} else {
@ -524,7 +527,8 @@ abstract class _BaseDartCompletionContributorTest extends AbstractContextTest
// expect(param, isNotNull);
// expect(param[0], equals('('));
// expect(param[param.length - 1], equals(')'));
expect(element.returnType, equals(returnType ?? 'dynamic'));
expect(element.aliasedType, aliasedType);
expect(element.returnType, returnType);
// TODO (danrubel) Determine why param info is missing
// assertHasParameterInfo(cs);
return cs;

View file

@ -2400,7 +2400,8 @@ class B extends A {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -2430,7 +2431,8 @@ class B extends A {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -2461,7 +2463,8 @@ class B extends A {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -2498,7 +2501,8 @@ main() {
}
''');
await computeSuggestions();
assertSuggestTypeAlias('F', 'void');
assertSuggestTypeAlias('F',
aliasedType: 'void Function()', returnType: 'void');
}
Future<void> test_functionTypeAlias_old() async {
@ -2513,7 +2517,8 @@ main() {
}
''');
await computeSuggestions();
assertSuggestTypeAlias('F', 'void');
assertSuggestTypeAlias('F',
aliasedType: 'void Function()', returnType: 'void');
}
Future<void> test_IfStatement() async {
@ -2914,7 +2919,8 @@ main() {
// in which case suggestions will have null (unresolved) returnType
assertSuggestTopLevelVar('T1', null);
assertSuggestFunction('F1', null);
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -3178,7 +3184,8 @@ main() {
// to be resolved.
assertSuggestTopLevelVar('T1', /* null */ 'int');
assertSuggestFunction('F1', /* null */ 'dynamic');
assertSuggestTypeAlias('D1', /* null */ 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -3477,7 +3484,8 @@ class B {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -3506,7 +3514,8 @@ class B {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -3535,7 +3544,8 @@ class B {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -3566,7 +3576,8 @@ class B {
assertSuggestClass('Object');
assertNotSuggested('T1');
assertNotSuggested('F1');
assertSuggestTypeAlias('D1', 'dynamic');
assertSuggestTypeAlias('D1',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
@ -4611,7 +4622,8 @@ typedef void F(^);
expect(replacementLength, 0);
assertSuggestClass('Object');
assertSuggestClass('C1');
assertSuggestTypeAlias('T1', 'String');
assertSuggestTypeAlias('T1',
aliasedType: 'String Function(int)', returnType: 'String');
assertNotSuggested('C2');
assertNotSuggested('T2');
assertNotSuggested('F1');

View file

@ -238,9 +238,11 @@ main() {
expect(replacementLength, 0);
assertSuggestClass('X');
assertSuggestClass('Y');
assertSuggestTypeAlias('TypeAliasLegacy', 'void');
assertSuggestTypeAlias('TypeAliasFunctionType', 'void');
assertSuggestTypeAlias('TypeAliasInterfaceType', 'List<int>');
assertSuggestTypeAlias('TypeAliasLegacy',
aliasedType: 'void Function()', returnType: 'void');
assertSuggestTypeAlias('TypeAliasFunctionType',
aliasedType: 'void Function()', returnType: 'void');
assertSuggestTypeAlias('TypeAliasInterfaceType', aliasedType: 'List<int>');
assertNotSuggested('T1');
assertNotSuggested('T2');
assertNotSuggested('Object');

View file

@ -229,9 +229,11 @@ void f() {^}
}
assertSuggestFunction('af', 'int');
assertSuggestTopLevelVar('m', null);
assertSuggestTypeAlias('t1', null);
assertSuggestTypeAlias('t2', 'void');
assertSuggestTypeAlias('t3', 'List<int>');
assertSuggestTypeAlias('t1',
aliasedType: 'dynamic Function(int)', returnType: 'dynamic');
assertSuggestTypeAlias('t2',
aliasedType: 'void Function(int)', returnType: 'void');
assertSuggestTypeAlias('t3', aliasedType: 'List<int>');
assertNotSuggested('a1');
assertNotSuggested('a2');
// Suggested by LocalConstructorContributor
@ -274,7 +276,8 @@ void f() {^}
}
assertSuggestFunction('bf', 'int');
assertSuggestTopLevelVar('n', null);
assertSuggestTypeAlias('t1', null);
assertSuggestTypeAlias('t1',
aliasedType: 'dynamic Function(int)', returnType: 'dynamic');
assertNotSuggested('b1');
assertNotSuggested('b2');
// Suggested by ConstructorContributor

View file

@ -2588,7 +2588,8 @@ class C {foo(){^} void bar() {}}''');
assertSuggestClass('C');
assertSuggestMethod('foo', 'C', null);
assertSuggestMethod('bar', 'C', 'void');
assertSuggestTypeAlias('F2', 'int');
assertSuggestTypeAlias('F2',
aliasedType: 'int Function(int)', returnType: 'int');
assertSuggestClass('Clz');
assertSuggestClass('C');
assertNotSuggested('x');
@ -3242,7 +3243,8 @@ class C2 { }
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -3272,7 +3274,8 @@ class C2 { }
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -3303,7 +3306,8 @@ class C2 { }
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -3870,7 +3874,8 @@ main() {String name; print("hello \${^}");}''');
assertNotSuggested('C1');
assertSuggestTopLevelVar('T2', 'int');
assertSuggestFunction('F2', null);
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertSuggestLocalVariable('name', 'String');
}
@ -4218,7 +4223,8 @@ foo = {^''');
assertNotSuggested('C1');
assertSuggestTopLevelVar('T2', 'int');
assertSuggestFunction('F2', null);
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
}
@ -4767,7 +4773,8 @@ class C2 {^ zoo(z) { } String name; }''');
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -4796,7 +4803,8 @@ class C2 {/* */ ^ zoo(z) { } String name; }''');
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -4825,7 +4833,8 @@ class C2 {/** */ ^ zoo(z) { } String name; }''');
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -4856,7 +4865,8 @@ class C2 {
assertNotSuggested('C1');
assertNotSuggested('T2');
assertNotSuggested('F2');
assertSuggestTypeAlias('D2', 'dynamic');
assertSuggestTypeAlias('D2',
aliasedType: 'dynamic Function()', returnType: 'dynamic');
assertSuggestClass('C2');
assertNotSuggested('name');
}
@ -6035,7 +6045,8 @@ main() {
}
''');
await computeSuggestions();
assertSuggestTypeAlias('F', 'void');
assertSuggestTypeAlias('F',
aliasedType: 'void Function()', returnType: 'void');
}
Future<void> test_typeAlias_interfaceType() async {
@ -6046,7 +6057,7 @@ main() {
}
''');
await computeSuggestions();
assertSuggestTypeAlias('F', 'List<int>');
assertSuggestTypeAlias('F', aliasedType: 'List<int>');
}
Future<void> test_typeAlias_legacy() async {
@ -6057,7 +6068,8 @@ main() {
}
''');
await computeSuggestions();
assertSuggestTypeAlias('F', 'void');
assertSuggestTypeAlias('F',
aliasedType: 'void Function()', returnType: 'void');
}
Future<void> test_TypeArgumentList() async {
@ -6081,7 +6093,8 @@ main() { C<^> c; }''');
assertNotSuggested('C1');
assertNotSuggested('T1');
assertSuggestClass('C2');
assertSuggestTypeAlias('T2', 'int');
assertSuggestTypeAlias('T2',
aliasedType: 'int Function(int)', returnType: 'int');
assertNotSuggested('F1');
assertNotSuggested('F2');
}

View file

@ -94,10 +94,16 @@ public class Element {
*/
private final String typeParameters;
/**
* If the element is a type alias, this field is the aliased type. Otherwise this field will not be
* defined.
*/
private final String aliasedType;
/**
* Constructor for {@link Element}.
*/
public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters) {
public Element(String kind, String name, Location location, int flags, String parameters, String returnType, String typeParameters, String aliasedType) {
this.kind = kind;
this.name = name;
this.location = location;
@ -105,6 +111,7 @@ public class Element {
this.parameters = parameters;
this.returnType = returnType;
this.typeParameters = typeParameters;
this.aliasedType = aliasedType;
}
@Override
@ -118,7 +125,8 @@ public class Element {
other.flags == flags &&
ObjectUtilities.equals(other.parameters, parameters) &&
ObjectUtilities.equals(other.returnType, returnType) &&
ObjectUtilities.equals(other.typeParameters, typeParameters);
ObjectUtilities.equals(other.typeParameters, typeParameters) &&
ObjectUtilities.equals(other.aliasedType, aliasedType);
}
return false;
}
@ -131,7 +139,8 @@ public class Element {
String parameters = jsonObject.get("parameters") == null ? null : jsonObject.get("parameters").getAsString();
String returnType = jsonObject.get("returnType") == null ? null : jsonObject.get("returnType").getAsString();
String typeParameters = jsonObject.get("typeParameters") == null ? null : jsonObject.get("typeParameters").getAsString();
return new Element(kind, name, location, flags, parameters, returnType, typeParameters);
String aliasedType = jsonObject.get("aliasedType") == null ? null : jsonObject.get("aliasedType").getAsString();
return new Element(kind, name, location, flags, parameters, returnType, typeParameters, aliasedType);
}
public static List<Element> fromJsonArray(JsonArray jsonArray) {
@ -146,6 +155,14 @@ public class Element {
return list;
}
/**
* If the element is a type alias, this field is the aliased type. Otherwise this field will not be
* defined.
*/
public String getAliasedType() {
return aliasedType;
}
/**
* A bit-map containing the following flags:
*
@ -217,6 +234,7 @@ public class Element {
builder.append(parameters);
builder.append(returnType);
builder.append(typeParameters);
builder.append(aliasedType);
return builder.toHashCode();
}
@ -261,6 +279,9 @@ public class Element {
if (typeParameters != null) {
jsonObject.addProperty("typeParameters", typeParameters);
}
if (aliasedType != null) {
jsonObject.addProperty("aliasedType", aliasedType);
}
return jsonObject;
}
@ -281,7 +302,9 @@ public class Element {
builder.append("returnType=");
builder.append(returnType + ", ");
builder.append("typeParameters=");
builder.append(typeParameters);
builder.append(typeParameters + ", ");
builder.append("aliasedType=");
builder.append(aliasedType);
builder.append("]");
return builder.toString();
}

View file

@ -1435,6 +1435,7 @@ class DiagnosticMessage implements HasToJson {
/// "parameters": optional String
/// "returnType": optional String
/// "typeParameters": optional String
/// "aliasedType": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
@ -1477,6 +1478,8 @@ class Element implements HasToJson {
String _typeParameters;
String _aliasedType;
/// The kind of the element.
ElementKind get kind => _kind;
@ -1566,11 +1569,22 @@ class Element implements HasToJson {
_typeParameters = value;
}
/// If the element is a type alias, this field is the aliased type. Otherwise
/// this field will not be defined.
String get aliasedType => _aliasedType;
/// If the element is a type alias, this field is the aliased type. Otherwise
/// this field will not be defined.
set aliasedType(String value) {
_aliasedType = value;
}
Element(ElementKind kind, String name, int flags,
{Location location,
String parameters,
String returnType,
String typeParameters}) {
String typeParameters,
String aliasedType}) {
this.kind = kind;
this.name = name;
this.location = location;
@ -1578,6 +1592,7 @@ class Element implements HasToJson {
this.parameters = parameters;
this.returnType = returnType;
this.typeParameters = typeParameters;
this.aliasedType = aliasedType;
}
factory Element.fromJson(
@ -1623,11 +1638,17 @@ class Element implements HasToJson {
typeParameters = jsonDecoder.decodeString(
jsonPath + '.typeParameters', json['typeParameters']);
}
String aliasedType;
if (json.containsKey('aliasedType')) {
aliasedType = jsonDecoder.decodeString(
jsonPath + '.aliasedType', json['aliasedType']);
}
return Element(kind, name, flags,
location: location,
parameters: parameters,
returnType: returnType,
typeParameters: typeParameters);
typeParameters: typeParameters,
aliasedType: aliasedType);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Element', json);
}
@ -1658,6 +1679,9 @@ class Element implements HasToJson {
if (typeParameters != null) {
result['typeParameters'] = typeParameters;
}
if (aliasedType != null) {
result['aliasedType'] = aliasedType;
}
return result;
}
@ -1673,7 +1697,8 @@ class Element implements HasToJson {
flags == other.flags &&
parameters == other.parameters &&
returnType == other.returnType &&
typeParameters == other.typeParameters;
typeParameters == other.typeParameters &&
aliasedType == other.aliasedType;
}
return false;
}
@ -1688,6 +1713,7 @@ class Element implements HasToJson {
hash = JenkinsSmiHash.combine(hash, parameters.hashCode);
hash = JenkinsSmiHash.combine(hash, returnType.hashCode);
hash = JenkinsSmiHash.combine(hash, typeParameters.hashCode);
hash = JenkinsSmiHash.combine(hash, aliasedType.hashCode);
return JenkinsSmiHash.finish(hash);
}
}

View file

@ -1289,6 +1289,12 @@ a:focus, a:hover {
The type parameter list for the element. If the element doesn't have
type parameters, this field will not be defined.
</p>
</dd><dt class="field"><b>aliasedType: String<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
If the element is a type alias, this field is the aliased type.
Otherwise this field will not be defined.
</p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_ElementKind">ElementKind: String</a></dt><dd>
<p>
An enumeration of the kinds of elements.

View file

@ -1435,6 +1435,7 @@ class DiagnosticMessage implements HasToJson {
/// "parameters": optional String
/// "returnType": optional String
/// "typeParameters": optional String
/// "aliasedType": optional String
/// }
///
/// Clients may not extend, implement or mix-in this class.
@ -1477,6 +1478,8 @@ class Element implements HasToJson {
String _typeParameters;
String _aliasedType;
/// The kind of the element.
ElementKind get kind => _kind;
@ -1566,11 +1569,22 @@ class Element implements HasToJson {
_typeParameters = value;
}
/// If the element is a type alias, this field is the aliased type. Otherwise
/// this field will not be defined.
String get aliasedType => _aliasedType;
/// If the element is a type alias, this field is the aliased type. Otherwise
/// this field will not be defined.
set aliasedType(String value) {
_aliasedType = value;
}
Element(ElementKind kind, String name, int flags,
{Location location,
String parameters,
String returnType,
String typeParameters}) {
String typeParameters,
String aliasedType}) {
this.kind = kind;
this.name = name;
this.location = location;
@ -1578,6 +1592,7 @@ class Element implements HasToJson {
this.parameters = parameters;
this.returnType = returnType;
this.typeParameters = typeParameters;
this.aliasedType = aliasedType;
}
factory Element.fromJson(
@ -1623,11 +1638,17 @@ class Element implements HasToJson {
typeParameters = jsonDecoder.decodeString(
jsonPath + '.typeParameters', json['typeParameters']);
}
String aliasedType;
if (json.containsKey('aliasedType')) {
aliasedType = jsonDecoder.decodeString(
jsonPath + '.aliasedType', json['aliasedType']);
}
return Element(kind, name, flags,
location: location,
parameters: parameters,
returnType: returnType,
typeParameters: typeParameters);
typeParameters: typeParameters,
aliasedType: aliasedType);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Element', json);
}
@ -1658,6 +1679,9 @@ class Element implements HasToJson {
if (typeParameters != null) {
result['typeParameters'] = typeParameters;
}
if (aliasedType != null) {
result['aliasedType'] = aliasedType;
}
return result;
}
@ -1673,7 +1697,8 @@ class Element implements HasToJson {
flags == other.flags &&
parameters == other.parameters &&
returnType == other.returnType &&
typeParameters == other.typeParameters;
typeParameters == other.typeParameters &&
aliasedType == other.aliasedType;
}
return false;
}
@ -1688,6 +1713,7 @@ class Element implements HasToJson {
hash = JenkinsSmiHash.combine(hash, parameters.hashCode);
hash = JenkinsSmiHash.combine(hash, returnType.hashCode);
hash = JenkinsSmiHash.combine(hash, typeParameters.hashCode);
hash = JenkinsSmiHash.combine(hash, aliasedType.hashCode);
return JenkinsSmiHash.finish(hash);
}
}

View file

@ -111,19 +111,22 @@ class AnalyzerConverter {
plugin.Element convertElement(analyzer.Element element) {
var kind = _convertElementToElementKind(element);
return plugin.Element(
kind,
element.displayName,
plugin.Element.makeFlags(
isPrivate: element.isPrivate,
isDeprecated: element.hasDeprecated,
isAbstract: _isAbstract(element),
isConst: _isConst(element),
isFinal: _isFinal(element),
isStatic: _isStatic(element)),
location: locationFromElement(element),
typeParameters: _getTypeParametersString(element),
parameters: _getParametersString(element),
returnType: _getReturnTypeString(element));
kind,
element.displayName,
plugin.Element.makeFlags(
isPrivate: element.isPrivate,
isDeprecated: element.hasDeprecated,
isAbstract: _isAbstract(element),
isConst: _isConst(element),
isFinal: _isFinal(element),
isStatic: _isStatic(element),
),
location: locationFromElement(element),
typeParameters: _getTypeParametersString(element),
aliasedType: _getAliasedTypeString(element),
parameters: _getParametersString(element),
returnType: _getReturnTypeString(element),
);
}
/// Convert the element [kind] from the 'analyzer' package to an element kind
@ -224,6 +227,14 @@ class AnalyzerConverter {
return convertElementKind(element.kind);
}
String _getAliasedTypeString(analyzer.Element element) {
if (element is analyzer.TypeAliasElement) {
var aliasedType = element.aliasedType;
return aliasedType.getDisplayString(withNullability: false);
}
return null;
}
/// Return a textual representation of the parameters of the given [element],
/// or `null` if the element does not have any parameters.
String _getParametersString(analyzer.Element element) {
@ -288,8 +299,6 @@ class AnalyzerConverter {
if (aliasedType is FunctionType) {
var returnType = aliasedType.returnType;
return returnType.getDisplayString(withNullability: false);
} else {
return aliasedType.getDisplayString(withNullability: false);
}
}
return null;

View file

@ -221,6 +221,7 @@ final Matcher isDiagnosticMessage = LazyMatcher(() => MatchesJsonObject(
/// "parameters": optional String
/// "returnType": optional String
/// "typeParameters": optional String
/// "aliasedType": optional String
/// }
final Matcher isElement = LazyMatcher(() => MatchesJsonObject('Element', {
'kind': isElementKind,
@ -230,7 +231,8 @@ final Matcher isElement = LazyMatcher(() => MatchesJsonObject('Element', {
'location': isLocation,
'parameters': isString,
'returnType': isString,
'typeParameters': isString
'typeParameters': isString,
'aliasedType': isString
}));
/// ElementKind

View file

@ -604,8 +604,9 @@ typedef A<T> = Map<int, T>;
expect(location.startLine, 1);
expect(location.startColumn, 9);
}
expect(element.aliasedType, 'Map<int, T>');
expect(element.parameters, isNull);
expect(element.returnType, 'Map<int, T>');
expect(element.returnType, isNull);
expect(element.flags, 0);
}

View file

@ -520,6 +520,13 @@
type parameters, this field will not be defined.
</p>
</field>
<field name="aliasedType" optional="true">
<ref>String</ref>
<p>
If the element is a type alias, this field is the aliased type.
Otherwise this field will not be defined.
</p>
</field>
</object>
</type>
<type name="ElementKind">