Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(685)

Side by Side Diff: pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart

Issue 1407273004: next step toward completion plugin API (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/src/generated/ast.dart'; 7 import 'package:analyzer/src/generated/ast.dart';
8 import 'package:analyzer/src/generated/element.dart'; 8 import 'package:analyzer/src/generated/element.dart';
9 import 'package:analyzer/src/generated/scanner.dart'; 9 import 'package:analyzer/src/generated/scanner.dart';
10 import 'package:analyzer/src/generated/utilities_dart.dart'; 10 import 'package:analyzer/src/generated/utilities_dart.dart';
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 * 79 *
80 * If the file is empty, or the cursor is after all the text in the file, then 80 * If the file is empty, or the cursor is after all the text in the file, then
81 * there may be no edge in the parse tree which is appropriate to act as the 81 * there may be no edge in the parse tree which is appropriate to act as the
82 * completion target; in this case, [entity] is set to null and 82 * completion target; in this case, [entity] is set to null and
83 * [containingNode] is set to the CompilationUnit. 83 * [containingNode] is set to the CompilationUnit.
84 * 84 *
85 * Clients may not extend, implement or mix-in this class. 85 * Clients may not extend, implement or mix-in this class.
86 */ 86 */
87 class CompletionTarget { 87 class CompletionTarget {
88 /** 88 /**
89 * The compilation unit in which the completion is occurring.
90 */
91 final CompilationUnit unit;
92
93 /**
89 * The context in which the completion is occurring. This is the AST node 94 * The context in which the completion is occurring. This is the AST node
90 * which is a direct parent of [entity]. 95 * which is a direct parent of [entity].
91 */ 96 */
92 final AstNode containingNode; 97 final AstNode containingNode;
93 98
94 /** 99 /**
95 * The entity which the completed text will replace (or which will be 100 * The entity which the completed text will replace (or which will be
96 * displaced once the completed text is inserted). This may be an AstNode or 101 * displaced once the completed text is inserted). This may be an AstNode or
97 * a Token, or it may be null if the cursor is after all tokens in the file. 102 * a Token, or it may be null if the cursor is after all tokens in the file.
98 * 103 *
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 continue outerLoop; 154 continue outerLoop;
150 } 155 }
151 } 156 }
152 } 157 }
153 for (var entity in containingNode.childEntities) { 158 for (var entity in containingNode.childEntities) {
154 if (entity is Token) { 159 if (entity is Token) {
155 if (_isCandidateToken(entity, offset)) { 160 if (_isCandidateToken(entity, offset)) {
156 // Try to replace with a comment token. 161 // Try to replace with a comment token.
157 Token commentToken = _getContainingCommentToken(entity, offset); 162 Token commentToken = _getContainingCommentToken(entity, offset);
158 if (commentToken != null) { 163 if (commentToken != null) {
159 return new CompletionTarget._(containingNode, commentToken, true); 164 return new CompletionTarget._(
165 compilationUnit, containingNode, commentToken, true);
160 } 166 }
161 // Target found. 167 // Target found.
162 return new CompletionTarget._(containingNode, entity, false); 168 return new CompletionTarget._(
169 compilationUnit, containingNode, entity, false);
163 } else { 170 } else {
164 // Since entity is a token, we don't need to look inside it; just 171 // Since entity is a token, we don't need to look inside it; just
165 // proceed to the next entity. 172 // proceed to the next entity.
166 continue; 173 continue;
167 } 174 }
168 } else if (entity is AstNode) { 175 } else if (entity is AstNode) {
169 // If the last token in the node isn't a candidate target, then 176 // If the last token in the node isn't a candidate target, then
170 // neither the node nor any of its descendants can possibly be the 177 // neither the node nor any of its descendants can possibly be the
171 // completion target, so we can skip the node entirely. 178 // completion target, so we can skip the node entirely.
172 if (!_isCandidateToken(entity.endToken, offset)) { 179 if (!_isCandidateToken(entity.endToken, offset)) {
173 continue; 180 continue;
174 } 181 }
175 182
176 // If the node is a candidate target, then we are done. 183 // If the node is a candidate target, then we are done.
177 if (_isCandidateNode(entity, offset)) { 184 if (_isCandidateNode(entity, offset)) {
178 // Check to see if the offset is in a preceding comment 185 // Check to see if the offset is in a preceding comment
179 Token commentToken = 186 Token commentToken =
180 _getContainingCommentToken(entity.beginToken, offset); 187 _getContainingCommentToken(entity.beginToken, offset);
181 if (commentToken != null) { 188 if (commentToken != null) {
182 entity = commentToken; 189 entity = commentToken;
183 // If the preceding comment is dartdoc token, then update 190 // If the preceding comment is dartdoc token, then update
184 // the containing node to be the dartdoc comment. 191 // the containing node to be the dartdoc comment.
185 // Otherwise completion is not required. 192 // Otherwise completion is not required.
186 Comment docComment = 193 Comment docComment =
187 _getContainingDocComment(containingNode, commentToken); 194 _getContainingDocComment(containingNode, commentToken);
188 if (docComment != null) { 195 if (docComment != null) {
189 containingNode = docComment; 196 containingNode = docComment;
190 } else { 197 } else {
191 return new CompletionTarget._( 198 return new CompletionTarget._(
192 compilationUnit, commentToken, true); 199 compilationUnit, compilationUnit, commentToken, true);
193 } 200 }
194 } 201 }
195 return new CompletionTarget._(containingNode, entity, false); 202 return new CompletionTarget._(
203 compilationUnit, containingNode, entity, false);
196 } 204 }
197 205
198 // Otherwise, the completion target is somewhere inside the entity, 206 // Otherwise, the completion target is somewhere inside the entity,
199 // so we need to jump to the start of the outer loop to examine its 207 // so we need to jump to the start of the outer loop to examine its
200 // contents. 208 // contents.
201 containingNode = entity; 209 containingNode = entity;
202 continue outerLoop; 210 continue outerLoop;
203 } else { 211 } else {
204 // Unexpected entity found (all entities in a parse tree should be 212 // Unexpected entity found (all entities in a parse tree should be
205 // AST nodes or tokens). 213 // AST nodes or tokens).
206 assert(false); 214 assert(false);
207 } 215 }
208 } 216 }
209 217
210 // No completion target found. It should only be possible to reach here 218 // No completion target found. It should only be possible to reach here
211 // the first time through the outer loop (since we only jump to the start 219 // the first time through the outer loop (since we only jump to the start
212 // of the outer loop after determining that the completion target is 220 // of the outer loop after determining that the completion target is
213 // inside an entity). We can check that assumption by verifying that 221 // inside an entity). We can check that assumption by verifying that
214 // containingNode is still the compilationUnit. 222 // containingNode is still the compilationUnit.
215 assert(identical(containingNode, compilationUnit)); 223 assert(identical(containingNode, compilationUnit));
216 224
217 // Since no completion target was found, we set the completion target 225 // Since no completion target was found, we set the completion target
218 // entity to null and use the compilationUnit as the parent. 226 // entity to null and use the compilationUnit as the parent.
219 return new CompletionTarget._(compilationUnit, null, false); 227 return new CompletionTarget._(
228 compilationUnit, compilationUnit, null, false);
220 } 229 }
221 } 230 }
222 231
223 /** 232 /**
224 * Create a [CompletionTarget] holding the given [containingNode] and 233 * Create a [CompletionTarget] holding the given [containingNode] and
225 * [entity]. 234 * [entity].
226 */ 235 */
227 CompletionTarget._(AstNode containingNode, Object entity, this.isCommentText) 236 CompletionTarget._(
237 this.unit, AstNode containingNode, Object entity, this.isCommentText)
228 : this.containingNode = containingNode, 238 : this.containingNode = containingNode,
229 this.entity = entity, 239 this.entity = entity,
230 this.argIndex = _computeArgIndex(containingNode, entity); 240 this.argIndex = _computeArgIndex(containingNode, entity);
231 241
232 /** 242 /**
233 * Return `true` if the target is a functional argument in an argument list. 243 * Return `true` if the target is a functional argument in an argument list.
234 * The target [AstNode] hierarchy *must* be resolved for this to work. 244 * The target [AstNode] hierarchy *must* be resolved for this to work.
235 */ 245 */
236 bool isFunctionalArgument() { 246 bool isFunctionalArgument() {
237 if (argIndex == null) { 247 if (argIndex == null) {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 if (param.parameterKind == ParameterKind.NAMED) { 380 if (param.parameterKind == ParameterKind.NAMED) {
371 // TODO(danrubel) handle named parameters 381 // TODO(danrubel) handle named parameters
372 return false; 382 return false;
373 } else { 383 } else {
374 return paramType is FunctionType || paramType is FunctionTypeAlias; 384 return paramType is FunctionType || paramType is FunctionTypeAlias;
375 } 385 }
376 } 386 }
377 return false; 387 return false;
378 } 388 }
379 } 389 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698