OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library analysis_server.src.provisional.completion.dart.completion_target; | 5 library analysis_server.src.provisional.completion.dart.completion_target; |
6 | 6 |
7 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
8 import 'package:analyzer/dart/ast/token.dart'; | 8 import 'package:analyzer/dart/ast/token.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'; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 | 130 |
131 /** | 131 /** |
132 * If the target is an argument in an [ArgumentList], then this is the index | 132 * If the target is an argument in an [ArgumentList], then this is the index |
133 * of the argument in the list, otherwise this is `null`. | 133 * of the argument in the list, otherwise this is `null`. |
134 */ | 134 */ |
135 final int argIndex; | 135 final int argIndex; |
136 | 136 |
137 /** | 137 /** |
138 * Compute the appropriate [CompletionTarget] for the given [offset] within | 138 * Compute the appropriate [CompletionTarget] for the given [offset] within |
139 * the [compilationUnit]. | 139 * the [compilationUnit]. |
140 * | |
141 * Optionally, start the search from within [entryPoint] instead of using | |
142 * the [compilationUnit], which is useful for analyzing ASTs that have no | |
143 * [compilationUnit] such as dart expressions within angular templates. | |
140 */ | 144 */ |
141 factory CompletionTarget.forOffset( | 145 factory CompletionTarget.forOffset( |
142 CompilationUnit compilationUnit, int offset) { | 146 CompilationUnit compilationUnit, int offset, {AstNode entryPoint}) { |
143 // The precise algorithm is as follows. We perform a depth-first search of | 147 // The precise algorithm is as follows. We perform a depth-first search of |
144 // all edges in the parse tree (both those that point to AST nodes and | 148 // all edges in the parse tree (both those that point to AST nodes and |
145 // those that point to tokens), visiting parents before children. The | 149 // those that point to tokens), visiting parents before children. The |
146 // first edge which points to an entity satisfying either _isCandidateToken | 150 // first edge which points to an entity satisfying either _isCandidateToken |
147 // or _isCandidateNode is the completion target. If no edge is found that | 151 // or _isCandidateNode is the completion target. If no edge is found that |
148 // satisfies these two predicates, then we set the completion target entity | 152 // satisfies these two predicates, then we set the completion target entity |
149 // to null and the containingNode to the compilationUnit. | 153 // to null and the containingNode to the entryPoint. |
150 // | 154 // |
151 // Note that if a token is not a candidate target, then none of the tokens | 155 // Note that if a token is not a candidate target, then none of the tokens |
152 // that precede it are candidate targets either. Therefore any entity | 156 // that precede it are candidate targets either. Therefore any entity |
153 // whose last token is not a candidate target can be skipped. This lets us | 157 // whose last token is not a candidate target can be skipped. This lets us |
154 // prune the search to the point where no recursion is necessary; at each | 158 // prune the search to the point where no recursion is necessary; at each |
155 // step in the process we know exactly which child node we need to proceed | 159 // step in the process we know exactly which child node we need to proceed |
156 // to. | 160 // to. |
157 AstNode containingNode = compilationUnit; | 161 if (entryPoint == null) { |
162 entryPoint = compilationUnit; | |
163 } | |
Brian Wilkerson
2016/12/09 17:15:19
Or just "entryPoint ??= compilationUnit;" (in plac
| |
164 AstNode containingNode = entryPoint; | |
158 outerLoop: while (true) { | 165 outerLoop: while (true) { |
159 if (containingNode is Comment) { | 166 if (containingNode is Comment) { |
160 // Comments are handled specially: we descend into any CommentReference | 167 // Comments are handled specially: we descend into any CommentReference |
161 // child node that contains the cursor offset. | 168 // child node that contains the cursor offset. |
162 Comment comment = containingNode; | 169 Comment comment = containingNode; |
163 for (CommentReference commentReference in comment.references) { | 170 for (CommentReference commentReference in comment.references) { |
164 if (commentReference.offset <= offset && | 171 if (commentReference.offset <= offset && |
165 offset <= commentReference.end) { | 172 offset <= commentReference.end) { |
166 containingNode = commentReference; | 173 containingNode = commentReference; |
167 continue outerLoop; | 174 continue outerLoop; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 // Unexpected entity found (all entities in a parse tree should be | 232 // Unexpected entity found (all entities in a parse tree should be |
226 // AST nodes or tokens). | 233 // AST nodes or tokens). |
227 assert(false); | 234 assert(false); |
228 } | 235 } |
229 } | 236 } |
230 | 237 |
231 // No completion target found. It should only be possible to reach here | 238 // No completion target found. It should only be possible to reach here |
232 // the first time through the outer loop (since we only jump to the start | 239 // the first time through the outer loop (since we only jump to the start |
233 // of the outer loop after determining that the completion target is | 240 // of the outer loop after determining that the completion target is |
234 // inside an entity). We can check that assumption by verifying that | 241 // inside an entity). We can check that assumption by verifying that |
235 // containingNode is still the compilationUnit. | 242 // containingNode is still the entryPoint. |
236 assert(identical(containingNode, compilationUnit)); | 243 assert(identical(containingNode, entryPoint)); |
237 | 244 |
238 // Since no completion target was found, we set the completion target | 245 // Since no completion target was found, we set the completion target |
239 // entity to null and use the compilationUnit as the parent. | 246 // entity to null and use the entryPoint as the parent. |
240 return new CompletionTarget._( | 247 return new CompletionTarget._( |
241 compilationUnit, offset, compilationUnit, null, false); | 248 compilationUnit, offset, entryPoint, null, false); |
242 } | 249 } |
243 } | 250 } |
244 | 251 |
245 /** | 252 /** |
246 * Create a [CompletionTarget] holding the given [containingNode] and | 253 * Create a [CompletionTarget] holding the given [containingNode] and |
247 * [entity]. | 254 * [entity]. |
248 */ | 255 */ |
249 CompletionTarget._(this.unit, this.offset, AstNode containingNode, | 256 CompletionTarget._(this.unit, this.offset, AstNode containingNode, |
250 Object entity, this.isCommentText) | 257 Object entity, this.isCommentText) |
251 : this.containingNode = containingNode, | 258 : this.containingNode = containingNode, |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 if (param.parameterKind == ParameterKind.NAMED) { | 430 if (param.parameterKind == ParameterKind.NAMED) { |
424 // TODO(danrubel) handle named parameters | 431 // TODO(danrubel) handle named parameters |
425 return false; | 432 return false; |
426 } else { | 433 } else { |
427 return paramType is FunctionType || paramType is FunctionTypeAlias; | 434 return paramType is FunctionType || paramType is FunctionTypeAlias; |
428 } | 435 } |
429 } | 436 } |
430 return false; | 437 return false; |
431 } | 438 } |
432 } | 439 } |
OLD | NEW |