OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 services.completion.contributor.dart.keyword; | 5 library services.completion.contributor.dart.keyword; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 | 8 |
9 import 'package:analysis_server/src/protocol.dart'; | 9 import 'package:analysis_server/src/protocol.dart'; |
10 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart'; | 10 import 'package:analysis_server/src/services/completion/dart_completion_manager. dart'; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 @override | 225 @override |
226 visitInstanceCreationExpression(InstanceCreationExpression node) { | 226 visitInstanceCreationExpression(InstanceCreationExpression node) { |
227 if (entity == node.constructorName) { | 227 if (entity == node.constructorName) { |
228 // no keywords in 'new ^' expression | 228 // no keywords in 'new ^' expression |
229 } else { | 229 } else { |
230 super.visitInstanceCreationExpression(node); | 230 super.visitInstanceCreationExpression(node); |
231 } | 231 } |
232 } | 232 } |
233 | 233 |
234 @override | 234 @override |
235 visitIsExpression(IsExpression node) { | |
236 if (entity == node.isOperator) { | |
237 _addSuggestion(Keyword.IS, DART_RELEVANCE_HIGH); | |
238 } else { | |
239 _addExpressionKeywords(node); | |
240 } | |
241 } | |
242 | |
243 @override | |
235 visitLibraryIdentifier(LibraryIdentifier node) { | 244 visitLibraryIdentifier(LibraryIdentifier node) { |
236 // no suggestions | 245 // no suggestions |
237 } | 246 } |
238 | 247 |
239 @override | 248 @override |
240 visitMethodDeclaration(MethodDeclaration node) { | 249 visitMethodDeclaration(MethodDeclaration node) { |
241 if (entity == node.body) { | 250 if (entity == node.body) { |
242 if (node.body is EmptyFunctionBody) { | 251 if (node.body is EmptyFunctionBody) { |
243 _addClassBodyKeywords(); | 252 _addClassBodyKeywords(); |
244 _addSuggestion2(ASYNC); | 253 _addSuggestion2(ASYNC); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
397 } | 406 } |
398 } | 407 } |
399 | 408 |
400 void _addStatementKeywords(AstNode node) { | 409 void _addStatementKeywords(AstNode node) { |
401 if (_inClassMemberBody(node)) { | 410 if (_inClassMemberBody(node)) { |
402 _addSuggestions([Keyword.SUPER, Keyword.THIS,]); | 411 _addSuggestions([Keyword.SUPER, Keyword.THIS,]); |
403 } | 412 } |
404 if (_inAsyncMethodOrFunction(node)) { | 413 if (_inAsyncMethodOrFunction(node)) { |
405 _addSuggestion2(AWAIT); | 414 _addSuggestion2(AWAIT); |
406 } | 415 } |
416 if (_inLoop(node)) { | |
417 _addSuggestions([Keyword.BREAK, Keyword.CONTINUE]); | |
418 } | |
419 if (_inSwitch(node)) { | |
420 _addSuggestions([Keyword.BREAK]); | |
421 } | |
407 _addSuggestions([ | 422 _addSuggestions([ |
408 Keyword.ASSERT, | 423 Keyword.ASSERT, |
409 Keyword.CONTINUE, | |
410 Keyword.DO, | 424 Keyword.DO, |
411 Keyword.FINAL, | 425 Keyword.FINAL, |
412 Keyword.FOR, | 426 Keyword.FOR, |
413 Keyword.IF, | 427 Keyword.IF, |
414 Keyword.NEW, | 428 Keyword.NEW, |
Brian Wilkerson
2015/08/26 20:33:20
If we suggest 'new', shouldn't we also suggest 'co
danrubel
2015/08/26 21:39:29
Good suggestion. Done.
| |
415 Keyword.RETURN, | 429 Keyword.RETURN, |
416 Keyword.SWITCH, | 430 Keyword.SWITCH, |
417 Keyword.THROW, | 431 Keyword.THROW, |
418 Keyword.TRY, | 432 Keyword.TRY, |
419 Keyword.VAR, | 433 Keyword.VAR, |
420 Keyword.VOID, | 434 Keyword.VOID, |
421 Keyword.WHILE | 435 Keyword.WHILE |
422 ]); | 436 ]); |
423 _addSuggestion(Keyword.RETHROW, DART_RELEVANCE_KEYWORD - 1); | 437 _addSuggestion(Keyword.RETHROW, DART_RELEVANCE_KEYWORD - 1); |
Brian Wilkerson
2015/08/26 20:33:20
Seems like we should only suggest this if we're in
danrubel
2015/08/26 21:39:29
Good point. I'll address this in a subsequent CL.
| |
424 } | 438 } |
425 | 439 |
426 void _addSuggestion(Keyword keyword, | 440 void _addSuggestion(Keyword keyword, |
427 [int relevance = DART_RELEVANCE_KEYWORD]) { | 441 [int relevance = DART_RELEVANCE_KEYWORD]) { |
428 _addSuggestion2(keyword.syntax, relevance: relevance); | 442 _addSuggestion2(keyword.syntax, relevance: relevance); |
429 } | 443 } |
430 | 444 |
431 void _addSuggestion2(String completion, | 445 void _addSuggestion2(String completion, |
432 {int offset, int relevance: DART_RELEVANCE_KEYWORD}) { | 446 {int offset, int relevance: DART_RELEVANCE_KEYWORD}) { |
433 if (offset == null) { | 447 if (offset == null) { |
434 offset = completion.length; | 448 offset = completion.length; |
435 } | 449 } |
436 request.addSuggestion(new CompletionSuggestion( | 450 request.addSuggestion(new CompletionSuggestion( |
437 CompletionSuggestionKind.KEYWORD, relevance, completion, offset, 0, | 451 CompletionSuggestionKind.KEYWORD, |
438 false, false)); | 452 relevance, |
453 completion, | |
454 offset, | |
455 0, | |
456 false, | |
457 false)); | |
439 } | 458 } |
440 | 459 |
441 void _addSuggestions(List<Keyword> keywords, | 460 void _addSuggestions(List<Keyword> keywords, |
442 [int relevance = DART_RELEVANCE_KEYWORD]) { | 461 [int relevance = DART_RELEVANCE_KEYWORD]) { |
443 keywords.forEach((Keyword keyword) { | 462 keywords.forEach((Keyword keyword) { |
444 _addSuggestion(keyword, relevance); | 463 _addSuggestion(keyword, relevance); |
445 }); | 464 }); |
446 } | 465 } |
447 | 466 |
448 bool _inAsyncMethodOrFunction(AstNode node) { | 467 bool _inAsyncMethodOrFunction(AstNode node) { |
449 FunctionBody body = node.getAncestor((n) => n is FunctionBody); | 468 FunctionBody body = node.getAncestor((n) => n is FunctionBody); |
450 return body != null && body.isAsynchronous; | 469 return body != null && body.isAsynchronous; |
451 } | 470 } |
452 | 471 |
453 bool _inClassMemberBody(AstNode node) { | 472 bool _inClassMemberBody(AstNode node) { |
454 while (true) { | 473 while (true) { |
455 AstNode body = node.getAncestor((n) => n is FunctionBody); | 474 AstNode body = node.getAncestor((n) => n is FunctionBody); |
456 if (body == null) { | 475 if (body == null) { |
457 return false; | 476 return false; |
458 } | 477 } |
459 AstNode parent = body.parent; | 478 AstNode parent = body.parent; |
460 if (parent is ConstructorDeclaration || parent is MethodDeclaration) { | 479 if (parent is ConstructorDeclaration || parent is MethodDeclaration) { |
461 return true; | 480 return true; |
Brian Wilkerson
2015/08/26 20:33:20
If we're inside a method declaration, given that t
danrubel
2015/08/26 21:39:29
Not sure what you mean here. Isn't this valid thus
| |
462 } | 481 } |
463 node = parent; | 482 node = parent; |
464 } | 483 } |
465 } | 484 } |
485 | |
486 bool _inDoLoop(AstNode node) => | |
487 node.getAncestor((p) => p is DoStatement) != null; | |
488 | |
489 bool _inForLoop(AstNode node) => | |
490 node.getAncestor((p) => p is ForStatement || p is ForEachStatement) != | |
491 null; | |
492 | |
493 bool _inLoop(AstNode node) => | |
494 _inDoLoop(node) || _inForLoop(node) || _inWhileLoop(node); | |
495 | |
496 bool _inSwitch(AstNode node) => | |
497 node.getAncestor((p) => p is SwitchStatement) != null; | |
498 | |
499 bool _inWhileLoop(AstNode node) => | |
500 node.getAncestor((p) => p is WhileStatement) != null; | |
466 } | 501 } |
OLD | NEW |