Add outline support for extensions

Change-Id: I1b7145e899614b3d73d3fc2bfbe3dd7f773d38d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109880
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Brian Wilkerson 2019-07-22 21:12:40 +00:00 committed by commit-bot@chromium.org
parent 41263a4c1a
commit 17e15ee9a4
10 changed files with 97 additions and 4 deletions

View file

@ -3713,7 +3713,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">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_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">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_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>

View file

@ -42,6 +42,9 @@ class DartUnitOutlineComputer {
constantOutlines.add(_newEnumConstant(constant));
}
unitContents.add(_newEnumOutline(enumDeclaration, constantOutlines));
} else if (unitMember is ExtensionDeclaration) {
unitContents.add(_newExtensionOutline(
unitMember, _outlinesForMembers(unitMember.members)));
} else if (unitMember is TopLevelVariableDeclaration) {
TopLevelVariableDeclaration fieldDeclaration = unitMember;
VariableDeclarationList fields = fieldDeclaration.variables;
@ -92,7 +95,6 @@ class DartUnitOutlineComputer {
}
Outline _newClassOutline(ClassDeclaration node, List<Outline> classContents) {
node.firstTokenAfterCommentAndMetadata;
SimpleIdentifier nameNode = node.name;
String name = nameNode.name;
Element element = new Element(
@ -175,6 +177,21 @@ class DartUnitOutlineComputer {
return _nodeOutline(node, element, children);
}
Outline _newExtensionOutline(
ExtensionDeclaration node, List<Outline> extensionContents) {
SimpleIdentifier nameNode = node.name;
String name = nameNode?.name ?? '';
Element element = new Element(
ElementKind.EXTENSION,
name,
Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(node)),
location: _getLocationNode(nameNode ?? node.extendedType),
typeParameters: _getTypeParametersStr(node.typeParameters));
return _nodeOutline(node, element, extensionContents);
}
Outline _newFunctionOutline(FunctionDeclaration function, bool isStatic) {
TypeAnnotation returnType = function.returnType;
SimpleIdentifier nameNode = function.name;

View file

@ -470,6 +470,7 @@ final Matcher isElementDeclaration =
* CONSTRUCTOR_INVOCATION
* ENUM
* ENUM_CONSTANT
* EXTENSION
* FIELD
* FILE
* FUNCTION
@ -499,6 +500,7 @@ final Matcher isElementKind = new MatchesEnum("ElementKind", [
"CONSTRUCTOR_INVOCATION",
"ENUM",
"ENUM_CONSTANT",
"EXTENSION",
"FIELD",
"FILE",
"FUNCTION",

View file

@ -5,6 +5,7 @@
import 'dart:async';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:meta/meta.dart';
import 'package:test/test.dart';
@ -413,6 +414,68 @@ enum MyEnum {
}
}
test_extension_named() async {
createAnalysisOptionsFile(experiments: [EnableString.extension_methods]);
Outline unitOutline = await _computeOutline('''
extension MyExt on String {
int get halfLength => length ~/ 2;
void writeOn(StringBuffer b) {
b.write(this);
}
}
''');
List<Outline> topOutlines = unitOutline.children;
expect(topOutlines, hasLength(1));
// MyExt
{
Outline outline_MyExt = topOutlines[0];
Element element_MyExt = outline_MyExt.element;
expect(element_MyExt.kind, ElementKind.EXTENSION);
expect(element_MyExt.name, 'MyExt');
{
Location location = element_MyExt.location;
expect(location.offset, testCode.indexOf('MyExt on'));
expect(location.length, 'MyExt'.length);
}
expect(element_MyExt.parameters, null);
expect(element_MyExt.returnType, null);
// StringUtilities children
List<Outline> outlines_MyExt = outline_MyExt.children;
expect(outlines_MyExt, hasLength(2));
}
}
test_extension_unnamed() async {
createAnalysisOptionsFile(experiments: [EnableString.extension_methods]);
Outline unitOutline = await _computeOutline('''
extension on String {
int get halfLength => length ~/ 2;
void writeOn(StringBuffer b) {
b.write(this);
}
}
''');
List<Outline> topOutlines = unitOutline.children;
expect(topOutlines, hasLength(1));
// MyExt
{
Outline outline_MyExt = topOutlines[0];
Element element_MyExt = outline_MyExt.element;
expect(element_MyExt.kind, ElementKind.EXTENSION);
expect(element_MyExt.name, '');
{
Location location = element_MyExt.location;
expect(location.offset, testCode.indexOf('String'));
expect(location.length, 'String'.length);
}
expect(element_MyExt.parameters, null);
expect(element_MyExt.returnType, null);
// StringUtilities children
List<Outline> outlines_MyExt = outline_MyExt.children;
expect(outlines_MyExt, hasLength(2));
}
}
test_genericTypeAlias_incomplete() async {
Outline unitOutline = await _computeOutline('''
typedef F = Object;

View file

@ -29,6 +29,8 @@ public class ElementKind {
public static final String ENUM_CONSTANT = "ENUM_CONSTANT";
public static final String EXTENSION = "EXTENSION";
public static final String FIELD = "FIELD";
public static final String FILE = "FILE";

View file

@ -3906,7 +3906,7 @@ class ExtensionDeclarationImpl extends CompilationUnitMemberImpl
}
@override
Token get firstTokenAfterCommentAndMetadata => name.beginToken;
Token get firstTokenAfterCommentAndMetadata => extensionKeyword;
@override
NodeList<ClassMember> get members => _members;

View file

@ -1291,7 +1291,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">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_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">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_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.

View file

@ -1903,6 +1903,7 @@ class Element implements HasToJson {
* CONSTRUCTOR_INVOCATION
* ENUM
* ENUM_CONSTANT
* EXTENSION
* FIELD
* FILE
* FUNCTION
@ -1944,6 +1945,8 @@ class ElementKind implements Enum {
static const ElementKind ENUM_CONSTANT = const ElementKind._("ENUM_CONSTANT");
static const ElementKind EXTENSION = const ElementKind._("EXTENSION");
static const ElementKind FIELD = const ElementKind._("FIELD");
static const ElementKind FILE = const ElementKind._("FILE");
@ -2000,6 +2003,7 @@ class ElementKind implements Enum {
CONSTRUCTOR_INVOCATION,
ENUM,
ENUM_CONSTANT,
EXTENSION,
FIELD,
FILE,
FUNCTION,
@ -2042,6 +2046,8 @@ class ElementKind implements Enum {
return ENUM;
case "ENUM_CONSTANT":
return ENUM_CONSTANT;
case "EXTENSION":
return EXTENSION;
case "FIELD":
return FIELD;
case "FILE":

View file

@ -271,6 +271,7 @@ final Matcher isElement =
* CONSTRUCTOR_INVOCATION
* ENUM
* ENUM_CONSTANT
* EXTENSION
* FIELD
* FILE
* FUNCTION
@ -300,6 +301,7 @@ final Matcher isElementKind = new MatchesEnum("ElementKind", [
"CONSTRUCTOR_INVOCATION",
"ENUM",
"ENUM_CONSTANT",
"EXTENSION",
"FIELD",
"FILE",
"FUNCTION",

View file

@ -530,6 +530,7 @@
<value><code>CONSTRUCTOR_INVOCATION</code></value>
<value><code>ENUM</code></value>
<value><code>ENUM_CONSTANT</code></value>
<value><code>EXTENSION</code></value>
<value><code>FIELD</code></value>
<value><code>FILE</code></value>
<value><code>FUNCTION</code></value>