Add outline support for the new mixin syntax
Change-Id: I75d020f613daf37812ccf805d75e35091a28c198
Reviewed-on: https://dart-review.googlesource.com/72524
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 1d35cca..490f5b5 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -31,41 +31,19 @@
List<Outline> unitContents = <Outline>[];
for (CompilationUnitMember unitMember in unit.declarations) {
if (unitMember is ClassDeclaration) {
- ClassDeclaration classDeclaration = unitMember;
- List<Outline> classContents = <Outline>[];
- for (ClassMember classMember in classDeclaration.members) {
- if (classMember is ConstructorDeclaration) {
- ConstructorDeclaration constructorDeclaration = classMember;
- classContents.add(_newConstructorOutline(constructorDeclaration));
- }
- if (classMember is FieldDeclaration) {
- FieldDeclaration fieldDeclaration = classMember;
- VariableDeclarationList fields = fieldDeclaration.fields;
- if (fields != null) {
- TypeAnnotation fieldType = fields.type;
- String fieldTypeName = _safeToSource(fieldType);
- for (VariableDeclaration field in fields.variables) {
- classContents.add(_newVariableOutline(fieldTypeName,
- ElementKind.FIELD, field, fieldDeclaration.isStatic));
- }
- }
- }
- if (classMember is MethodDeclaration) {
- MethodDeclaration methodDeclaration = classMember;
- classContents.add(_newMethodOutline(methodDeclaration));
- }
- }
- unitContents.add(_newClassOutline(classDeclaration, classContents));
- }
- if (unitMember is EnumDeclaration) {
+ unitContents.add(_newClassOutline(
+ unitMember, _outlinesForMembers(unitMember.members)));
+ } else if (unitMember is MixinDeclaration) {
+ unitContents.add(_newMixinOutline(
+ unitMember, _outlinesForMembers(unitMember.members)));
+ } else if (unitMember is EnumDeclaration) {
EnumDeclaration enumDeclaration = unitMember;
List<Outline> constantOutlines = <Outline>[];
for (EnumConstantDeclaration constant in enumDeclaration.constants) {
constantOutlines.add(_newEnumConstant(constant));
}
unitContents.add(_newEnumOutline(enumDeclaration, constantOutlines));
- }
- if (unitMember is TopLevelVariableDeclaration) {
+ } else if (unitMember is TopLevelVariableDeclaration) {
TopLevelVariableDeclaration fieldDeclaration = unitMember;
VariableDeclarationList fields = fieldDeclaration.variables;
if (fields != null) {
@@ -76,16 +54,13 @@
fieldTypeName, ElementKind.TOP_LEVEL_VARIABLE, field, false));
}
}
- }
- if (unitMember is FunctionDeclaration) {
+ } else if (unitMember is FunctionDeclaration) {
FunctionDeclaration functionDeclaration = unitMember;
unitContents.add(_newFunctionOutline(functionDeclaration, true));
- }
- if (unitMember is ClassTypeAlias) {
+ } else if (unitMember is ClassTypeAlias) {
ClassTypeAlias alias = unitMember;
unitContents.add(_newClassTypeAlias(alias));
- }
- if (unitMember is FunctionTypeAlias) {
+ } else if (unitMember is FunctionTypeAlias) {
FunctionTypeAlias alias = unitMember;
unitContents.add(_newFunctionTypeAliasOutline(alias));
}
@@ -280,6 +255,21 @@
return _nodeOutline(method, element, contents);
}
+ Outline _newMixinOutline(MixinDeclaration node, List<Outline> mixinContents) {
+ node.firstTokenAfterCommentAndMetadata;
+ SimpleIdentifier nameNode = node.name;
+ String name = nameNode.name;
+ Element element = new Element(
+ ElementKind.MIXIN,
+ name,
+ Element.makeFlags(
+ isPrivate: Identifier.isPrivateName(name),
+ isDeprecated: _isDeprecated(node)),
+ location: _getLocationNode(nameNode),
+ typeParameters: _getTypeParametersStr(node.typeParameters));
+ return _nodeOutline(node, element, mixinContents);
+ }
+
Outline _newUnitOutline(List<Outline> unitContents) {
Element element = new Element(
ElementKind.COMPILATION_UNIT, '<unit>', Element.makeFlags(),
@@ -332,6 +322,33 @@
children: nullIfEmpty(children));
}
+ List<Outline> _outlinesForMembers(List<ClassMember> members) {
+ List<Outline> memberOutlines = <Outline>[];
+ for (ClassMember classMember in members) {
+ if (classMember is ConstructorDeclaration) {
+ ConstructorDeclaration constructorDeclaration = classMember;
+ memberOutlines.add(_newConstructorOutline(constructorDeclaration));
+ }
+ if (classMember is FieldDeclaration) {
+ FieldDeclaration fieldDeclaration = classMember;
+ VariableDeclarationList fields = fieldDeclaration.fields;
+ if (fields != null) {
+ TypeAnnotation fieldType = fields.type;
+ String fieldTypeName = _safeToSource(fieldType);
+ for (VariableDeclaration field in fields.variables) {
+ memberOutlines.add(_newVariableOutline(fieldTypeName,
+ ElementKind.FIELD, field, fieldDeclaration.isStatic));
+ }
+ }
+ }
+ if (classMember is MethodDeclaration) {
+ MethodDeclaration methodDeclaration = classMember;
+ memberOutlines.add(_newMethodOutline(methodDeclaration));
+ }
+ }
+ return memberOutlines;
+ }
+
static String _getTypeParametersStr(TypeParameterList parameters) {
if (parameters == null) {
return null;
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 9aa971d..340045a 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -830,6 +830,77 @@
}
}
+ test_mixin() async {
+ Outline unitOutline = await _computeOutline('''
+mixin M<N> {
+ c(int d) {}
+ String get e => null;
+ set f(int g) {}
+}
+''');
+ List<Outline> topOutlines = unitOutline.children;
+ expect(topOutlines, hasLength(1));
+ // M
+ {
+ Outline outline_M = topOutlines[0];
+ Element element_M = outline_M.element;
+ expect(element_M.kind, ElementKind.MIXIN);
+ expect(element_M.name, "M");
+ expect(element_M.typeParameters, "<N>");
+ {
+ Location location = element_M.location;
+ expect(location.offset, testCode.indexOf("M<N>"));
+ expect(location.length, 1);
+ }
+ expect(element_M.parameters, isNull);
+ expect(element_M.returnType, isNull);
+ // M children
+ List<Outline> outlines_M = outline_M.children;
+ expect(outlines_M, hasLength(3));
+ {
+ Outline outline = outlines_M[0];
+ Element element = outline.element;
+ expect(element.kind, ElementKind.METHOD);
+ expect(element.name, "c");
+ {
+ Location location = element.location;
+ expect(location.offset, testCode.indexOf("c(int d)"));
+ expect(location.length, 1);
+ }
+ expect(element.parameters, "(int d)");
+ expect(element.returnType, "");
+ expect(element.isAbstract, isFalse);
+ expect(element.isStatic, isFalse);
+ }
+ {
+ Outline outline = outlines_M[1];
+ Element element = outline.element;
+ expect(element.kind, ElementKind.GETTER);
+ expect(element.name, "e");
+ {
+ Location location = element.location;
+ expect(location.offset, testCode.indexOf("e => null"));
+ expect(location.length, 1);
+ }
+ expect(element.parameters, isNull);
+ expect(element.returnType, "String");
+ }
+ {
+ Outline outline = outlines_M[2];
+ Element element = outline.element;
+ expect(element.kind, ElementKind.SETTER);
+ expect(element.name, "f");
+ {
+ Location location = element.location;
+ expect(location.offset, testCode.indexOf("f(int g)"));
+ expect(location.length, 1);
+ }
+ expect(element.parameters, "(int g)");
+ expect(element.returnType, "");
+ }
+ }
+ }
+
test_sourceRanges_fields() async {
Outline unitOutline = await _computeOutline('''
class A {