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 edit.domain; | 5 library edit.domain; | 
| 6 | 6 | 
| 7 import 'dart:async'; | 7 import 'dart:async'; | 
| 8 | 8 | 
| 9 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; | 9 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; | 
| 10 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; | 10 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; | 
| 11 import 'package:analysis_server/src/analysis_server.dart'; | 11 import 'package:analysis_server/src/analysis_server.dart'; | 
| 12 import 'package:analysis_server/src/collections.dart'; | 12 import 'package:analysis_server/src/collections.dart'; | 
| 13 import 'package:analysis_server/src/constants.dart'; | 13 import 'package:analysis_server/src/constants.dart'; | 
| 14 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 14 import 'package:analysis_server/src/protocol_server.dart' hide Element; | 
| 15 import 'package:analysis_server/src/services/correction/assist.dart'; | 15 import 'package:analysis_server/src/services/correction/assist.dart'; | 
| 16 import 'package:analysis_server/src/services/correction/fix.dart'; | 16 import 'package:analysis_server/src/services/correction/fix.dart'; | 
| 17 import 'package:analysis_server/src/services/correction/organize_directives.dart '; | 17 import 'package:analysis_server/src/services/correction/organize_directives.dart '; | 
| 18 import 'package:analysis_server/src/services/correction/sort_members.dart'; | 18 import 'package:analysis_server/src/services/correction/sort_members.dart'; | 
| 19 import 'package:analysis_server/src/services/correction/status.dart'; | 19 import 'package:analysis_server/src/services/correction/status.dart'; | 
| 20 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 20 import 'package:analysis_server/src/services/refactoring/refactoring.dart'; | 
| 21 import 'package:analysis_server/src/services/search/search_engine.dart'; | 21 import 'package:analysis_server/src/services/search/search_engine.dart'; | 
| 22 import 'package:analyzer/dart/ast/ast.dart'; | 22 import 'package:analyzer/dart/ast/ast.dart'; | 
| 23 import 'package:analyzer/dart/element/element.dart'; | 23 import 'package:analyzer/dart/element/element.dart'; | 
| 24 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine; | 24 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine; | 
| 25 import 'package:analyzer/src/generated/engine.dart' as engine; | 25 import 'package:analyzer/src/generated/engine.dart' as engine; | 
| 26 import 'package:analyzer/src/generated/error.dart' as engine; | 26 import 'package:analyzer/src/generated/error.dart' as engine; | 
| 27 import 'package:analyzer/src/generated/parser.dart' as engine; | 27 import 'package:analyzer/src/generated/parser.dart' as engine; | 
| 28 import 'package:analyzer/src/generated/source.dart'; | 28 import 'package:analyzer/src/generated/source.dart'; | 
| 29 import 'package:analyzer/task/dart.dart'; | |
| 29 import 'package:dart_style/dart_style.dart'; | 30 import 'package:dart_style/dart_style.dart'; | 
| 30 | 31 | 
| 32 int test_resetCount = 0; | |
| 33 | |
| 31 bool test_simulateRefactoringException_change = false; | 34 bool test_simulateRefactoringException_change = false; | 
| 32 bool test_simulateRefactoringException_final = false; | 35 bool test_simulateRefactoringException_final = false; | 
| 33 bool test_simulateRefactoringException_init = false; | 36 bool test_simulateRefactoringException_init = false; | 
| 34 | 37 | 
| 35 bool test_simulateRefactoringReset_afterCreateChange = false; | 38 bool test_simulateRefactoringReset_afterCreateChange = false; | 
| 36 bool test_simulateRefactoringReset_afterFinalConditions = false; | 39 bool test_simulateRefactoringReset_afterFinalConditions = false; | 
| 37 bool test_simulateRefactoringReset_afterInitialConditions = false; | 40 bool test_simulateRefactoringReset_afterInitialConditions = false; | 
| 38 | 41 | 
| 39 /** | 42 /** | 
| 40 * Instances of the class [EditDomainHandler] implement a [RequestHandler] | 43 * Instances of the class [EditDomainHandler] implement a [RequestHandler] | 
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 * | 372 * | 
| 370 * Once new set of parameters is received, the previous [Refactoring] instance | 373 * Once new set of parameters is received, the previous [Refactoring] instance | 
| 371 * is invalidated and a new one is created and initialized. | 374 * is invalidated and a new one is created and initialized. | 
| 372 */ | 375 */ | 
| 373 class _RefactoringManager { | 376 class _RefactoringManager { | 
| 374 static const List<RefactoringProblem> EMPTY_PROBLEM_LIST = | 377 static const List<RefactoringProblem> EMPTY_PROBLEM_LIST = | 
| 375 const <RefactoringProblem>[]; | 378 const <RefactoringProblem>[]; | 
| 376 | 379 | 
| 377 final AnalysisServer server; | 380 final AnalysisServer server; | 
| 378 final SearchEngine searchEngine; | 381 final SearchEngine searchEngine; | 
| 379 StreamSubscription onAnalysisStartedSubscription; | 382 StreamSubscription subscriptionToReset; | 
| 380 | 383 | 
| 381 RefactoringKind kind; | 384 RefactoringKind kind; | 
| 382 String file; | 385 String file; | 
| 383 int offset; | 386 int offset; | 
| 384 int length; | 387 int length; | 
| 385 Refactoring refactoring; | 388 Refactoring refactoring; | 
| 386 RefactoringFeedback feedback; | 389 RefactoringFeedback feedback; | 
| 387 RefactoringStatus initStatus; | 390 RefactoringStatus initStatus; | 
| 388 RefactoringStatus optionsStatus; | 391 RefactoringStatus optionsStatus; | 
| 389 RefactoringStatus finalStatus; | 392 RefactoringStatus finalStatus; | 
| 390 | 393 | 
| 391 Request request; | 394 Request request; | 
| 392 EditGetRefactoringResult result; | 395 EditGetRefactoringResult result; | 
| 393 | 396 | 
| 394 _RefactoringManager(this.server, this.searchEngine) { | 397 _RefactoringManager(this.server, this.searchEngine) { | 
| 395 onAnalysisStartedSubscription = server.onAnalysisStarted.listen(_reset); | |
| 396 _reset(); | 398 _reset(); | 
| 397 } | 399 } | 
| 398 | 400 | 
| 399 /** | 401 /** | 
| 400 * Returns `true` if a response for the current request has not yet been sent. | 402 * Returns `true` if a response for the current request has not yet been sent. | 
| 401 */ | 403 */ | 
| 402 bool get hasPendingRequest => request != null; | 404 bool get hasPendingRequest => request != null; | 
| 403 | 405 | 
| 404 bool get _hasFatalError { | 406 bool get _hasFatalError { | 
| 405 return initStatus.hasFatalError || | 407 return initStatus.hasFatalError || | 
| 406 optionsStatus.hasFatalError || | 408 optionsStatus.hasFatalError || | 
| 407 finalStatus.hasFatalError; | 409 finalStatus.hasFatalError; | 
| 408 } | 410 } | 
| 409 | 411 | 
| 410 /** | 412 /** | 
| 411 * Checks if [refactoring] requires options. | 413 * Checks if [refactoring] requires options. | 
| 412 */ | 414 */ | 
| 413 bool get _requiresOptions { | 415 bool get _requiresOptions { | 
| 414 return refactoring is ExtractLocalRefactoring || | 416 return refactoring is ExtractLocalRefactoring || | 
| 415 refactoring is ExtractMethodRefactoring || | 417 refactoring is ExtractMethodRefactoring || | 
| 416 refactoring is InlineMethodRefactoring || | 418 refactoring is InlineMethodRefactoring || | 
| 417 refactoring is MoveFileRefactoring || | 419 refactoring is MoveFileRefactoring || | 
| 418 refactoring is RenameRefactoring; | 420 refactoring is RenameRefactoring; | 
| 419 } | 421 } | 
| 420 | 422 | 
| 421 /** | 423 /** | 
| 422 * Cancels processing of the current request and cleans up. | 424 * Cancels processing of the current request and cleans up. | 
| 423 */ | 425 */ | 
| 424 void cancel() { | 426 void cancel() { | 
| 425 onAnalysisStartedSubscription.cancel(); | 427 subscriptionToReset?.cancel(); | 
| 428 subscriptionToReset = null; | |
| 426 server.sendResponse(new Response.refactoringRequestCancelled(request)); | 429 server.sendResponse(new Response.refactoringRequestCancelled(request)); | 
| 427 request = null; | 430 request = null; | 
| 428 } | 431 } | 
| 429 | 432 | 
| 430 void getRefactoring(Request _request) { | 433 void getRefactoring(Request _request) { | 
| 431 // prepare for processing the request | 434 // prepare for processing the request | 
| 432 request = _request; | 435 request = _request; | 
| 433 result = new EditGetRefactoringResult( | 436 result = new EditGetRefactoringResult( | 
| 434 EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST); | 437 EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST); | 
| 435 // process the request | 438 // process the request | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 cancel(); | 488 cancel(); | 
| 486 } else { | 489 } else { | 
| 487 server.instrumentationService.logException(exception, stackTrace); | 490 server.instrumentationService.logException(exception, stackTrace); | 
| 488 server.sendResponse( | 491 server.sendResponse( | 
| 489 new Response.serverError(_request, exception, stackTrace)); | 492 new Response.serverError(_request, exception, stackTrace)); | 
| 490 } | 493 } | 
| 491 _reset(); | 494 _reset(); | 
| 492 }); | 495 }); | 
| 493 } | 496 } | 
| 494 | 497 | 
| 498 /** | |
| 499 * Perform enough analysis to be able to perform refactoring of the given | |
| 500 * [kind] in the given [file]. | |
| 501 */ | |
| 502 Future<Null> _analyzeForRefactoring(String file, RefactoringKind kind) async { | |
| 503 // "Extract Local" and "Inline Local" refactorings need only local analysis. | |
| 504 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE || | |
| 505 kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { | |
| 506 ContextSourcePair pair = server.getContextSourcePair(file); | |
| 507 engine.AnalysisContext context = pair.context; | |
| 508 Source source = pair.source; | |
| 509 if (context != null && source != null) { | |
| 510 if (context.computeResult(source, SOURCE_KIND) == SourceKind.LIBRARY) { | |
| 511 await context.computeResolvedCompilationUnitAsync(source, source); | |
| 512 return; | |
| 513 } | |
| 514 } | |
| 515 } | |
| 516 // A refactoring for which we cannot optimize analysis. | |
| 517 // So, wait for full analysis. | |
| 518 await server.onAnalysisComplete; | |
| 519 } | |
| 520 | |
| 495 void _checkForReset_afterCreateChange() { | 521 void _checkForReset_afterCreateChange() { | 
| 496 if (test_simulateRefactoringReset_afterCreateChange) { | 522 if (test_simulateRefactoringReset_afterCreateChange) { | 
| 497 _reset(); | 523 _reset(); | 
| 498 } | 524 } | 
| 499 if (refactoring == null) { | 525 if (refactoring == null) { | 
| 500 throw new _ResetError(); | 526 throw new _ResetError(); | 
| 501 } | 527 } | 
| 502 } | 528 } | 
| 503 | 529 | 
| 504 void _checkForReset_afterFinalConditions() { | 530 void _checkForReset_afterFinalConditions() { | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 518 throw new _ResetError(); | 544 throw new _ResetError(); | 
| 519 } | 545 } | 
| 520 } | 546 } | 
| 521 | 547 | 
| 522 /** | 548 /** | 
| 523 * Initializes this context to perform a refactoring with the specified | 549 * Initializes this context to perform a refactoring with the specified | 
| 524 * parameters. The existing [Refactoring] is reused or created as needed. | 550 * parameters. The existing [Refactoring] is reused or created as needed. | 
| 525 */ | 551 */ | 
| 526 Future _init( | 552 Future _init( | 
| 527 RefactoringKind kind, String file, int offset, int length) async { | 553 RefactoringKind kind, String file, int offset, int length) async { | 
| 528 await server.onAnalysisComplete; | 554 await _analyzeForRefactoring(file, kind); | 
| 529 // check if we can continue with the existing Refactoring instance | 555 // check if we can continue with the existing Refactoring instance | 
| 530 if (this.kind == kind && | 556 if (this.kind == kind && | 
| 531 this.file == file && | 557 this.file == file && | 
| 532 this.offset == offset && | 558 this.offset == offset && | 
| 533 this.length == length) { | 559 this.length == length) { | 
| 534 return; | 560 return; | 
| 535 } | 561 } | 
| 536 _reset(); | 562 _reset(); | 
| 537 this.kind = kind; | 563 this.kind = kind; | 
| 538 this.file = file; | 564 this.file = file; | 
| 539 this.offset = offset; | 565 this.offset = offset; | 
| 540 this.length = length; | 566 this.length = length; | 
| 541 // simulate an exception | 567 // simulate an exception | 
| 542 if (test_simulateRefactoringException_init) { | 568 if (test_simulateRefactoringException_init) { | 
| 543 throw 'A simulated refactoring exception - init.'; | 569 throw 'A simulated refactoring exception - init.'; | 
| 544 } | 570 } | 
| 545 // create a new Refactoring instance | 571 // create a new Refactoring instance | 
| 546 if (kind == RefactoringKind.CONVERT_GETTER_TO_METHOD) { | 572 if (kind == RefactoringKind.CONVERT_GETTER_TO_METHOD) { | 
| 547 List<Element> elements = server.getElementsAtOffset(file, offset); | 573 List<Element> elements = server.getElementsAtOffset(file, offset); | 
| 548 if (elements.isNotEmpty) { | 574 if (elements.isNotEmpty) { | 
| 549 Element element = elements[0]; | 575 Element element = elements[0]; | 
| 550 if (element is ExecutableElement) { | 576 if (element is ExecutableElement) { | 
| 577 _resetOnAnalysisStarted(); | |
| 551 refactoring = | 578 refactoring = | 
| 552 new ConvertGetterToMethodRefactoring(searchEngine, element); | 579 new ConvertGetterToMethodRefactoring(searchEngine, element); | 
| 553 } | 580 } | 
| 554 } | 581 } | 
| 555 } | 582 } | 
| 556 if (kind == RefactoringKind.CONVERT_METHOD_TO_GETTER) { | 583 if (kind == RefactoringKind.CONVERT_METHOD_TO_GETTER) { | 
| 557 List<Element> elements = server.getElementsAtOffset(file, offset); | 584 List<Element> elements = server.getElementsAtOffset(file, offset); | 
| 558 if (elements.isNotEmpty) { | 585 if (elements.isNotEmpty) { | 
| 559 Element element = elements[0]; | 586 Element element = elements[0]; | 
| 560 if (element is ExecutableElement) { | 587 if (element is ExecutableElement) { | 
| 588 _resetOnAnalysisStarted(); | |
| 561 refactoring = | 589 refactoring = | 
| 562 new ConvertMethodToGetterRefactoring(searchEngine, element); | 590 new ConvertMethodToGetterRefactoring(searchEngine, element); | 
| 563 } | 591 } | 
| 564 } | 592 } | 
| 565 } | 593 } | 
| 566 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { | 594 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) { | 
| 567 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 595 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 
| 568 if (units.isNotEmpty) { | 596 if (units.isNotEmpty) { | 
| 597 _resetOnFileResolutionChanged(file); | |
| 569 refactoring = new ExtractLocalRefactoring(units[0], offset, length); | 598 refactoring = new ExtractLocalRefactoring(units[0], offset, length); | 
| 570 feedback = new ExtractLocalVariableFeedback( | 599 feedback = new ExtractLocalVariableFeedback( | 
| 571 <String>[], <int>[], <int>[], | 600 <String>[], <int>[], <int>[], | 
| 572 coveringExpressionOffsets: <int>[], | 601 coveringExpressionOffsets: <int>[], | 
| 573 coveringExpressionLengths: <int>[]); | 602 coveringExpressionLengths: <int>[]); | 
| 574 } | 603 } | 
| 575 } | 604 } | 
| 576 if (kind == RefactoringKind.EXTRACT_METHOD) { | 605 if (kind == RefactoringKind.EXTRACT_METHOD) { | 
| 577 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 606 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 
| 578 if (units.isNotEmpty) { | 607 if (units.isNotEmpty) { | 
| 608 _resetOnAnalysisStarted(); | |
| 579 refactoring = new ExtractMethodRefactoring( | 609 refactoring = new ExtractMethodRefactoring( | 
| 580 searchEngine, units[0], offset, length); | 610 searchEngine, units[0], offset, length); | 
| 581 feedback = new ExtractMethodFeedback(offset, length, '', <String>[], | 611 feedback = new ExtractMethodFeedback(offset, length, '', <String>[], | 
| 582 false, <RefactoringMethodParameter>[], <int>[], <int>[]); | 612 false, <RefactoringMethodParameter>[], <int>[], <int>[]); | 
| 583 } | 613 } | 
| 584 } | 614 } | 
| 585 if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { | 615 if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { | 
| 586 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 616 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 
| 587 if (units.isNotEmpty) { | 617 if (units.isNotEmpty) { | 
| 618 _resetOnFileResolutionChanged(file); | |
| 588 refactoring = | 619 refactoring = | 
| 589 new InlineLocalRefactoring(searchEngine, units[0], offset); | 620 new InlineLocalRefactoring(searchEngine, units[0], offset); | 
| 590 } | 621 } | 
| 591 } | 622 } | 
| 592 if (kind == RefactoringKind.INLINE_METHOD) { | 623 if (kind == RefactoringKind.INLINE_METHOD) { | 
| 593 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 624 List<CompilationUnit> units = server.getResolvedCompilationUnits(file); | 
| 594 if (units.isNotEmpty) { | 625 if (units.isNotEmpty) { | 
| 626 _resetOnAnalysisStarted(); | |
| 595 refactoring = | 627 refactoring = | 
| 596 new InlineMethodRefactoring(searchEngine, units[0], offset); | 628 new InlineMethodRefactoring(searchEngine, units[0], offset); | 
| 597 } | 629 } | 
| 598 } | 630 } | 
| 599 if (kind == RefactoringKind.MOVE_FILE) { | 631 if (kind == RefactoringKind.MOVE_FILE) { | 
| 632 _resetOnAnalysisStarted(); | |
| 600 ContextSourcePair contextSource = server.getContextSourcePair(file); | 633 ContextSourcePair contextSource = server.getContextSourcePair(file); | 
| 601 engine.AnalysisContext context = contextSource.context; | 634 engine.AnalysisContext context = contextSource.context; | 
| 602 Source source = contextSource.source; | 635 Source source = contextSource.source; | 
| 603 refactoring = new MoveFileRefactoring( | 636 refactoring = new MoveFileRefactoring( | 
| 604 server.resourceProvider, searchEngine, context, source, file); | 637 server.resourceProvider, searchEngine, context, source, file); | 
| 605 } | 638 } | 
| 606 if (kind == RefactoringKind.RENAME) { | 639 if (kind == RefactoringKind.RENAME) { | 
| 607 List<AstNode> nodes = server.getNodesAtOffset(file, offset); | 640 List<AstNode> nodes = server.getNodesAtOffset(file, offset); | 
| 608 List<Element> elements = server.getElementsOfNodes(nodes); | 641 List<Element> elements = server.getElementsOfNodes(nodes); | 
| 609 if (nodes.isNotEmpty && elements.isNotEmpty) { | 642 if (nodes.isNotEmpty && elements.isNotEmpty) { | 
| 610 AstNode node = nodes[0]; | 643 AstNode node = nodes[0]; | 
| 611 Element element = elements[0]; | 644 Element element = elements[0]; | 
| 612 if (element is FieldFormalParameterElement) { | 645 if (element is FieldFormalParameterElement) { | 
| 613 element = (element as FieldFormalParameterElement).field; | 646 element = (element as FieldFormalParameterElement).field; | 
| 614 } | 647 } | 
| 615 // climb from "Class" in "new Class.named()" to "Class.named" | 648 // climb from "Class" in "new Class.named()" to "Class.named" | 
| 616 if (node.parent is TypeName && node.parent.parent is ConstructorName) { | 649 if (node.parent is TypeName && node.parent.parent is ConstructorName) { | 
| 617 ConstructorName constructor = node.parent.parent; | 650 ConstructorName constructor = node.parent.parent; | 
| 618 node = constructor; | 651 node = constructor; | 
| 619 element = constructor.staticElement; | 652 element = constructor.staticElement; | 
| 620 } | 653 } | 
| 621 // do create the refactoring | 654 // do create the refactoring | 
| 655 _resetOnAnalysisStarted(); | |
| 622 refactoring = new RenameRefactoring(searchEngine, element); | 656 refactoring = new RenameRefactoring(searchEngine, element); | 
| 623 feedback = | 657 feedback = | 
| 624 new RenameFeedback(node.offset, node.length, 'kind', 'oldName'); | 658 new RenameFeedback(node.offset, node.length, 'kind', 'oldName'); | 
| 625 } | 659 } | 
| 626 } | 660 } | 
| 627 if (refactoring == null) { | 661 if (refactoring == null) { | 
| 628 initStatus = | 662 initStatus = | 
| 629 new RefactoringStatus.fatal('Unable to create a refactoring'); | 663 new RefactoringStatus.fatal('Unable to create a refactoring'); | 
| 630 return; | 664 return; | 
| 631 } | 665 } | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 } | 703 } | 
| 670 } | 704 } | 
| 671 if (refactoring is RenameRefactoring) { | 705 if (refactoring is RenameRefactoring) { | 
| 672 RenameRefactoring refactoring = this.refactoring; | 706 RenameRefactoring refactoring = this.refactoring; | 
| 673 RenameFeedback feedback = this.feedback; | 707 RenameFeedback feedback = this.feedback; | 
| 674 feedback.elementKindName = refactoring.elementKindName; | 708 feedback.elementKindName = refactoring.elementKindName; | 
| 675 feedback.oldName = refactoring.oldName; | 709 feedback.oldName = refactoring.oldName; | 
| 676 } | 710 } | 
| 677 } | 711 } | 
| 678 | 712 | 
| 679 void _reset([engine.AnalysisContext context]) { | 713 void _reset() { | 
| 714 test_resetCount++; | |
| 680 kind = null; | 715 kind = null; | 
| 681 offset = null; | 716 offset = null; | 
| 682 length = null; | 717 length = null; | 
| 683 refactoring = null; | 718 refactoring = null; | 
| 684 feedback = null; | 719 feedback = null; | 
| 685 initStatus = new RefactoringStatus(); | 720 initStatus = new RefactoringStatus(); | 
| 686 optionsStatus = new RefactoringStatus(); | 721 optionsStatus = new RefactoringStatus(); | 
| 687 finalStatus = new RefactoringStatus(); | 722 finalStatus = new RefactoringStatus(); | 
| 723 subscriptionToReset?.cancel(); | |
| 724 subscriptionToReset = null; | |
| 725 } | |
| 726 | |
| 727 void _resetOnAnalysisStarted() { | |
| 728 subscriptionToReset = server.onAnalysisStarted.listen((_) => _reset()); | |
| 
 
Brian Wilkerson
2016/08/22 23:32:23
Should we assert that `subscriptionToReset` is nul
 
scheglov
2016/08/23 01:55:28
Well, we need to at least cancel the current subsc
 
 | |
| 729 } | |
| 730 | |
| 731 /** | |
| 732 * We're performing a refactoring that affects only the given [file]. | |
| 733 * So, when the [file] resolution is changed, we need to reset refactoring. | |
| 734 * But when any other file is changed or analyzer, we can continue. | |
| 735 */ | |
| 736 void _resetOnFileResolutionChanged(String file) { | |
| 737 engine.AnalysisContext context = server.getAnalysisContext(file); | |
| 738 subscriptionToReset = | |
| 739 context?.onResultChanged(RESOLVED_UNIT)?.listen((event) { | |
| 740 Source targetSource = event.target.source; | |
| 741 if (targetSource?.fullName == file) { | |
| 742 _reset(); | |
| 743 } | |
| 744 }); | |
| 688 } | 745 } | 
| 689 | 746 | 
| 690 void _sendResultResponse() { | 747 void _sendResultResponse() { | 
| 691 // ignore if was cancelled | 748 // ignore if was cancelled | 
| 692 if (request == null) { | 749 if (request == null) { | 
| 693 return; | 750 return; | 
| 694 } | 751 } | 
| 695 // set feedback | 752 // set feedback | 
| 696 result.feedback = feedback; | 753 result.feedback = feedback; | 
| 697 // set problems | 754 // set problems | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 } | 803 } | 
| 747 return new RefactoringStatus(); | 804 return new RefactoringStatus(); | 
| 748 } | 805 } | 
| 749 } | 806 } | 
| 750 | 807 | 
| 751 /** | 808 /** | 
| 752 * [_RefactoringManager] throws instances of this class internally to stop | 809 * [_RefactoringManager] throws instances of this class internally to stop | 
| 753 * processing in a manager that was reset. | 810 * processing in a manager that was reset. | 
| 754 */ | 811 */ | 
| 755 class _ResetError {} | 812 class _ResetError {} | 
| OLD | NEW |