From 17e15ee9a4280a66cd2fc8a2c81e95fe00d8aba5 Mon Sep 17 00:00:00 2001
From: Brian Wilkerson
Date: Mon, 22 Jul 2019 21:12:40 +0000
Subject: [PATCH] Add outline support for extensions
Change-Id: I1b7145e899614b3d73d3fc2bfbe3dd7f773d38d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109880
Commit-Queue: Brian Wilkerson
Reviewed-by: Konstantin Shcheglov
---
pkg/analysis_server/doc/api.html | 2 +-
.../lib/src/computer/computer_outline.dart | 19 +++++-
.../support/protocol_matchers.dart | 2 +
.../src/computer/outline_computer_test.dart | 63 +++++++++++++++++++
.../generated/java/types/ElementKind.java | 2 +
pkg/analyzer/lib/src/dart/ast/ast.dart | 2 +-
pkg/analyzer_plugin/doc/api.html | 2 +-
.../lib/protocol/protocol_common.dart | 6 ++
.../support/protocol_matchers.dart | 2 +
.../tool/spec/common_types_spec.html | 1 +
10 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index ab38556b71a..a3f8ce1bef0 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -3713,7 +3713,7 @@ a:focus, a:hover {
An enumeration of the kinds of elements.
- - CLASS
- CLASS_TYPE_ALIAS
- COMPILATION_UNIT
- CONSTRUCTOR
- CONSTRUCTOR_INVOCATION
- ENUM
- ENUM_CONSTANT
- FIELD
- FILE
- FUNCTION
- FUNCTION_INVOCATION
- FUNCTION_TYPE_ALIAS
- GETTER
- LABEL
- LIBRARY
- LOCAL_VARIABLE
- METHOD
- MIXIN
- PARAMETER
- PREFIX
- SETTER
- TOP_LEVEL_VARIABLE
- TYPE_PARAMETER
- UNIT_TEST_GROUP
- UNIT_TEST_TEST
- UNKNOWN
ExecutableFile: object
+ - CLASS
- CLASS_TYPE_ALIAS
- COMPILATION_UNIT
- CONSTRUCTOR
- CONSTRUCTOR_INVOCATION
- ENUM
- ENUM_CONSTANT
- EXTENSION
- FIELD
- FILE
- FUNCTION
- FUNCTION_INVOCATION
- FUNCTION_TYPE_ALIAS
- GETTER
- LABEL
- LIBRARY
- LOCAL_VARIABLE
- METHOD
- MIXIN
- PARAMETER
- PREFIX
- SETTER
- TOP_LEVEL_VARIABLE
- TYPE_PARAMETER
- UNIT_TEST_GROUP
- UNIT_TEST_TEST
- UNKNOWN
ExecutableFile: object
A description of an executable file.
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index aebb4165298..0315200e687 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -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 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 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;
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ab3dae87e73..aa49a58e724 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -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",
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index bfd4ce53559..ac637b408c7 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -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 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 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 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 outlines_MyExt = outline_MyExt.children;
+ expect(outlines_MyExt, hasLength(2));
+ }
+ }
+
test_genericTypeAlias_incomplete() async {
Outline unitOutline = await _computeOutline('''
typedef F = Object;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
index 2ac5f3ed310..5fe4e7b8fa6 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ElementKind.java
@@ -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";
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 623d44ac443..736f66abf20 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3906,7 +3906,7 @@ class ExtensionDeclarationImpl extends CompilationUnitMemberImpl
}
@override
- Token get firstTokenAfterCommentAndMetadata => name.beginToken;
+ Token get firstTokenAfterCommentAndMetadata => extensionKeyword;
@override
NodeList get members => _members;
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 910ab7aba83..2390ce261e8 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1291,7 +1291,7 @@ a:focus, a:hover {
An enumeration of the kinds of elements.
- - CLASS
- CLASS_TYPE_ALIAS
- COMPILATION_UNIT
- CONSTRUCTOR
- CONSTRUCTOR_INVOCATION
- ENUM
- ENUM_CONSTANT
- FIELD
- FILE
- FUNCTION
- FUNCTION_INVOCATION
- FUNCTION_TYPE_ALIAS
- GETTER
- LABEL
- LIBRARY
- LOCAL_VARIABLE
- METHOD
- MIXIN
- PARAMETER
- PREFIX
- SETTER
- TOP_LEVEL_VARIABLE
- TYPE_PARAMETER
- UNIT_TEST_GROUP
- UNIT_TEST_TEST
- UNKNOWN
FilePath: String
+ - CLASS
- CLASS_TYPE_ALIAS
- COMPILATION_UNIT
- CONSTRUCTOR
- CONSTRUCTOR_INVOCATION
- ENUM
- ENUM_CONSTANT
- EXTENSION
- FIELD
- FILE
- FUNCTION
- FUNCTION_INVOCATION
- FUNCTION_TYPE_ALIAS
- GETTER
- LABEL
- LIBRARY
- LOCAL_VARIABLE
- METHOD
- MIXIN
- PARAMETER
- PREFIX
- SETTER
- TOP_LEVEL_VARIABLE
- TYPE_PARAMETER
- UNIT_TEST_GROUP
- UNIT_TEST_TEST
- UNKNOWN
FilePath: String
The absolute, normalized path of a file.
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 82891af510b..75ea6641a52 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -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":
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index d7aeda74e09..58cb27cec7d 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -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",
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index aac0a52a51f..812c4492390 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -530,6 +530,7 @@
CONSTRUCTOR_INVOCATION
ENUM
ENUM_CONSTANT
+ EXTENSION
FIELD
FILE
FUNCTION