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