| Index: pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
|
| index d6d9e7c2ae46af185677f0dcbfb48335a4cbef60..31f6a652750d3cba1f8e061b70d4d3595b1fcf06 100644
|
| --- a/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
|
| +++ b/pkg/analysis_server/lib/src/services/completion/suggestion_builder.dart
|
| @@ -8,9 +8,87 @@ import 'package:analysis_server/src/protocol_server.dart' as protocol;
|
| import 'package:analysis_server/src/protocol_server.dart' hide Element,
|
| ElementKind;
|
| import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| import 'package:analyzer/src/generated/element.dart';
|
|
|
| /**
|
| + * Call the given function with each non-null non-empty inherited type name
|
| + * that is defined in the given class.
|
| + */
|
| +visitInheritedTypeNames(ClassDeclaration node, void inherited(String name)) {
|
| +
|
| + void visit(TypeName type) {
|
| + if (type != null) {
|
| + Identifier id = type.name;
|
| + if (id != null) {
|
| + String name = id.name;
|
| + if (name != null && name.length > 0) {
|
| + inherited(name);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + ExtendsClause extendsClause = node.extendsClause;
|
| + if (extendsClause != null) {
|
| + visit(extendsClause.superclass);
|
| + }
|
| + ImplementsClause implementsClause = node.implementsClause;
|
| + if (implementsClause != null) {
|
| + NodeList<TypeName> interfaces = implementsClause.interfaces;
|
| + if (interfaces != null) {
|
| + interfaces.forEach((TypeName type) {
|
| + visit(type);
|
| + });
|
| + }
|
| + }
|
| + WithClause withClause = node.withClause;
|
| + if (withClause != null) {
|
| + NodeList<TypeName> mixinTypes = withClause.mixinTypes;
|
| + if (mixinTypes != null) {
|
| + mixinTypes.forEach((TypeName type) {
|
| + visit(type);
|
| + });
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Call the given functions with each non-null non-empty inherited class
|
| + * declaration, if the class is defined locally, or type name if it is not
|
| + * defined locally.
|
| + */
|
| +void visitInheritedTypes(ClassDeclaration node, void
|
| + local(ClassDeclaration classNode), void imported(String typeName)) {
|
| + CompilationUnit unit = node.getAncestor((p) => p is CompilationUnit);
|
| + List<ClassDeclaration> todo = new List<ClassDeclaration>();
|
| + todo.add(node);
|
| + Set<String> visited = new Set<String>();
|
| + while (todo.length > 0) {
|
| + node = todo.removeLast();
|
| + visitInheritedTypeNames(node, (String name) {
|
| + if (visited.add(name)) {
|
| + var classNode = unit.declarations.firstWhere((member) {
|
| + if (member is ClassDeclaration) {
|
| + SimpleIdentifier id = member.name;
|
| + if (id != null && id.name == name) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }, orElse: () => null);
|
| + if (classNode is ClassDeclaration) {
|
| + local(classNode);
|
| + todo.add(classNode);
|
| + } else {
|
| + imported(name);
|
| + }
|
| + }
|
| + });
|
| + }
|
| +}
|
| +
|
| +/**
|
| * This class visits elements in a class and provides suggestions based upon
|
| * the visible members in that class. Clients should call
|
| * [ClassElementSuggestionBuilder.suggestionsFor].
|
|
|