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

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

Issue 2834513004: Compete try-statements (Closed)
Patch Set: Created 3 years, 8 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/services/completion/statement/statement_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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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.src.completion.statement; 5 library services.src.completion.statement;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:analysis_server/plugin/protocol/protocol.dart'; 9 import 'package:analysis_server/plugin/protocol/protocol.dart';
10 import 'package:analysis_server/src/protocol_server.dart' hide Element; 10 import 'package:analysis_server/src/protocol_server.dart' hide Element;
(...skipping 25 matching lines...) Expand all
36 static const COMPLETE_DO_STMT = const StatementCompletionKind( 36 static const COMPLETE_DO_STMT = const StatementCompletionKind(
37 'COMPLETE_DO_STMT', "Complete do-statement"); 37 'COMPLETE_DO_STMT', "Complete do-statement");
38 static const COMPLETE_IF_STMT = const StatementCompletionKind( 38 static const COMPLETE_IF_STMT = const StatementCompletionKind(
39 'COMPLETE_IF_STMT', "Complete if-statement"); 39 'COMPLETE_IF_STMT', "Complete if-statement");
40 static const COMPLETE_FOR_STMT = const StatementCompletionKind( 40 static const COMPLETE_FOR_STMT = const StatementCompletionKind(
41 'COMPLETE_FOR_STMT', "Complete for-statement"); 41 'COMPLETE_FOR_STMT', "Complete for-statement");
42 static const COMPLETE_FOR_EACH_STMT = const StatementCompletionKind( 42 static const COMPLETE_FOR_EACH_STMT = const StatementCompletionKind(
43 'COMPLETE_FOR_EACH_STMT', "Complete for-each-statement"); 43 'COMPLETE_FOR_EACH_STMT', "Complete for-each-statement");
44 static const COMPLETE_SWITCH_STMT = const StatementCompletionKind( 44 static const COMPLETE_SWITCH_STMT = const StatementCompletionKind(
45 'COMPLETE_SWITCH_STMT', "Complete switch-statement"); 45 'COMPLETE_SWITCH_STMT', "Complete switch-statement");
46 static const COMPLETE_TRY_STMT = const StatementCompletionKind(
47 'COMPLETE_TRY_STMT', "Complete try-statement");
46 static const COMPLETE_WHILE_STMT = const StatementCompletionKind( 48 static const COMPLETE_WHILE_STMT = const StatementCompletionKind(
47 'COMPLETE_WHILE_STMT', "Complete while-statement"); 49 'COMPLETE_WHILE_STMT', "Complete while-statement");
48 } 50 }
49 51
50 /** 52 /**
51 * A description of a statement completion. 53 * A description of a statement completion.
52 * 54 *
53 * Clients may not extend, implement or mix-in this class. 55 * Clients may not extend, implement or mix-in this class.
54 */ 56 */
55 class StatementCompletion { 57 class StatementCompletion {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 186
185 // TODO(messick) Consider changing (some of) this to a visitor. 187 // TODO(messick) Consider changing (some of) this to a visitor.
186 if (_complete_ifStatement() || 188 if (_complete_ifStatement() ||
187 _complete_doStatement() || 189 _complete_doStatement() ||
188 _complete_forStatement() || 190 _complete_forStatement() ||
189 _complete_forEachStatement() || 191 _complete_forEachStatement() ||
190 _complete_switchStatement() || 192 _complete_switchStatement() ||
191 _complete_tryStatement() || 193 _complete_tryStatement() ||
192 _complete_whileStatement() || 194 _complete_whileStatement() ||
193 _complete_simpleSemicolon() || 195 _complete_simpleSemicolon() ||
196 _complete_controlFlowBlock() ||
194 _complete_simpleEnter()) { 197 _complete_simpleEnter()) {
195 return completion; 198 return completion;
196 } 199 }
197 return NO_COMPLETION; 200 return NO_COMPLETION;
198 } 201 }
199 202
200 void _addInsertEdit(int offset, String text) { 203 void _addInsertEdit(int offset, String text) {
201 SourceEdit edit = new SourceEdit(offset, 0, text); 204 SourceEdit edit = new SourceEdit(offset, 0, text);
202 doSourceChange_addElementEdit(change, unitElement, edit); 205 doSourceChange_addElementEdit(change, unitElement, edit);
203 } 206 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 } 287 }
285 SourceBuilder sb2; 288 SourceBuilder sb2;
286 if (hasWhileKeyword) { 289 if (hasWhileKeyword) {
287 var stmt = new _KeywordConditionBlockStructure( 290 var stmt = new _KeywordConditionBlockStructure(
288 statement.whileKeyword, 291 statement.whileKeyword,
289 statement.leftParenthesis, 292 statement.leftParenthesis,
290 statement.condition, 293 statement.condition,
291 statement.rightParenthesis, 294 statement.rightParenthesis,
292 null); 295 null);
293 sb2 = _complete_keywordCondition(stmt); 296 sb2 = _complete_keywordCondition(stmt);
297 if (sb2 == null) {
298 return false;
299 }
294 if (sb2.length == 0) { 300 if (sb2.length == 0) {
295 // true if condition is '()' 301 // true if condition is '()'
296 if (exitPosition != null) { 302 if (exitPosition != null) {
297 if (statement.semicolon.isSynthetic) { 303 if (statement.semicolon.isSynthetic) {
298 _insertBuilder(sb); 304 _insertBuilder(sb);
299 sb = new SourceBuilder(file, exitPosition.offset + 1); 305 sb = new SourceBuilder(file, exitPosition.offset + 1);
300 sb.append(';'); 306 sb.append(';');
301 } 307 }
302 } 308 }
303 } else { 309 } else {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 exitPosition = new Position(file, exitPosition.offset - delta); 453 exitPosition = new Position(file, exitPosition.offset - delta);
448 } 454 }
449 _insertBuilder(sb); 455 _insertBuilder(sb);
450 _setCompletion(DartStatementCompletion.COMPLETE_FOR_STMT); 456 _setCompletion(DartStatementCompletion.COMPLETE_FOR_STMT);
451 return true; 457 return true;
452 } 458 }
453 459
454 bool _complete_ifOrWhileStatement( 460 bool _complete_ifOrWhileStatement(
455 _KeywordConditionBlockStructure statement, StatementCompletionKind kind) { 461 _KeywordConditionBlockStructure statement, StatementCompletionKind kind) {
456 SourceBuilder sb = _complete_keywordCondition(statement); 462 SourceBuilder sb = _complete_keywordCondition(statement);
463 if (sb == null) {
464 return false;
465 }
457 if (statement.block is EmptyStatement) { 466 if (statement.block is EmptyStatement) {
458 sb.append(' '); 467 sb.append(' ');
459 _appendEmptyBraces(sb, exitPosition == null); 468 _appendEmptyBraces(sb, exitPosition == null);
460 } 469 }
461 _insertBuilder(sb); 470 _insertBuilder(sb);
462 _setCompletion(kind); 471 _setCompletion(kind);
463 return true; 472 return true;
464 } 473 }
465 474
466 bool _complete_ifStatement() { 475 bool _complete_ifStatement() {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 // See https://github.com/dart-lang/sdk/issues/29391 579 // See https://github.com/dart-lang/sdk/issues/29391
571 sb.append(' '); 580 sb.append(' ');
572 _appendEmptyBraces(sb, exitPosition == null); 581 _appendEmptyBraces(sb, exitPosition == null);
573 } 582 }
574 _insertBuilder(sb); 583 _insertBuilder(sb);
575 _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT); 584 _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT);
576 return true; 585 return true;
577 } 586 }
578 587
579 bool _complete_tryStatement() { 588 bool _complete_tryStatement() {
580 // TODO(messick) Implement _complete_tryStatement 589 if (errors.isEmpty || node is! TryStatement) {
581 return false; 590 return false;
591 }
592 TryStatement tryNode = node;
593 SourceBuilder sb;
594 CatchClause catchNode;
595 bool addSpace = true;
596 if (tryNode.body.leftBracket.isSynthetic) {
597 String src = utils.getNodeText(tryNode);
598 if (src
599 .substring(tryNode.tryKeyword.end - tryNode.offset)
600 .startsWith(new RegExp(r'[ \t]+'))) {
601 // keywordSpace
602 sb = new SourceBuilder(file, tryNode.tryKeyword.end + 1);
603 } else {
604 // keywordOnly
605 sb = new SourceBuilder(file, tryNode.tryKeyword.end);
606 sb.append(' ');
607 }
608 _appendEmptyBraces(sb, true);
609 _insertBuilder(sb);
610 sb = null;
611 } else if ((catchNode = _firstInvalidCatch(tryNode.catchClauses)) != null) {
612 if (catchNode.onKeyword != null) {
613 if (catchNode.exceptionType.length == 0) {
614 String src = utils.getNodeText(catchNode);
615 if (src.startsWith(new RegExp(r'on[ \t]+'))) {
616 if (src.startsWith(new RegExp(r'on[ \t][ \t]+'))) {
617 // onSpaces
618 exitPosition = new Position(file, catchNode.onKeyword.end + 1);
619 sb = new SourceBuilder(file, catchNode.onKeyword.end + 2);
620 addSpace = false;
621 } else {
622 // onSpace
623 sb = new SourceBuilder(file, catchNode.onKeyword.end + 1);
624 sb.setExitOffset();
625 }
626 } else {
627 // onOnly
628 sb = new SourceBuilder(file, catchNode.onKeyword.end);
629 sb.append(' ');
630 sb.setExitOffset();
631 }
632 } else {
633 // onType
634 sb = new SourceBuilder(file, catchNode.exceptionType.end);
635 }
636 }
637 if (catchNode.catchKeyword != null) {
638 // catchOnly
639 var struct = new _KeywordConditionBlockStructure(
640 catchNode.catchKeyword,
641 catchNode.leftParenthesis,
642 catchNode.exceptionParameter,
643 catchNode.rightParenthesis,
644 catchNode.body);
645 if (sb != null) {
646 // onCatch
647 _insertBuilder(sb);
648 }
649 sb = _complete_keywordCondition(struct);
650 if (sb == null) {
651 return false;
652 }
653 }
654 if (catchNode.body.leftBracket.isSynthetic) {
655 // onOnly and others
656 if (addSpace) {
657 sb.append(' ');
658 }
659 _appendEmptyBraces(sb, exitPosition == null);
660 }
661 _insertBuilder(sb);
662 } else if (tryNode.finallyKeyword != null) {
663 if (tryNode.finallyBlock.leftBracket.isSynthetic) {
664 // finallyOnly
665 sb = new SourceBuilder(file, tryNode.finallyKeyword.end);
666 sb.append(' ');
667 _appendEmptyBraces(sb, true);
668 _insertBuilder(sb);
669 }
670 }
671 _setCompletion(DartStatementCompletion.COMPLETE_TRY_STMT);
672 return true;
582 } 673 }
583 674
584 bool _complete_whileStatement() { 675 bool _complete_whileStatement() {
585 if (errors.isEmpty || node is! WhileStatement) { 676 if (errors.isEmpty || node is! WhileStatement) {
586 return false; 677 return false;
587 } 678 }
588 WhileStatement whileNode = node; 679 WhileStatement whileNode = node;
589 if (whileNode != null) { 680 if (whileNode != null) {
590 var stmt = new _KeywordConditionBlockStructure( 681 var stmt = new _KeywordConditionBlockStructure(
591 whileNode.whileKeyword, 682 whileNode.whileKeyword,
(...skipping 12 matching lines...) Expand all
604 errors.firstWhere((err) => err.errorCode == code, orElse: () => null); 695 errors.firstWhere((err) => err.errorCode == code, orElse: () => null);
605 if (error != null) { 696 if (error != null) {
606 if (partialMatch != null) { 697 if (partialMatch != null) {
607 return error.message.contains(partialMatch) ? error : null; 698 return error.message.contains(partialMatch) ? error : null;
608 } 699 }
609 return error; 700 return error;
610 } 701 }
611 return null; 702 return null;
612 } 703 }
613 704
705 CatchClause _firstInvalidCatch(NodeList<CatchClause> list) {
706 return list.firstWhere((e) {
707 bool found = false;
708 for (var error in errors) {
709 if (error.offset >= e.offset && error.offset <= e.end) {
710 if (error.errorCode is! HintCode) {
711 found = true;
712 break;
713 }
714 }
715 }
716 return found;
717 }, orElse: () => null);
718 }
719
614 LinkedEditGroup _getLinkedPosition(String groupId) { 720 LinkedEditGroup _getLinkedPosition(String groupId) {
615 LinkedEditGroup group = linkedPositionGroups[groupId]; 721 LinkedEditGroup group = linkedPositionGroups[groupId];
616 if (group == null) { 722 if (group == null) {
617 group = new LinkedEditGroup.empty(); 723 group = new LinkedEditGroup.empty();
618 linkedPositionGroups[groupId] = group; 724 linkedPositionGroups[groupId] = group;
619 } 725 }
620 return group; 726 return group;
621 } 727 }
622 728
623 void _insertBuilder(SourceBuilder builder, [int length = 0]) { 729 void _insertBuilder(SourceBuilder builder, [int length = 0]) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 final Token keyword; 802 final Token keyword;
697 final Token leftParenthesis, rightParenthesis; 803 final Token leftParenthesis, rightParenthesis;
698 final Expression condition; 804 final Expression condition;
699 final Statement block; 805 final Statement block;
700 806
701 _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis, 807 _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis,
702 this.condition, this.rightParenthesis, this.block); 808 this.condition, this.rightParenthesis, this.block);
703 809
704 int get offset => keyword.offset; 810 int get offset => keyword.offset;
705 } 811 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698