| 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; | 7 import 'package:analysis_server/plugin/edit/assist/assist_core.dart'; |
| 8 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; | 8 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart'; |
| 9 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; | 9 import 'package:analysis_server/plugin/edit/fix/fix_core.dart'; |
| 10 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; | 10 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart'; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 import 'package:analyzer/error/error.dart' as engine; | 29 import 'package:analyzer/error/error.dart' as engine; |
| 30 import 'package:analyzer/file_system/file_system.dart'; | 30 import 'package:analyzer/file_system/file_system.dart'; |
| 31 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; | 31 import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart'; |
| 32 import 'package:analyzer/src/dart/analysis/driver.dart'; | 32 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 33 import 'package:analyzer/src/dart/element/ast_provider.dart'; | 33 import 'package:analyzer/src/dart/element/ast_provider.dart'; |
| 34 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine; | 34 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine; |
| 35 import 'package:analyzer/src/error/codes.dart' as engine; | 35 import 'package:analyzer/src/error/codes.dart' as engine; |
| 36 import 'package:analyzer/src/generated/engine.dart' as engine; | 36 import 'package:analyzer/src/generated/engine.dart' as engine; |
| 37 import 'package:analyzer/src/generated/parser.dart' as engine; | 37 import 'package:analyzer/src/generated/parser.dart' as engine; |
| 38 import 'package:analyzer/src/generated/source.dart'; | 38 import 'package:analyzer/src/generated/source.dart'; |
| 39 import 'package:analyzer/task/dart.dart'; | |
| 40 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; | 39 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin; |
| 41 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin; | 40 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin; |
| 42 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; | 41 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin; |
| 43 import 'package:dart_style/dart_style.dart'; | 42 import 'package:dart_style/dart_style.dart'; |
| 44 | 43 |
| 45 int test_resetCount = 0; | 44 int test_resetCount = 0; |
| 46 | 45 |
| 47 bool test_simulateRefactoringException_change = false; | 46 bool test_simulateRefactoringException_change = false; |
| 48 bool test_simulateRefactoringException_final = false; | 47 bool test_simulateRefactoringException_final = false; |
| 49 bool test_simulateRefactoringException_init = false; | 48 bool test_simulateRefactoringException_init = false; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 75 _newRefactoringManager(); | 74 _newRefactoringManager(); |
| 76 } | 75 } |
| 77 | 76 |
| 78 Response format(Request request) { | 77 Response format(Request request) { |
| 79 EditFormatParams params = new EditFormatParams.fromRequest(request); | 78 EditFormatParams params = new EditFormatParams.fromRequest(request); |
| 80 String file = params.file; | 79 String file = params.file; |
| 81 | 80 |
| 82 String unformattedSource; | 81 String unformattedSource; |
| 83 try { | 82 try { |
| 84 Source source = server.resourceProvider.getFile(file).createSource(); | 83 Source source = server.resourceProvider.getFile(file).createSource(); |
| 85 if (server.options.enableNewAnalysisDriver) { | 84 unformattedSource = |
| 86 unformattedSource = server.fileContentOverlay[file]; | 85 server.fileContentOverlay[file] ?? source.contents.data; |
| 87 } else { | |
| 88 unformattedSource = server.overlayState.getContents(source); | |
| 89 } | |
| 90 unformattedSource ??= source.contents.data; | |
| 91 } catch (e) { | 86 } catch (e) { |
| 92 return new Response.formatInvalidFile(request); | 87 return new Response.formatInvalidFile(request); |
| 93 } | 88 } |
| 94 | 89 |
| 95 int start = params.selectionOffset; | 90 int start = params.selectionOffset; |
| 96 int length = params.selectionLength; | 91 int length = params.selectionLength; |
| 97 | 92 |
| 98 // No need to preserve 0,0 selection | 93 // No need to preserve 0,0 selection |
| 99 if (start == 0 && length == 0) { | 94 if (start == 0 && length == 0) { |
| 100 start = null; | 95 start = null; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 | 333 |
| 339 Future<Null> organizeDirectives(Request request) async { | 334 Future<Null> organizeDirectives(Request request) async { |
| 340 var params = new EditOrganizeDirectivesParams.fromRequest(request); | 335 var params = new EditOrganizeDirectivesParams.fromRequest(request); |
| 341 // prepare file | 336 // prepare file |
| 342 String file = params.file; | 337 String file = params.file; |
| 343 if (!engine.AnalysisEngine.isDartFileName(file)) { | 338 if (!engine.AnalysisEngine.isDartFileName(file)) { |
| 344 server.sendResponse(new Response.fileNotAnalyzed(request, file)); | 339 server.sendResponse(new Response.fileNotAnalyzed(request, file)); |
| 345 return; | 340 return; |
| 346 } | 341 } |
| 347 // Prepare the file information. | 342 // Prepare the file information. |
| 348 int fileStamp; | 343 AnalysisResult result = await server.getAnalysisResult(file); |
| 349 String code; | 344 if (result == null) { |
| 350 CompilationUnit unit; | 345 server.sendResponse(new Response.fileNotAnalyzed(request, file)); |
| 351 List<engine.AnalysisError> errors; | 346 return; |
| 352 if (server.options.enableNewAnalysisDriver) { | |
| 353 AnalysisResult result = await server.getAnalysisResult(file); | |
| 354 if (result == null) { | |
| 355 server.sendResponse(new Response.fileNotAnalyzed(request, file)); | |
| 356 return; | |
| 357 } | |
| 358 fileStamp = -1; | |
| 359 code = result.content; | |
| 360 unit = result.unit; | |
| 361 errors = result.errors; | |
| 362 } else { | |
| 363 // prepare resolved unit | |
| 364 unit = await server.getResolvedCompilationUnit(file); | |
| 365 if (unit == null) { | |
| 366 server.sendResponse(new Response.fileNotAnalyzed(request, file)); | |
| 367 return; | |
| 368 } | |
| 369 // prepare context | |
| 370 CompilationUnitElement compilationUnitElement = | |
| 371 resolutionMap.elementDeclaredByCompilationUnit(unit); | |
| 372 engine.AnalysisContext context = compilationUnitElement.context; | |
| 373 Source source = compilationUnitElement.source; | |
| 374 errors = context.computeErrors(source); | |
| 375 // prepare code | |
| 376 fileStamp = context.getModificationStamp(source); | |
| 377 code = context.getContents(source).data; | |
| 378 } | 347 } |
| 348 int fileStamp = -1; |
| 349 String code = result.content; |
| 350 CompilationUnit unit = result.unit; |
| 351 List<engine.AnalysisError> errors = result.errors; |
| 379 // check if there are scan/parse errors in the file | 352 // check if there are scan/parse errors in the file |
| 380 int numScanParseErrors = _getNumberOfScanParseErrors(errors); | 353 int numScanParseErrors = _getNumberOfScanParseErrors(errors); |
| 381 if (numScanParseErrors != 0) { | 354 if (numScanParseErrors != 0) { |
| 382 server.sendResponse(new Response.organizeDirectivesError( | 355 server.sendResponse(new Response.organizeDirectivesError( |
| 383 request, 'File has $numScanParseErrors scan/parse errors.')); | 356 request, 'File has $numScanParseErrors scan/parse errors.')); |
| 384 return; | 357 return; |
| 385 } | 358 } |
| 386 // do organize | 359 // do organize |
| 387 DirectiveOrganizer sorter = new DirectiveOrganizer(code, unit, errors); | 360 DirectiveOrganizer sorter = new DirectiveOrganizer(code, unit, errors); |
| 388 List<SourceEdit> edits = sorter.organize(); | 361 List<SourceEdit> edits = sorter.organize(); |
| 389 SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits); | 362 SourceFileEdit fileEdit = new SourceFileEdit(file, fileStamp, edits: edits); |
| 390 server.sendResponse( | 363 server.sendResponse( |
| 391 new EditOrganizeDirectivesResult(fileEdit).toResponse(request.id)); | 364 new EditOrganizeDirectivesResult(fileEdit).toResponse(request.id)); |
| 392 } | 365 } |
| 393 | 366 |
| 394 Future<Null> sortMembers(Request request) async { | 367 Future<Null> sortMembers(Request request) async { |
| 395 var params = new EditSortMembersParams.fromRequest(request); | 368 var params = new EditSortMembersParams.fromRequest(request); |
| 396 // prepare file | 369 // prepare file |
| 397 String file = params.file; | 370 String file = params.file; |
| 398 if (!engine.AnalysisEngine.isDartFileName(file)) { | 371 if (!engine.AnalysisEngine.isDartFileName(file)) { |
| 399 server.sendResponse(new Response.sortMembersInvalidFile(request)); | 372 server.sendResponse(new Response.sortMembersInvalidFile(request)); |
| 400 return; | 373 return; |
| 401 } | 374 } |
| 402 // Prepare the file information. | 375 // Prepare the file information. |
| 403 int fileStamp; | 376 AnalysisDriver driver = server.getAnalysisDriver(file); |
| 404 String code; | 377 ParseResult result = await driver?.parseFile(file); |
| 405 CompilationUnit unit; | 378 if (result == null) { |
| 406 List<engine.AnalysisError> errors; | 379 server.sendResponse(new Response.fileNotAnalyzed(request, file)); |
| 407 if (server.options.enableNewAnalysisDriver) { | 380 return; |
| 408 AnalysisDriver driver = server.getAnalysisDriver(file); | |
| 409 ParseResult result = await driver?.parseFile(file); | |
| 410 if (result == null) { | |
| 411 server.sendResponse(new Response.fileNotAnalyzed(request, file)); | |
| 412 return; | |
| 413 } | |
| 414 fileStamp = -1; | |
| 415 code = result.content; | |
| 416 unit = result.unit; | |
| 417 errors = result.errors; | |
| 418 } else { | |
| 419 // prepare location | |
| 420 ContextSourcePair contextSource = server.getContextSourcePair(file); | |
| 421 engine.AnalysisContext context = contextSource.context; | |
| 422 Source source = contextSource.source; | |
| 423 if (context == null || source == null) { | |
| 424 server.sendResponse(new Response.sortMembersInvalidFile(request)); | |
| 425 return; | |
| 426 } | |
| 427 // prepare code | |
| 428 fileStamp = context.getModificationStamp(source); | |
| 429 code = context.getContents(source).data; | |
| 430 // prepare parsed unit | |
| 431 try { | |
| 432 unit = context.parseCompilationUnit(source); | |
| 433 } catch (e) { | |
| 434 server.sendResponse(new Response.sortMembersInvalidFile(request)); | |
| 435 return; | |
| 436 } | |
| 437 // Get the errors. | |
| 438 errors = context.getErrors(source).errors; | |
| 439 } | 381 } |
| 382 int fileStamp = -1; |
| 383 String code = result.content; |
| 384 CompilationUnit unit = result.unit; |
| 385 List<engine.AnalysisError> errors = result.errors; |
| 440 // Check if there are scan/parse errors in the file. | 386 // Check if there are scan/parse errors in the file. |
| 441 int numScanParseErrors = _getNumberOfScanParseErrors(errors); | 387 int numScanParseErrors = _getNumberOfScanParseErrors(errors); |
| 442 if (numScanParseErrors != 0) { | 388 if (numScanParseErrors != 0) { |
| 443 server.sendResponse( | 389 server.sendResponse( |
| 444 new Response.sortMembersParseErrors(request, numScanParseErrors)); | 390 new Response.sortMembersParseErrors(request, numScanParseErrors)); |
| 445 return; | 391 return; |
| 446 } | 392 } |
| 447 // Do sort. | 393 // Do sort. |
| 448 MemberSorter sorter = new MemberSorter(code, unit); | 394 MemberSorter sorter = new MemberSorter(code, unit); |
| 449 List<SourceEdit> edits = sorter.sort(); | 395 List<SourceEdit> edits = sorter.sort(); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 cancel(); | 652 cancel(); |
| 707 } else { | 653 } else { |
| 708 server.instrumentationService.logException(exception, stackTrace); | 654 server.instrumentationService.logException(exception, stackTrace); |
| 709 server.sendResponse( | 655 server.sendResponse( |
| 710 new Response.serverError(_request, exception, stackTrace)); | 656 new Response.serverError(_request, exception, stackTrace)); |
| 711 } | 657 } |
| 712 _reset(); | 658 _reset(); |
| 713 }); | 659 }); |
| 714 } | 660 } |
| 715 | 661 |
| 716 /** | |
| 717 * Perform enough analysis to be able to perform refactoring of the given | |
| 718 * [kind] in the given [file]. | |
| 719 */ | |
| 720 Future<Null> _analyzeForRefactoring(String file, RefactoringKind kind) async { | |
| 721 if (server.options.enableNewAnalysisDriver) { | |
| 722 return; | |
| 723 } | |
| 724 // "Extract Local" and "Inline Local" refactorings need only local analysis. | |
| 725 if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE || | |
| 726 kind == RefactoringKind.INLINE_LOCAL_VARIABLE) { | |
| 727 ContextSourcePair pair = server.getContextSourcePair(file); | |
| 728 engine.AnalysisContext context = pair.context; | |
| 729 Source source = pair.source; | |
| 730 if (context != null && source != null) { | |
| 731 if (context.computeResult(source, SOURCE_KIND) == SourceKind.LIBRARY) { | |
| 732 await context.computeResolvedCompilationUnitAsync(source, source); | |
| 733 return; | |
| 734 } | |
| 735 } | |
| 736 } | |
| 737 // A refactoring for which we cannot optimize analysis. | |
| 738 // So, wait for full analysis. | |
| 739 await server.onAnalysisComplete; | |
| 740 } | |
| 741 | |
| 742 void _checkForReset_afterCreateChange() { | 662 void _checkForReset_afterCreateChange() { |
| 743 if (test_simulateRefactoringReset_afterCreateChange) { | 663 if (test_simulateRefactoringReset_afterCreateChange) { |
| 744 _reset(); | 664 _reset(); |
| 745 } | 665 } |
| 746 if (refactoring == null) { | 666 if (refactoring == null) { |
| 747 throw new _ResetError(); | 667 throw new _ResetError(); |
| 748 } | 668 } |
| 749 } | 669 } |
| 750 | 670 |
| 751 void _checkForReset_afterFinalConditions() { | 671 void _checkForReset_afterFinalConditions() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 765 throw new _ResetError(); | 685 throw new _ResetError(); |
| 766 } | 686 } |
| 767 } | 687 } |
| 768 | 688 |
| 769 /** | 689 /** |
| 770 * Initializes this context to perform a refactoring with the specified | 690 * Initializes this context to perform a refactoring with the specified |
| 771 * parameters. The existing [Refactoring] is reused or created as needed. | 691 * parameters. The existing [Refactoring] is reused or created as needed. |
| 772 */ | 692 */ |
| 773 Future _init( | 693 Future _init( |
| 774 RefactoringKind kind, String file, int offset, int length) async { | 694 RefactoringKind kind, String file, int offset, int length) async { |
| 775 await _analyzeForRefactoring(file, kind); | |
| 776 // check if we can continue with the existing Refactoring instance | 695 // check if we can continue with the existing Refactoring instance |
| 777 if (this.kind == kind && | 696 if (this.kind == kind && |
| 778 this.file == file && | 697 this.file == file && |
| 779 this.offset == offset && | 698 this.offset == offset && |
| 780 this.length == length) { | 699 this.length == length) { |
| 781 return; | 700 return; |
| 782 } | 701 } |
| 783 _reset(); | 702 _reset(); |
| 784 this.kind = kind; | 703 this.kind = kind; |
| 785 this.file = file; | 704 this.file = file; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 } | 760 } |
| 842 if (kind == RefactoringKind.INLINE_METHOD) { | 761 if (kind == RefactoringKind.INLINE_METHOD) { |
| 843 CompilationUnit unit = await server.getResolvedCompilationUnit(file); | 762 CompilationUnit unit = await server.getResolvedCompilationUnit(file); |
| 844 if (unit != null) { | 763 if (unit != null) { |
| 845 _resetOnAnalysisStarted(); | 764 _resetOnAnalysisStarted(); |
| 846 refactoring = new InlineMethodRefactoring( | 765 refactoring = new InlineMethodRefactoring( |
| 847 searchEngine, server.getAstProvider(file), unit, offset); | 766 searchEngine, server.getAstProvider(file), unit, offset); |
| 848 } | 767 } |
| 849 } | 768 } |
| 850 if (kind == RefactoringKind.MOVE_FILE) { | 769 if (kind == RefactoringKind.MOVE_FILE) { |
| 851 _resetOnAnalysisStarted(); | 770 // TODO(brianwilkerson) Re-implement this refactoring under the new analys
is driver |
| 852 ContextSourcePair contextSource = server.getContextSourcePair(file); | 771 // _resetOnAnalysisStarted(); |
| 853 engine.AnalysisContext context = contextSource.context; | 772 // ContextSourcePair contextSource = server.getContextSourcePair(file); |
| 854 Source source = contextSource.source; | 773 // engine.AnalysisContext context = contextSource.context; |
| 855 refactoring = new MoveFileRefactoring( | 774 // Source source = contextSource.source; |
| 856 server.resourceProvider, searchEngine, context, source, file); | 775 // refactoring = new MoveFileRefactoring( |
| 776 // server.resourceProvider, searchEngine, context, source, file); |
| 857 } | 777 } |
| 858 if (kind == RefactoringKind.RENAME) { | 778 if (kind == RefactoringKind.RENAME) { |
| 859 AstNode node = await server.getNodeAtOffset(file, offset); | 779 AstNode node = await server.getNodeAtOffset(file, offset); |
| 860 Element element = server.getElementOfNode(node); | 780 Element element = server.getElementOfNode(node); |
| 861 if (node != null && element != null) { | 781 if (node != null && element != null) { |
| 862 if (element is FieldFormalParameterElement) { | 782 if (element is FieldFormalParameterElement) { |
| 863 element = (element as FieldFormalParameterElement).field; | 783 element = (element as FieldFormalParameterElement).field; |
| 864 } | 784 } |
| 865 // climb from "Class" in "new Class.named()" to "Class.named" | 785 // climb from "Class" in "new Class.named()" to "Class.named" |
| 866 if (node.parent is TypeName && node.parent.parent is ConstructorName) { | 786 if (node.parent is TypeName && node.parent.parent is ConstructorName) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 subscriptionToReset?.cancel(); | 866 subscriptionToReset?.cancel(); |
| 947 subscriptionToReset = server.onAnalysisStarted.listen((_) => _reset()); | 867 subscriptionToReset = server.onAnalysisStarted.listen((_) => _reset()); |
| 948 } | 868 } |
| 949 | 869 |
| 950 /** | 870 /** |
| 951 * We're performing a refactoring that affects only the given [file]. | 871 * We're performing a refactoring that affects only the given [file]. |
| 952 * So, when the [file] resolution is changed, we need to reset refactoring. | 872 * So, when the [file] resolution is changed, we need to reset refactoring. |
| 953 * But when any other file is changed or analyzed, we can continue. | 873 * But when any other file is changed or analyzed, we can continue. |
| 954 */ | 874 */ |
| 955 void _resetOnFileResolutionChanged(String file) { | 875 void _resetOnFileResolutionChanged(String file) { |
| 956 if (server.options.enableNewAnalysisDriver) { | 876 // TODO(brianwilkerson) Decide whether we want to implement this |
| 957 return; | 877 // functionality for the new analysis driver or whether we should remove |
| 958 } | 878 // this method. |
| 959 subscriptionToReset?.cancel(); | |
| 960 subscriptionToReset = server | |
| 961 .getAnalysisContext(file) | |
| 962 ?.onResultChanged(RESOLVED_UNIT) | |
| 963 ?.listen((event) { | |
| 964 Source targetSource = event.target.source; | |
| 965 if (targetSource?.fullName == file) { | |
| 966 _reset(); | |
| 967 } | |
| 968 }); | |
| 969 } | 879 } |
| 970 | 880 |
| 971 void _sendResultResponse() { | 881 void _sendResultResponse() { |
| 972 // ignore if was cancelled | 882 // ignore if was cancelled |
| 973 if (request == null) { | 883 if (request == null) { |
| 974 return; | 884 return; |
| 975 } | 885 } |
| 976 // set feedback | 886 // set feedback |
| 977 result.feedback = feedback; | 887 result.feedback = feedback; |
| 978 // set problems | 888 // set problems |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 } | 937 } |
| 1028 return new RefactoringStatus(); | 938 return new RefactoringStatus(); |
| 1029 } | 939 } |
| 1030 } | 940 } |
| 1031 | 941 |
| 1032 /** | 942 /** |
| 1033 * [_RefactoringManager] throws instances of this class internally to stop | 943 * [_RefactoringManager] throws instances of this class internally to stop |
| 1034 * processing in a manager that was reset. | 944 * processing in a manager that was reset. |
| 1035 */ | 945 */ |
| 1036 class _ResetError {} | 946 class _ResetError {} |
| OLD | NEW |