| Index: pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
|
| diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d415b51985ad2a4d02a971d75218b252a617cf4
|
| --- /dev/null
|
| +++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
|
| @@ -0,0 +1,147 @@
|
| +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
|
| +import 'package:analyzer/dart/ast/ast.dart';
|
| +import 'package:analyzer/dart/ast/standard_resolution_map.dart';
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/dart/element/type.dart';
|
| +import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
|
| +import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
|
| +import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
|
| +import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
|
| +
|
| +/**
|
| + * A contributor for calculating suggestions for inherited references.
|
| + */
|
| +class InheritedReferenceContributor extends Object
|
| + with ElementSuggestionBuilder
|
| + implements CompletionContributor {
|
| + @override
|
| + LibraryElement containingLibrary;
|
| +
|
| + @override
|
| + CompletionSuggestionKind kind;
|
| +
|
| + @override
|
| + Future<Null> computeSuggestions(
|
| + CompletionRequest request, CompletionCollector collector) async {
|
| + CompletionTarget target =
|
| + new CompletionTarget.forOffset(request.result.unit, request.offset);
|
| + OpType optype = new OpType.forCompletion(target, request.offset);
|
| + if (!optype.includeIdentifiers) {
|
| + return;
|
| + }
|
| + ClassDeclaration classDecl = _enclosingClass(target);
|
| + if (classDecl == null || classDecl.element == null) {
|
| + return;
|
| + }
|
| + containingLibrary = request.result.libraryElement;
|
| + _computeSuggestionsForClass2(
|
| + collector,
|
| + target,
|
| + resolutionMap.elementDeclaredByClassDeclaration(classDecl),
|
| + request,
|
| + optype);
|
| + }
|
| +
|
| + List<CompletionSuggestion> computeSuggestionsForClass(
|
| + CompletionCollector collector,
|
| + ClassElement classElement,
|
| + CompletionRequest request,
|
| + {bool skipChildClass: true}) {
|
| +// if (!request.includeIdentifiers) {
|
| +// return const <CompletionSuggestion>[];
|
| +// }
|
| +// containingLibrary = request.result.libraryElement;
|
| +//
|
| +// return _computeSuggestionsForClass2(collector, classElement, request,
|
| +// skipChildClass: skipChildClass);
|
| + throw new StateError('Unexpected invocation of computeSuggestionsForClass');
|
| + }
|
| +
|
| + _addSuggestionsForType(InterfaceType type, OpType optype,
|
| + {bool isFunctionalArgument: false}) {
|
| + if (!isFunctionalArgument) {
|
| + for (PropertyAccessorElement elem in type.accessors) {
|
| + if (elem.isGetter) {
|
| + if (optype.includeReturnValueSuggestions) {
|
| + addSuggestion(elem);
|
| + }
|
| + } else {
|
| + if (optype.includeVoidReturnSuggestions) {
|
| + addSuggestion(elem);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + for (MethodElement elem in type.methods) {
|
| + if (elem.returnType == null) {
|
| + addSuggestion(elem);
|
| + } else if (!elem.returnType.isVoid) {
|
| + if (optype.includeReturnValueSuggestions) {
|
| + addSuggestion(elem);
|
| + }
|
| + } else {
|
| + if (optype.includeVoidReturnSuggestions) {
|
| + addSuggestion(elem);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + void _computeSuggestionsForClass2(
|
| + CompletionCollector collector,
|
| + CompletionTarget target,
|
| + ClassElement classElement,
|
| + CompletionRequest request,
|
| + OpType optype,
|
| + {bool skipChildClass: true}) {
|
| + bool isFunctionalArgument = target.isFunctionalArgument();
|
| + kind = isFunctionalArgument
|
| + ? CompletionSuggestionKind.IDENTIFIER
|
| + : CompletionSuggestionKind.INVOCATION;
|
| +
|
| + if (!skipChildClass) {
|
| + _addSuggestionsForType(classElement.type, optype,
|
| + isFunctionalArgument: isFunctionalArgument);
|
| + }
|
| +
|
| + for (InterfaceType type in classElement.allSupertypes) {
|
| + _addSuggestionsForType(type, optype,
|
| + isFunctionalArgument: isFunctionalArgument);
|
| + }
|
| + for (CompletionSuggestion suggestion in suggestions) {
|
| + collector.addSuggestion(suggestion);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return the class containing the target
|
| + * or `null` if the target is in a static method or field
|
| + * or not in a class.
|
| + */
|
| + ClassDeclaration _enclosingClass(CompletionTarget target) {
|
| + AstNode node = target.containingNode;
|
| + while (node != null) {
|
| + if (node is ClassDeclaration) {
|
| + return node;
|
| + }
|
| + if (node is MethodDeclaration) {
|
| + if (node.isStatic) {
|
| + return null;
|
| + }
|
| + }
|
| + if (node is FieldDeclaration) {
|
| + if (node.isStatic) {
|
| + return null;
|
| + }
|
| + }
|
| + node = node.parent;
|
| + }
|
| + return null;
|
| + }
|
| +}
|
|
|