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

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

Issue 2830793007: Clean up TODOs (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;
11 import 'package:analysis_server/src/services/correction/source_buffer.dart'; 11 import 'package:analysis_server/src/services/correction/source_buffer.dart';
12 import 'package:analysis_server/src/services/correction/source_range.dart'; 12 import 'package:analysis_server/src/services/correction/source_range.dart';
13 import 'package:analysis_server/src/services/correction/util.dart'; 13 import 'package:analysis_server/src/services/correction/util.dart';
14 import 'package:analyzer/dart/ast/ast.dart'; 14 import 'package:analyzer/dart/ast/ast.dart';
15 import 'package:analyzer/dart/ast/token.dart'; 15 import 'package:analyzer/dart/ast/token.dart';
16 import 'package:analyzer/dart/ast/visitor.dart';
16 import 'package:analyzer/dart/element/element.dart'; 17 import 'package:analyzer/dart/element/element.dart';
17 import 'package:analyzer/error/error.dart'; 18 import 'package:analyzer/error/error.dart';
18 import 'package:analyzer/error/error.dart' as engine; 19 import 'package:analyzer/error/error.dart' as engine;
19 import 'package:analyzer/src/dart/ast/utilities.dart'; 20 import 'package:analyzer/src/dart/ast/utilities.dart';
20 import 'package:analyzer/src/dart/error/hint_codes.dart'; 21 import 'package:analyzer/src/dart/error/hint_codes.dart';
21 import 'package:analyzer/src/dart/error/syntactic_errors.dart'; 22 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
22 import 'package:analyzer/src/generated/engine.dart'; 23 import 'package:analyzer/src/generated/engine.dart';
23 import 'package:analyzer/src/generated/java_core.dart'; 24 import 'package:analyzer/src/generated/java_core.dart';
24 import 'package:analyzer/src/generated/source.dart'; 25 import 'package:analyzer/src/generated/source.dart';
25 26
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 } 178 }
178 for (engine.AnalysisError error in statementContext.errors) { 179 for (engine.AnalysisError error in statementContext.errors) {
179 if (error.offset >= node.offset && 180 if (error.offset >= node.offset &&
180 error.offset <= node.offset + node.length) { 181 error.offset <= node.offset + node.length) {
181 if (error.errorCode is! HintCode) { 182 if (error.errorCode is! HintCode) {
182 errors.add(error); 183 errors.add(error);
183 } 184 }
184 } 185 }
185 } 186 }
186 187
187 // TODO(messick) Consider changing (some of) this to a visitor. 188 if (errors.isEmpty) {
188 if (_complete_ifStatement() || 189 if (_complete_simpleEnter()) {
189 _complete_doStatement() || 190 return completion;
190 _complete_forStatement() || 191 }
191 _complete_forEachStatement() || 192 } else {
192 _complete_switchStatement() || 193 if (_complete_ifStatement() ||
193 _complete_tryStatement() || 194 _complete_doStatement() ||
194 _complete_whileStatement() || 195 _complete_forStatement() ||
195 _complete_simpleSemicolon() || 196 _complete_forEachStatement() ||
196 _complete_controlFlowBlock() || 197 _complete_switchStatement() ||
197 _complete_simpleEnter()) { 198 _complete_tryStatement() ||
198 return completion; 199 _complete_whileStatement() ||
200 _complete_simpleSemicolon() ||
201 _complete_controlFlowBlock() ||
202 _complete_simpleEnter()) {
203 return completion;
204 }
199 } 205 }
200 return NO_COMPLETION; 206 return NO_COMPLETION;
201 } 207 }
202 208
203 void _addInsertEdit(int offset, String text) { 209 void _addInsertEdit(int offset, String text) {
204 SourceEdit edit = new SourceEdit(offset, 0, text); 210 SourceEdit edit = new SourceEdit(offset, 0, text);
205 doSourceChange_addElementEdit(change, unitElement, edit); 211 doSourceChange_addElementEdit(change, unitElement, edit);
206 } 212 }
207 213
208 void _addReplaceEdit(SourceRange range, String text) { 214 void _addReplaceEdit(SourceRange range, String text) {
(...skipping 30 matching lines...) Expand all
239 text = text.substring(0, text.length - eol.length); 245 text = text.substring(0, text.length - eol.length);
240 } 246 }
241 return text; 247 return text;
242 } 248 }
243 249
244 bool _complete_controlFlowBlock() { 250 bool _complete_controlFlowBlock() {
245 //TODO(messick) Implement _complete_controlFlowBlock 251 //TODO(messick) Implement _complete_controlFlowBlock
246 // Use statement completion to move the cursor to a new line outside the 252 // Use statement completion to move the cursor to a new line outside the
247 // current block. The statement has no errors in this case. Used to jump 253 // current block. The statement has no errors in this case. Used to jump
248 // out of do/for/if/while blocks. 254 // out of do/for/if/while blocks.
249 //TODO(messick) Move has-errors checking into dispatch method.
250 return false; 255 return false;
251 } 256 }
252 257
253 bool _complete_doStatement() { 258 bool _complete_doStatement() {
254 if (errors.isEmpty || node is! DoStatement) { 259 if (node is! DoStatement) {
255 return false; 260 return false;
256 } 261 }
257 DoStatement statement = node; 262 DoStatement statement = node;
258 SourceBuilder sb = _sourceBuilderAfterKeyword(statement.doKeyword); 263 SourceBuilder sb = _sourceBuilderAfterKeyword(statement.doKeyword);
259 bool hasWhileKeyword = statement.whileKeyword.lexeme == "while"; 264 bool hasWhileKeyword = statement.whileKeyword.lexeme == "while";
260 int exitDelta = 0; 265 int exitDelta = 0;
261 if (statement.body is EmptyStatement) { 266 if (statement.body is EmptyStatement) {
262 String text = utils.getNodeText(statement.body); 267 String text = utils.getNodeText(statement.body);
263 int delta = 0; 268 int delta = 0;
264 if (text.startsWith(';')) { 269 if (text.startsWith(';')) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 _insertBuilder(sb); 328 _insertBuilder(sb);
324 if (exitDelta != 0) { 329 if (exitDelta != 0) {
325 exitPosition = 330 exitPosition =
326 new Position(exitPosition.file, exitPosition.offset + exitDelta); 331 new Position(exitPosition.file, exitPosition.offset + exitDelta);
327 } 332 }
328 _setCompletion(DartStatementCompletion.COMPLETE_DO_STMT); 333 _setCompletion(DartStatementCompletion.COMPLETE_DO_STMT);
329 return true; 334 return true;
330 } 335 }
331 336
332 bool _complete_forEachStatement() { 337 bool _complete_forEachStatement() {
333 if (errors.isEmpty || node is! ForEachStatement) { 338 if (node is! ForEachStatement) {
334 return false; 339 return false;
335 } 340 }
336 ForEachStatement forNode = node; 341 ForEachStatement forNode = node;
337 if (forNode.inKeyword.isSynthetic) { 342 if (forNode.inKeyword.isSynthetic) {
338 return false; // Can't happen -- would be parsed as a for-statement. 343 return false; // Can't happen -- would be parsed as a for-statement.
339 } 344 }
340 SourceBuilder sb = 345 SourceBuilder sb =
341 new SourceBuilder(file, forNode.rightParenthesis.offset + 1); 346 new SourceBuilder(file, forNode.rightParenthesis.offset + 1);
342 AstNode name = forNode.identifier; 347 AstNode name = forNode.identifier;
343 name ??= forNode.loopVariable; 348 name ??= forNode.loopVariable;
(...skipping 25 matching lines...) Expand all
369 if (_isEmptyStatement(forNode.body)) { 374 if (_isEmptyStatement(forNode.body)) {
370 sb.append(' '); 375 sb.append(' ');
371 _appendEmptyBraces(sb, exitPosition == null); 376 _appendEmptyBraces(sb, exitPosition == null);
372 } 377 }
373 _insertBuilder(sb); 378 _insertBuilder(sb);
374 _setCompletion(DartStatementCompletion.COMPLETE_FOR_EACH_STMT); 379 _setCompletion(DartStatementCompletion.COMPLETE_FOR_EACH_STMT);
375 return true; 380 return true;
376 } 381 }
377 382
378 bool _complete_forStatement() { 383 bool _complete_forStatement() {
379 if (errors.isEmpty || node is! ForStatement) { 384 if (node is! ForStatement) {
380 return false; 385 return false;
381 } 386 }
382 ForStatement forNode = node; 387 ForStatement forNode = node;
383 SourceBuilder sb; 388 SourceBuilder sb;
384 int delta = 0; 389 int delta = 0;
385 if (forNode.leftParenthesis.isSynthetic) { 390 if (forNode.leftParenthesis.isSynthetic) {
386 if (!forNode.rightParenthesis.isSynthetic) { 391 if (!forNode.rightParenthesis.isSynthetic) {
387 return false; 392 return false;
388 } 393 }
389 // keywordOnly (unit test name suffix that exercises this branch) 394 // keywordOnly (unit test name suffix that exercises this branch)
390 sb = _sourceBuilderAfterKeyword(forNode.forKeyword); 395 sb = _sourceBuilderAfterKeyword(forNode.forKeyword);
391 sb.append('('); 396 sb.append('(');
392 sb.setExitOffset(); 397 sb.setExitOffset();
393 sb.append(')'); 398 sb.append(')');
394 } else { 399 } else {
395 if (!forNode.rightSeparator.isSynthetic) { 400 if (!forNode.rightSeparator.isSynthetic) {
396 // Fully-defined init, cond, updaters so nothing more needed here. 401 // Fully-defined init, cond, updaters so nothing more needed here.
397 // emptyParts 402 // emptyParts
398 sb = new SourceBuilder(file, forNode.rightParenthesis.offset + 1); 403 sb = new SourceBuilder(file, forNode.rightParenthesis.offset + 1);
399 } else if (!forNode.leftSeparator.isSynthetic) { 404 } else if (!forNode.leftSeparator.isSynthetic) {
400 if (_isSyntheticExpression(forNode.condition)) { 405 if (_isSyntheticExpression(forNode.condition)) {
401 exitPosition = _newPosition(forNode.leftSeparator.offset + 1); 406 exitPosition = _newPosition(forNode.leftSeparator.offset + 1);
402 String text = utils 407 String text = utils
403 .getNodeText(forNode) 408 .getNodeText(forNode)
404 .substring(forNode.leftSeparator.offset - forNode.offset); 409 .substring(forNode.leftSeparator.offset - forNode.offset);
405 if (text.startsWith(new RegExp(r';\s*\)'))) { 410 if (text.startsWith(new RegExp(r';\s*\)'))) {
406 // emptyCondition 411 // emptyCondition
407 int end = text.indexOf(')'); 412 int end = text.indexOf(')');
408 sb = new SourceBuilder(file, forNode.leftSeparator.offset); 413 sb = new SourceBuilder(file, forNode.leftSeparator.offset);
409 // TODO(messick) Consider adding two semicolons here. 414 _addReplaceEdit(rangeStartLength(sb.offset, end), '; ; ');
410 _addReplaceEdit(rangeStartLength(sb.offset, end), '; ');
411 delta = end - '; '.length; 415 delta = end - '; '.length;
412 } else { 416 } else {
413 // emptyInitializersEmptyCondition 417 // emptyInitializersEmptyCondition
414 exitPosition = _newPosition(forNode.rightParenthesis.offset); 418 exitPosition = _newPosition(forNode.rightParenthesis.offset);
415 sb = new SourceBuilder(file, forNode.rightParenthesis.offset); 419 sb = new SourceBuilder(file, forNode.rightParenthesis.offset);
416 } 420 }
417 } else { 421 } else {
418 // emptyUpdaters 422 // emptyUpdaters
419 exitPosition = _newPosition(forNode.rightSeparator.offset); 423 exitPosition = _newPosition(forNode.rightSeparator.offset);
420 sb = new SourceBuilder(file, forNode.rightSeparator.offset); 424 sb = new SourceBuilder(file, forNode.rightSeparator.offset);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 if (statement.block is EmptyStatement) { 470 if (statement.block is EmptyStatement) {
467 sb.append(' '); 471 sb.append(' ');
468 _appendEmptyBraces(sb, exitPosition == null); 472 _appendEmptyBraces(sb, exitPosition == null);
469 } 473 }
470 _insertBuilder(sb); 474 _insertBuilder(sb);
471 _setCompletion(kind); 475 _setCompletion(kind);
472 return true; 476 return true;
473 } 477 }
474 478
475 bool _complete_ifStatement() { 479 bool _complete_ifStatement() {
476 if (errors.isEmpty || node is! IfStatement) { 480 if (node is! IfStatement) {
477 return false; 481 return false;
478 } 482 }
479 IfStatement ifNode = node; 483 IfStatement ifNode = node;
480 if (ifNode != null) { 484 if (ifNode != null) {
481 if (ifNode.elseKeyword != null) { 485 if (ifNode.elseKeyword != null) {
482 return false; 486 return false;
483 } 487 }
484 var stmt = new _KeywordConditionBlockStructure( 488 var stmt = new _KeywordConditionBlockStructure(
485 ifNode.ifKeyword, 489 ifNode.ifKeyword,
486 ifNode.leftParenthesis, 490 ifNode.leftParenthesis,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 int insertOffset = error.offset + error.length; 543 int insertOffset = error.offset + error.length;
540 _addInsertEdit(insertOffset, ';'); 544 _addInsertEdit(insertOffset, ';');
541 int offset = _appendNewlinePlusIndent() + 1 /* ';' */; 545 int offset = _appendNewlinePlusIndent() + 1 /* ';' */;
542 _setCompletionAt(DartStatementCompletion.SIMPLE_SEMICOLON, offset); 546 _setCompletionAt(DartStatementCompletion.SIMPLE_SEMICOLON, offset);
543 return true; 547 return true;
544 } 548 }
545 return false; 549 return false;
546 } 550 }
547 551
548 bool _complete_switchStatement() { 552 bool _complete_switchStatement() {
549 if (errors.isEmpty || node is! SwitchStatement) { 553 if (node is! SwitchStatement) {
550 return false; 554 return false;
551 } 555 }
552 SourceBuilder sb; 556 SourceBuilder sb;
553 SwitchStatement switchNode = node; 557 SwitchStatement switchNode = node;
554 if (switchNode.leftParenthesis.isSynthetic && 558 if (switchNode.leftParenthesis.isSynthetic &&
555 switchNode.rightParenthesis.isSynthetic) { 559 switchNode.rightParenthesis.isSynthetic) {
556 exitPosition = new Position(file, switchNode.switchKeyword.end + 2); 560 exitPosition = new Position(file, switchNode.switchKeyword.end + 2);
557 String src = utils.getNodeText(switchNode); 561 String src = utils.getNodeText(switchNode);
558 if (src 562 if (src
559 .substring(switchNode.switchKeyword.end - switchNode.offset) 563 .substring(switchNode.switchKeyword.end - switchNode.offset)
(...skipping 19 matching lines...) Expand all
579 // See https://github.com/dart-lang/sdk/issues/29391 583 // See https://github.com/dart-lang/sdk/issues/29391
580 sb.append(' '); 584 sb.append(' ');
581 _appendEmptyBraces(sb, exitPosition == null); 585 _appendEmptyBraces(sb, exitPosition == null);
582 } 586 }
583 _insertBuilder(sb); 587 _insertBuilder(sb);
584 _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT); 588 _setCompletion(DartStatementCompletion.COMPLETE_SWITCH_STMT);
585 return true; 589 return true;
586 } 590 }
587 591
588 bool _complete_tryStatement() { 592 bool _complete_tryStatement() {
589 if (errors.isEmpty || node is! TryStatement) { 593 if (node is! TryStatement) {
590 return false; 594 return false;
591 } 595 }
592 TryStatement tryNode = node; 596 TryStatement tryNode = node;
593 SourceBuilder sb; 597 SourceBuilder sb;
594 CatchClause catchNode; 598 CatchClause catchNode;
595 bool addSpace = true; 599 bool addSpace = true;
596 if (tryNode.body.leftBracket.isSynthetic) { 600 if (tryNode.body.leftBracket.isSynthetic) {
597 String src = utils.getNodeText(tryNode); 601 String src = utils.getNodeText(tryNode);
598 if (src 602 if (src
599 .substring(tryNode.tryKeyword.end - tryNode.offset) 603 .substring(tryNode.tryKeyword.end - tryNode.offset)
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 sb.append(' '); 670 sb.append(' ');
667 _appendEmptyBraces(sb, true); 671 _appendEmptyBraces(sb, true);
668 _insertBuilder(sb); 672 _insertBuilder(sb);
669 } 673 }
670 } 674 }
671 _setCompletion(DartStatementCompletion.COMPLETE_TRY_STMT); 675 _setCompletion(DartStatementCompletion.COMPLETE_TRY_STMT);
672 return true; 676 return true;
673 } 677 }
674 678
675 bool _complete_whileStatement() { 679 bool _complete_whileStatement() {
676 if (errors.isEmpty || node is! WhileStatement) { 680 if (node is! WhileStatement) {
677 return false; 681 return false;
678 } 682 }
679 WhileStatement whileNode = node; 683 WhileStatement whileNode = node;
680 if (whileNode != null) { 684 if (whileNode != null) {
681 var stmt = new _KeywordConditionBlockStructure( 685 var stmt = new _KeywordConditionBlockStructure(
682 whileNode.whileKeyword, 686 whileNode.whileKeyword,
683 whileNode.leftParenthesis, 687 whileNode.leftParenthesis,
684 whileNode.condition, 688 whileNode.condition,
685 whileNode.rightParenthesis, 689 whileNode.rightParenthesis,
686 whileNode.body); 690 whileNode.body);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 final Token keyword; 806 final Token keyword;
803 final Token leftParenthesis, rightParenthesis; 807 final Token leftParenthesis, rightParenthesis;
804 final Expression condition; 808 final Expression condition;
805 final Statement block; 809 final Statement block;
806 810
807 _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis, 811 _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis,
808 this.condition, this.rightParenthesis, this.block); 812 this.condition, this.rightParenthesis, this.block);
809 813
810 int get offset => keyword.offset; 814 int get offset => keyword.offset;
811 } 815 }
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