OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 | 7 |
8 import 'package:analyzer/dart/ast/ast.dart'; | 8 import 'package:analyzer/dart/ast/ast.dart'; |
9 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
10 import 'package:analyzer/dart/element/type.dart'; | 10 import 'package:analyzer/dart/element/type.dart'; |
11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
12 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; | 12 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; |
13 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart'
; | 13 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart'
; |
14 import 'package:analyzer_plugin/src/utilities/completion/suggestion_builder.dart
'; | 14 import 'package:analyzer_plugin/src/utilities/completion/suggestion_builder.dart
'; |
15 import 'package:analyzer_plugin/src/utilities/visitors/local_declaration_visitor
.dart'; | 15 import 'package:analyzer_plugin/src/utilities/visitors/local_declaration_visitor
.dart'; |
16 import 'package:analyzer_plugin/utilities/completion/completion_core.dart'; | 16 import 'package:analyzer_plugin/utilities/completion/completion_core.dart'; |
17 import 'package:analyzer_plugin/utilities/completion/relevance.dart'; | 17 import 'package:analyzer_plugin/utilities/completion/relevance.dart'; |
18 import 'package:analyzer_plugin/utilities/completion/suggestion_builder.dart'; | 18 import 'package:analyzer_plugin/utilities/completion/suggestion_builder.dart'; |
19 | 19 |
20 /** | 20 /** |
21 * A completion contributor that will generate suggestions for instance | 21 * A completion contributor that will generate suggestions for instance |
22 * invocations and accesses. | 22 * invocations and accesses. |
23 */ | 23 */ |
24 class TypeMemberContributor implements CompletionContributor { | 24 class TypeMemberContributor implements CompletionContributor { |
25 /** | 25 /** |
26 * Clients should not overload this function. | 26 * Plugin contributors should primarily overload this function. |
| 27 * Should more parameters be needed for autocompletion needs, the |
| 28 * overloaded function should define those parameters and |
| 29 * call on `computeSuggestionsWithEntryPoint`. |
27 */ | 30 */ |
28 Future<Null> computeSuggestionsWithEntryPoint(CompletionRequest request, | 31 @override |
29 CompletionCollector collector, AstNode entryPoint) async { | 32 Future<Null> computeSuggestions( |
| 33 DartCompletionRequest request, CompletionCollector collector) async { |
30 LibraryElement containingLibrary = request.result.libraryElement; | 34 LibraryElement containingLibrary = request.result.libraryElement; |
31 // Gracefully degrade if the library element is not resolved | 35 // Gracefully degrade if the library element is not resolved |
32 // e.g. detached part file or source change | 36 // e.g. detached part file or source change |
33 if (containingLibrary == null) { | 37 if (containingLibrary == null) { |
34 return; | 38 return; |
35 } | 39 } |
36 | 40 |
37 // Recompute the target since resolution may have changed it | 41 // Recompute the target since resolution may have changed it |
38 Expression expression = _computeDotTarget(request, entryPoint); | 42 Expression expression = _computeDotTarget(request, null); |
39 if (expression == null || expression.isSynthetic) { | 43 if (expression == null || expression.isSynthetic) { |
40 return; | 44 return; |
41 } | 45 } |
42 _computeSuggestions(request, collector, containingLibrary, expression); | 46 _computeSuggestions(request, collector, containingLibrary, expression); |
43 } | 47 } |
44 | 48 |
45 /** | 49 /** |
46 * Plugin contributors should primarily overload this function. | 50 * Clients should not overload this function. |
47 * Should more parameters be needed for autocompletion needs, the | |
48 * overloaded function should define those parameters and | |
49 * call on `computeSuggestionsWithEntryPoint`. | |
50 */ | 51 */ |
51 @override | 52 Future<Null> computeSuggestionsWithEntryPoint(DartCompletionRequest request, |
52 Future<Null> computeSuggestions( | 53 CompletionCollector collector, AstNode entryPoint) async { |
53 CompletionRequest request, CompletionCollector collector) async { | |
54 LibraryElement containingLibrary = request.result.libraryElement; | 54 LibraryElement containingLibrary = request.result.libraryElement; |
55 // Gracefully degrade if the library element is not resolved | 55 // Gracefully degrade if the library element is not resolved |
56 // e.g. detached part file or source change | 56 // e.g. detached part file or source change |
57 if (containingLibrary == null) { | 57 if (containingLibrary == null) { |
58 return; | 58 return; |
59 } | 59 } |
60 | 60 |
61 // Recompute the target since resolution may have changed it | 61 // Recompute the target since resolution may have changed it |
62 Expression expression = _computeDotTarget(request, null); | 62 Expression expression = _computeDotTarget(request, entryPoint); |
63 if (expression == null || expression.isSynthetic) { | 63 if (expression == null || expression.isSynthetic) { |
64 return; | 64 return; |
65 } | 65 } |
66 _computeSuggestions(request, collector, containingLibrary, expression); | 66 _computeSuggestions(request, collector, containingLibrary, expression); |
67 } | 67 } |
68 | 68 |
| 69 /** |
| 70 * Update the completion [target] and [dotTarget] based on the given [unit]. |
| 71 */ |
| 72 Expression _computeDotTarget( |
| 73 DartCompletionRequest request, AstNode entryPoint) { |
| 74 CompletionTarget target = new CompletionTarget.forOffset( |
| 75 request.result.unit, request.offset, |
| 76 entryPoint: entryPoint); |
| 77 AstNode node = target.containingNode; |
| 78 if (node is MethodInvocation) { |
| 79 if (identical(node.methodName, target.entity)) { |
| 80 return node.realTarget; |
| 81 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { |
| 82 return node.realTarget; |
| 83 } |
| 84 } |
| 85 if (node is PropertyAccess) { |
| 86 if (identical(node.propertyName, target.entity)) { |
| 87 return node.realTarget; |
| 88 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { |
| 89 return node.realTarget; |
| 90 } |
| 91 } |
| 92 if (node is PrefixedIdentifier) { |
| 93 if (identical(node.identifier, target.entity)) { |
| 94 return node.prefix; |
| 95 } |
| 96 } |
| 97 return null; |
| 98 } |
| 99 |
69 void _computeSuggestions( | 100 void _computeSuggestions( |
70 CompletionRequest request, | 101 DartCompletionRequest request, |
71 CompletionCollector collector, | 102 CompletionCollector collector, |
72 LibraryElement containingLibrary, | 103 LibraryElement containingLibrary, |
73 Expression expression) { | 104 Expression expression) { |
74 if (expression is Identifier) { | 105 if (expression is Identifier) { |
75 Element element = expression.bestElement; | 106 Element element = expression.bestElement; |
76 if (element is ClassElement) { | 107 if (element is ClassElement) { |
77 // Suggestions provided by StaticMemberContributor | 108 // Suggestions provided by StaticMemberContributor |
78 return; | 109 return; |
79 } | 110 } |
80 if (element is PrefixElement) { | 111 if (element is PrefixElement) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 type = request.result.typeProvider.objectType; | 160 type = request.result.typeProvider.objectType; |
130 } | 161 } |
131 | 162 |
132 // Build the suggestions | 163 // Build the suggestions |
133 if (type is InterfaceType) { | 164 if (type is InterfaceType) { |
134 _SuggestionBuilder builder = new _SuggestionBuilder( | 165 _SuggestionBuilder builder = new _SuggestionBuilder( |
135 request.resourceProvider, collector, containingLibrary); | 166 request.resourceProvider, collector, containingLibrary); |
136 builder.buildSuggestions(type, containingMethodName); | 167 builder.buildSuggestions(type, containingMethodName); |
137 } | 168 } |
138 } | 169 } |
139 | |
140 /** | |
141 * Update the completion [target] and [dotTarget] based on the given [unit]. | |
142 */ | |
143 Expression _computeDotTarget(CompletionRequest request, AstNode entryPoint) { | |
144 CompletionTarget target = new CompletionTarget.forOffset( | |
145 request.result.unit, request.offset, | |
146 entryPoint: entryPoint); | |
147 AstNode node = target.containingNode; | |
148 if (node is MethodInvocation) { | |
149 if (identical(node.methodName, target.entity)) { | |
150 return node.realTarget; | |
151 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { | |
152 return node.realTarget; | |
153 } | |
154 } | |
155 if (node is PropertyAccess) { | |
156 if (identical(node.propertyName, target.entity)) { | |
157 return node.realTarget; | |
158 } else if (node.isCascaded && node.operator.offset + 1 == target.offset) { | |
159 return node.realTarget; | |
160 } | |
161 } | |
162 if (node is PrefixedIdentifier) { | |
163 if (identical(node.identifier, target.entity)) { | |
164 return node.prefix; | |
165 } | |
166 } | |
167 return null; | |
168 } | |
169 } | 170 } |
170 | 171 |
171 /** | 172 /** |
172 * An [AstVisitor] which looks for a declaration with the given name | 173 * An [AstVisitor] which looks for a declaration with the given name |
173 * and if found, tries to determine a type for that declaration. | 174 * and if found, tries to determine a type for that declaration. |
174 */ | 175 */ |
175 class _LocalBestTypeVisitor extends LocalDeclarationVisitor { | 176 class _LocalBestTypeVisitor extends LocalDeclarationVisitor { |
176 /** | 177 /** |
177 * The name for the declaration to be found. | 178 * The name for the declaration to be found. |
178 */ | 179 */ |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 // in the reverse order. | 490 // in the reverse order. |
490 typesToVisit.addAll(nextType.interfaces); | 491 typesToVisit.addAll(nextType.interfaces); |
491 if (nextType.superclass != null) { | 492 if (nextType.superclass != null) { |
492 typesToVisit.add(nextType.superclass); | 493 typesToVisit.add(nextType.superclass); |
493 } | 494 } |
494 typesToVisit.addAll(nextType.mixins); | 495 typesToVisit.addAll(nextType.mixins); |
495 } | 496 } |
496 return result; | 497 return result; |
497 } | 498 } |
498 } | 499 } |
OLD | NEW |