Chromium Code Reviews| 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 |