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 entryPoint ??= compilationUnit; |
| 162 AstNode containingNode = entryPoint; |
158 outerLoop: while (true) { | 163 outerLoop: while (true) { |
159 if (containingNode is Comment) { | 164 if (containingNode is Comment) { |
160 // Comments are handled specially: we descend into any CommentReference | 165 // Comments are handled specially: we descend into any CommentReference |
161 // child node that contains the cursor offset. | 166 // child node that contains the cursor offset. |
162 Comment comment = containingNode; | 167 Comment comment = containingNode; |
163 for (CommentReference commentReference in comment.references) { | 168 for (CommentReference commentReference in comment.references) { |
164 if (commentReference.offset <= offset && | 169 if (commentReference.offset <= offset && |
165 offset <= commentReference.end) { | 170 offset <= commentReference.end) { |
166 containingNode = commentReference; | 171 containingNode = commentReference; |
167 continue outerLoop; | 172 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 | 230 // Unexpected entity found (all entities in a parse tree should be |
226 // AST nodes or tokens). | 231 // AST nodes or tokens). |
227 assert(false); | 232 assert(false); |
228 } | 233 } |
229 } | 234 } |
230 | 235 |
231 // No completion target found. It should only be possible to reach here | 236 // 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 | 237 // 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 | 238 // of the outer loop after determining that the completion target is |
234 // inside an entity). We can check that assumption by verifying that | 239 // inside an entity). We can check that assumption by verifying that |
235 // containingNode is still the compilationUnit. | 240 // containingNode is still the entryPoint. |
236 assert(identical(containingNode, compilationUnit)); | 241 assert(identical(containingNode, entryPoint)); |
237 | 242 |
238 // Since no completion target was found, we set the completion target | 243 // Since no completion target was found, we set the completion target |
239 // entity to null and use the compilationUnit as the parent. | 244 // entity to null and use the entryPoint as the parent. |
240 return new CompletionTarget._( | 245 return new CompletionTarget._( |
241 compilationUnit, offset, compilationUnit, null, false); | 246 compilationUnit, offset, entryPoint, null, false); |
242 } | 247 } |
243 } | 248 } |
244 | 249 |
245 /** | 250 /** |
246 * Create a [CompletionTarget] holding the given [containingNode] and | 251 * Create a [CompletionTarget] holding the given [containingNode] and |
247 * [entity]. | 252 * [entity]. |
248 */ | 253 */ |
249 CompletionTarget._(this.unit, this.offset, AstNode containingNode, | 254 CompletionTarget._(this.unit, this.offset, AstNode containingNode, |
250 Object entity, this.isCommentText) | 255 Object entity, this.isCommentText) |
251 : this.containingNode = containingNode, | 256 : this.containingNode = containingNode, |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 if (param.parameterKind == ParameterKind.NAMED) { | 428 if (param.parameterKind == ParameterKind.NAMED) { |
424 // TODO(danrubel) handle named parameters | 429 // TODO(danrubel) handle named parameters |
425 return false; | 430 return false; |
426 } else { | 431 } else { |
427 return paramType is FunctionType || paramType is FunctionTypeAlias; | 432 return paramType is FunctionType || paramType is FunctionTypeAlias; |
428 } | 433 } |
429 } | 434 } |
430 return false; | 435 return false; |
431 } | 436 } |
432 } | 437 } |
OLD | NEW |