| 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 |