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; |
+ } |
+} |