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

Side by Side Diff: pkg/analysis_server/lib/src/services/completion/keyword_contributor.dart

Issue 1303233008: improve keyword suggestions - fixes #24016 (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 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
« no previous file with comments | « no previous file | pkg/analysis_server/test/completion_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/completion_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698