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

Side by Side Diff: pkg/analysis_server/test/edit/refactoring_test.dart

Issue 2262393003: 'Extract Local' and 'Inline Local' refactoring need only single file analysis. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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
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 test.edit.refactoring; 5 library test.edit.refactoring;
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/edit/edit_domain.dart'; 10 import 'package:analysis_server/src/edit/edit_domain.dart';
11 import 'package:analysis_server/src/services/index/index.dart'; 11 import 'package:analysis_server/src/services/index/index.dart';
12 import 'package:analyzer/task/dart.dart';
12 import 'package:plugin/manager.dart'; 13 import 'package:plugin/manager.dart';
13 import 'package:test_reflective_loader/test_reflective_loader.dart'; 14 import 'package:test_reflective_loader/test_reflective_loader.dart';
14 import 'package:unittest/unittest.dart' hide ERROR; 15 import 'package:unittest/unittest.dart' hide ERROR;
15 16
16 import '../analysis_abstract.dart'; 17 import '../analysis_abstract.dart';
17 import '../mocks.dart'; 18 import '../mocks.dart';
18 import '../utils.dart'; 19 import '../utils.dart';
19 20
20 main() { 21 main() {
21 initializeTestEnvironment(); 22 initializeTestEnvironment();
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 String search, String suffix, String name, bool extractAll) { 264 String search, String suffix, String name, bool extractAll) {
264 int offset = findOffset(search + suffix); 265 int offset = findOffset(search + suffix);
265 int length = search.length; 266 int length = search.length;
266 return sendExtractRequest(offset, length, name, extractAll); 267 return sendExtractRequest(offset, length, name, extractAll);
267 } 268 }
268 269
269 void tearDown() { 270 void tearDown() {
270 test_simulateRefactoringException_init = false; 271 test_simulateRefactoringException_init = false;
271 test_simulateRefactoringException_final = false; 272 test_simulateRefactoringException_final = false;
272 test_simulateRefactoringException_change = false; 273 test_simulateRefactoringException_change = false;
273 test_simulateRefactoringReset_afterInitialConditions = false;
274 test_simulateRefactoringReset_afterFinalConditions = false;
275 test_simulateRefactoringReset_afterCreateChange = false;
276 super.tearDown(); 274 super.tearDown();
277 } 275 }
278 276
277 test_analysis_onlyOneFile() async {
278 shouldWaitForFullAnalysis = false;
279 String otherFile = '$testFolder/other.dart';
280 addFile(
281 otherFile,
282 r'''
283 foo(int myName) {}
284 ''');
285 addTestFile('''
286 import 'other.dart';
287 main() {
288 foo(1 + 2);
289 }
290 ''');
291 // Start refactoring.
292 EditGetRefactoringResult result = await getRefactoringResult(() {
293 return sendStringRequest('1 + 2', 'res', true);
294 });
295 // We get the refactoring feedback....
296 ExtractLocalVariableFeedback feedback = result.feedback;
297 expect(feedback.names, contains('myName'));
298 // ...even though other.dart is not fully analyzed.
299 var otherSource = server.getContextSourcePair(otherFile).source;
300 var otherUnit = new LibrarySpecificUnit(otherSource, otherSource);
301 expect(testContext.getResult(otherUnit, RESOLVED_UNIT), isNull);
302 }
303
279 test_coveringExpressions() { 304 test_coveringExpressions() {
280 addTestFile(''' 305 addTestFile('''
281 main() { 306 main() {
282 var v = 111 + 222 + 333; 307 var v = 111 + 222 + 333;
283 } 308 }
284 '''); 309 ''');
285 return getRefactoringResult(() { 310 return getRefactoringResult(() {
286 return sendExtractRequest(testCode.indexOf('222 +'), 0, 'res', true); 311 return sendExtractRequest(testCode.indexOf('222 +'), 0, 'res', true);
287 }).then((result) { 312 }).then((result) {
288 ExtractLocalVariableFeedback feedback = result.feedback; 313 ExtractLocalVariableFeedback feedback = result.feedback;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 '''); 409 ''');
385 return getRefactoringResult(() { 410 return getRefactoringResult(() {
386 return sendStringRequest('1 + 2', 'res', true); 411 return sendStringRequest('1 + 2', 'res', true);
387 }).then((result) { 412 }).then((result) {
388 ExtractLocalVariableFeedback feedback = result.feedback; 413 ExtractLocalVariableFeedback feedback = result.feedback;
389 expect(feedback.offsets, [findOffset('1 + 2'), findOffset('1 + 2')]); 414 expect(feedback.offsets, [findOffset('1 + 2'), findOffset('1 + 2')]);
390 expect(feedback.lengths, [5, 6]); 415 expect(feedback.lengths, [5, 6]);
391 }); 416 });
392 } 417 }
393 418
394 test_reset_afterCreateChange() { 419 test_resetOnFileChange() async {
395 test_simulateRefactoringReset_afterCreateChange = true; 420 String otherFile = '$testFolder/other.dart';
421 addFile(otherFile, '// other 1');
396 addTestFile(''' 422 addTestFile('''
397 main() { 423 main() {
398 print(1 + 2); 424 foo(1 + 2);
399 } 425 }
426 foo(int myName) {}
400 '''); 427 ''');
401 return waitForTasksFinished().then((_) { 428 // Send the first request.
402 return sendStringRequest('1 + 2', 'res', true).then((response) { 429 {
403 _expectRefactoringRequestCancelled(response); 430 EditGetRefactoringResult result = await getRefactoringResult(() {
431 return sendStringRequest('1 + 2', 'res', true);
404 }); 432 });
405 }); 433 ExtractLocalVariableFeedback feedback = result.feedback;
406 } 434 expect(feedback.names, contains('myName'));
407 435 }
408 test_reset_afterFinalConditions() { 436 int initialResetCount = test_resetCount;
409 test_simulateRefactoringReset_afterFinalConditions = true; 437 // Update the other.dart file.
410 addTestFile(''' 438 // The refactoring is not reset, because it's a different file.
439 addFile(otherFile, '// other 2');
440 await pumpEventQueue();
441 expect(test_resetCount, initialResetCount);
442 // Update the test.dart file.
443 modifyTestFile('''
411 main() { 444 main() {
412 print(1 + 2); 445 foo(1 + 2);
413 } 446 }
447 foo(int otherName) {}
414 '''); 448 ''');
415 return waitForTasksFinished().then((_) { 449 // The refactoring was reset.
416 return sendStringRequest('1 + 2', 'res', true).then((response) { 450 await pumpEventQueue();
417 _expectRefactoringRequestCancelled(response); 451 expect(test_resetCount, initialResetCount + 1);
452 // Send the second request, with the same kind, file and offset.
453 {
454 EditGetRefactoringResult result = await getRefactoringResult(() {
455 return sendStringRequest('1 + 2', 'res', true);
418 }); 456 });
419 }); 457 ExtractLocalVariableFeedback feedback = result.feedback;
420 } 458 // The refactoring was reset, so we don't get stale results.
421 459 expect(feedback.names, contains('otherName'));
422 test_reset_afterInitialConditions() { 460 }
423 test_simulateRefactoringReset_afterInitialConditions = true;
424 addTestFile('''
425 main() {
426 print(1 + 2);
427 }
428 ''');
429 return waitForTasksFinished().then((_) {
430 return sendStringRequest('1 + 2', 'res', true).then((response) {
431 _expectRefactoringRequestCancelled(response);
432 });
433 });
434 } 461 }
435 462
436 test_serverError_change() { 463 test_serverError_change() {
437 test_simulateRefactoringException_change = true; 464 test_simulateRefactoringException_change = true;
438 addTestFile(''' 465 addTestFile('''
439 main() { 466 main() {
440 print(1 + 2); 467 print(1 + 2);
441 } 468 }
442 '''); 469 ''');
443 return waitForTasksFinished().then((_) { 470 return waitForTasksFinished().then((_) {
(...skipping 26 matching lines...) Expand all
470 print(1 + 2); 497 print(1 + 2);
471 } 498 }
472 '''); 499 ''');
473 return waitForTasksFinished().then((_) { 500 return waitForTasksFinished().then((_) {
474 return sendStringRequest('1 + 2', 'res', true).then((response) { 501 return sendStringRequest('1 + 2', 'res', true).then((response) {
475 expect(response.error, isNotNull); 502 expect(response.error, isNotNull);
476 expect(response.error.code, RequestErrorCode.SERVER_ERROR); 503 expect(response.error.code, RequestErrorCode.SERVER_ERROR);
477 }); 504 });
478 }); 505 });
479 } 506 }
480
481 void _expectRefactoringRequestCancelled(Response response) {
482 expect(response.error, isNotNull);
483 expect(response,
484 isResponseFailure('0', RequestErrorCode.REFACTORING_REQUEST_CANCELLED));
485 }
486 } 507 }
487 508
488 @reflectiveTest 509 @reflectiveTest
489 class ExtractMethodTest extends _AbstractGetRefactoring_Test { 510 class ExtractMethodTest extends _AbstractGetRefactoring_Test {
490 int offset; 511 int offset;
491 int length; 512 int length;
492 String name = 'res'; 513 String name = 'res';
493 ExtractMethodOptions options; 514 ExtractMethodOptions options;
494 515
495 test_expression() { 516 test_expression() {
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 } 944 }
924 '''); 945 ''');
925 await waitForTasksFinished(); 946 await waitForTasksFinished();
926 await getRefactoringsAtString('// not an element'); 947 await getRefactoringsAtString('// not an element');
927 expect(kinds, isNot(contains(RefactoringKind.RENAME))); 948 expect(kinds, isNot(contains(RefactoringKind.RENAME)));
928 } 949 }
929 } 950 }
930 951
931 @reflectiveTest 952 @reflectiveTest
932 class InlineLocalTest extends _AbstractGetRefactoring_Test { 953 class InlineLocalTest extends _AbstractGetRefactoring_Test {
954 test_analysis_onlyOneFile() async {
955 shouldWaitForFullAnalysis = false;
956 String otherFile = '$testFolder/other.dart';
957 addFile(
958 otherFile,
959 r'''
960 foo(int p) {}
961 ''');
962 addTestFile('''
963 import 'other.dart';
964 main() {
965 int res = 1 + 2;
966 foo(res);
967 foo(res);
968 }
969 ''');
970 // Start refactoring.
971 EditGetRefactoringResult result = await getRefactoringResult(() {
972 return _sendInlineRequest('res =');
973 });
974 // We get the refactoring feedback....
975 InlineLocalVariableFeedback feedback = result.feedback;
976 expect(feedback.occurrences, 2);
977 // ...even though other.dart is not fully analyzed.
978 var otherSource = server.getContextSourcePair(otherFile).source;
979 var otherUnit = new LibrarySpecificUnit(otherSource, otherSource);
980 expect(testContext.getResult(otherUnit, RESOLVED_UNIT), isNull);
981 }
982
933 test_feedback() { 983 test_feedback() {
934 addTestFile(''' 984 addTestFile('''
935 main() { 985 main() {
936 int test = 42; 986 int test = 42;
937 print(test); 987 print(test);
938 print(test); 988 print(test);
939 } 989 }
940 '''); 990 ''');
941 return getRefactoringResult(() { 991 return getRefactoringResult(() {
942 return _sendInlineRequest('test ='); 992 return _sendInlineRequest('test =');
(...skipping 28 matching lines...) Expand all
971 return _sendInlineRequest('test + 2'); 1021 return _sendInlineRequest('test + 2');
972 }, 1022 },
973 ''' 1023 '''
974 main() { 1024 main() {
975 int a = 42 + 2; 1025 int a = 42 + 2;
976 print(42); 1026 print(42);
977 } 1027 }
978 '''); 1028 ''');
979 } 1029 }
980 1030
1031 test_resetOnFileChange() async {
1032 String otherFile = '$testFolder/other.dart';
1033 addFile(otherFile, '// other 1');
1034 addTestFile('''
1035 main() {
1036 int res = 1 + 2;
1037 print(res);
1038 }
1039 ''');
1040 // Send the first request.
1041 await getRefactoringResult(() {
1042 return _sendInlineRequest('res = ');
1043 });
1044 int initialResetCount = test_resetCount;
1045 // Update the other.dart file.
1046 // The refactoring is not reset, because it's a different file.
1047 addFile(otherFile, '// other 2');
1048 await pumpEventQueue();
1049 expect(test_resetCount, initialResetCount);
1050 // Update the test.dart file.
1051 modifyTestFile('''
1052 main() {
1053 print(1 + 2);
1054 }
1055 ''');
1056 // The refactoring was reset.
1057 await pumpEventQueue();
1058 expect(test_resetCount, initialResetCount + 1);
1059 }
1060
981 Future<Response> _sendInlineRequest(String search) { 1061 Future<Response> _sendInlineRequest(String search) {
982 Request request = new EditGetRefactoringParams( 1062 Request request = new EditGetRefactoringParams(
983 RefactoringKind.INLINE_LOCAL_VARIABLE, 1063 RefactoringKind.INLINE_LOCAL_VARIABLE,
984 testFile, 1064 testFile,
985 findOffset(search), 1065 findOffset(search),
986 0, 1066 0,
987 false) 1067 false)
988 .toRequest('0'); 1068 .toRequest('0');
989 return serverChannel.sendRequest(request); 1069 return serverChannel.sendRequest(request);
990 } 1070 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 Future<Response> sendRenameRequest(String search, String newName, 1237 Future<Response> sendRenameRequest(String search, String newName,
1158 {String id: '0', bool validateOnly: false}) { 1238 {String id: '0', bool validateOnly: false}) {
1159 RenameOptions options = newName != null ? new RenameOptions(newName) : null; 1239 RenameOptions options = newName != null ? new RenameOptions(newName) : null;
1160 Request request = new EditGetRefactoringParams(RefactoringKind.RENAME, 1240 Request request = new EditGetRefactoringParams(RefactoringKind.RENAME,
1161 testFile, findOffset(search), 0, validateOnly, 1241 testFile, findOffset(search), 0, validateOnly,
1162 options: options) 1242 options: options)
1163 .toRequest(id); 1243 .toRequest(id);
1164 return serverChannel.sendRequest(request); 1244 return serverChannel.sendRequest(request);
1165 } 1245 }
1166 1246
1247 void tearDown() {
1248 test_simulateRefactoringReset_afterInitialConditions = false;
1249 test_simulateRefactoringReset_afterFinalConditions = false;
1250 test_simulateRefactoringReset_afterCreateChange = false;
1251 super.tearDown();
1252 }
1253
1167 test_cancelPendingRequest() async { 1254 test_cancelPendingRequest() async {
1168 addTestFile(''' 1255 addTestFile('''
1169 main() { 1256 main() {
1170 int test = 0; 1257 int test = 0;
1171 print(test); 1258 print(test);
1172 } 1259 }
1173 '''); 1260 ''');
1174 // send the "1" request, but don't wait for it 1261 // send the "1" request, but don't wait for it
1175 Future<Response> futureA = sendRenameRequest('test =', 'nameA', id: '1'); 1262 Future<Response> futureA = sendRenameRequest('test =', 'nameA', id: '1');
1176 // send the "2" request and wait for it 1263 // send the "2" request and wait for it
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 return getRefactoringResult(() { 1813 return getRefactoringResult(() {
1727 return sendRenameRequest('test = 0', 'newName'); 1814 return sendRenameRequest('test = 0', 'newName');
1728 }).then((result) { 1815 }).then((result) {
1729 List<RefactoringProblem> problems = result.finalProblems; 1816 List<RefactoringProblem> problems = result.finalProblems;
1730 expect(problems, hasLength(1)); 1817 expect(problems, hasLength(1));
1731 assertResultProblemsError( 1818 assertResultProblemsError(
1732 problems, "Duplicate local variable 'newName'."); 1819 problems, "Duplicate local variable 'newName'.");
1733 }); 1820 });
1734 } 1821 }
1735 1822
1823 test_reset_afterCreateChange() {
1824 test_simulateRefactoringReset_afterCreateChange = true;
1825 addTestFile('''
1826 test() {}
1827 main() {
1828 test();
1829 }
1830 ''');
1831 return waitForTasksFinished().then((_) {
1832 return sendRenameRequest('test() {}', 'newName').then((response) {
1833 _expectRefactoringRequestCancelled(response);
1834 });
1835 });
1836 }
1837
1838 test_reset_afterFinalConditions() {
1839 test_simulateRefactoringReset_afterFinalConditions = true;
1840 addTestFile('''
1841 test() {}
1842 main() {
1843 test();
1844 }
1845 ''');
1846 return waitForTasksFinished().then((_) {
1847 return sendRenameRequest('test() {}', 'newName').then((response) {
1848 _expectRefactoringRequestCancelled(response);
1849 });
1850 });
1851 }
1852
1853 test_reset_afterInitialConditions() {
1854 test_simulateRefactoringReset_afterInitialConditions = true;
1855 addTestFile('''
1856 test() {}
1857 main() {
1858 test();
1859 }
1860 ''');
1861 return waitForTasksFinished().then((_) {
1862 return sendRenameRequest('test() {}', 'newName').then((response) {
1863 _expectRefactoringRequestCancelled(response);
1864 });
1865 });
1866 }
1867
1736 test_resetOnAnalysis() { 1868 test_resetOnAnalysis() {
1737 addTestFile(''' 1869 addTestFile('''
1738 main() { 1870 main() {
1739 int initialName = 0; 1871 int initialName = 0;
1740 print(initialName); 1872 print(initialName);
1741 } 1873 }
1742 '''); 1874 ''');
1743 // send the first request 1875 // send the first request
1744 return getRefactoringResult(() { 1876 return getRefactoringResult(() {
1745 return sendRenameRequest('initialName =', 'newName', validateOnly: true); 1877 return sendRenameRequest('initialName =', 'newName', validateOnly: true);
(...skipping 14 matching lines...) Expand all
1760 validateOnly: true); 1892 validateOnly: true);
1761 }).then((result) { 1893 }).then((result) {
1762 RenameFeedback feedback = result.feedback; 1894 RenameFeedback feedback = result.feedback;
1763 // the refactoring was reset, so we don't get a stale result 1895 // the refactoring was reset, so we don't get a stale result
1764 expect(feedback.oldName, 'otherName'); 1896 expect(feedback.oldName, 'otherName');
1765 }); 1897 });
1766 }); 1898 });
1767 }); 1899 });
1768 } 1900 }
1769 1901
1902 void _expectRefactoringRequestCancelled(Response response) {
1903 expect(response.error, isNotNull);
1904 expect(response,
1905 isResponseFailure('0', RequestErrorCode.REFACTORING_REQUEST_CANCELLED));
1906 }
1907
1770 SourceEdit _findEditWithId(SourceChange change, String id) { 1908 SourceEdit _findEditWithId(SourceChange change, String id) {
1771 SourceEdit potentialEdit; 1909 SourceEdit potentialEdit;
1772 change.edits.forEach((fileEdit) { 1910 change.edits.forEach((fileEdit) {
1773 fileEdit.edits.forEach((edit) { 1911 fileEdit.edits.forEach((edit) {
1774 if (edit.id == id) { 1912 if (edit.id == id) {
1775 potentialEdit = edit; 1913 potentialEdit = edit;
1776 } 1914 }
1777 }); 1915 });
1778 }); 1916 });
1779 return potentialEdit; 1917 return potentialEdit;
1780 } 1918 }
1781 } 1919 }
1782 1920
1783 @reflectiveTest 1921 @reflectiveTest
1784 class _AbstractGetRefactoring_Test extends AbstractAnalysisTest { 1922 class _AbstractGetRefactoring_Test extends AbstractAnalysisTest {
1923 bool shouldWaitForFullAnalysis = true;
1924
1785 /** 1925 /**
1786 * Asserts that [problems] has a single ERROR problem. 1926 * Asserts that [problems] has a single ERROR problem.
1787 */ 1927 */
1788 void assertResultProblemsError(List<RefactoringProblem> problems, 1928 void assertResultProblemsError(List<RefactoringProblem> problems,
1789 [String message]) { 1929 [String message]) {
1790 RefactoringProblem problem = problems[0]; 1930 RefactoringProblem problem = problems[0];
1791 expect(problem.severity, RefactoringProblemSeverity.ERROR, 1931 expect(problem.severity, RefactoringProblemSeverity.ERROR,
1792 reason: problem.toString()); 1932 reason: problem.toString());
1793 if (message != null) { 1933 if (message != null) {
1794 expect(problem.message, message); 1934 expect(problem.message, message);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 fail('No SourceFileEdit for $testFile in $change'); 1998 fail('No SourceFileEdit for $testFile in $change');
1859 } 1999 }
1860 2000
1861 @override 2001 @override
1862 Index createIndex() { 2002 Index createIndex() {
1863 return createMemoryIndex(); 2003 return createMemoryIndex();
1864 } 2004 }
1865 2005
1866 Future<EditGetRefactoringResult> getRefactoringResult( 2006 Future<EditGetRefactoringResult> getRefactoringResult(
1867 Future<Response> requestSender()) async { 2007 Future<Response> requestSender()) async {
1868 await waitForTasksFinished(); 2008 if (shouldWaitForFullAnalysis) {
2009 await waitForTasksFinished();
2010 }
1869 Response response = await requestSender(); 2011 Response response = await requestSender();
1870 return new EditGetRefactoringResult.fromResponse(response); 2012 return new EditGetRefactoringResult.fromResponse(response);
1871 } 2013 }
1872 2014
1873 Future<Response> sendRequest( 2015 Future<Response> sendRequest(
1874 RefactoringKind kind, int offset, int length, RefactoringOptions options, 2016 RefactoringKind kind, int offset, int length, RefactoringOptions options,
1875 [bool validateOnly = false]) { 2017 [bool validateOnly = false]) {
1876 Request request = new EditGetRefactoringParams( 2018 Request request = new EditGetRefactoringParams(
1877 kind, testFile, offset, length, validateOnly, 2019 kind, testFile, offset, length, validateOnly,
1878 options: options) 2020 options: options)
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1922 .toRequest('0'); 2064 .toRequest('0');
1923 return _assertErrorResponseNoIndex(request); 2065 return _assertErrorResponseNoIndex(request);
1924 } 2066 }
1925 2067
1926 _assertErrorResponseNoIndex(Request request) async { 2068 _assertErrorResponseNoIndex(Request request) async {
1927 Response response = await serverChannel.sendRequest(request); 2069 Response response = await serverChannel.sendRequest(request);
1928 expect(response.error, isNotNull); 2070 expect(response.error, isNotNull);
1929 expect(response.error.code, RequestErrorCode.NO_INDEX_GENERATED); 2071 expect(response.error.code, RequestErrorCode.NO_INDEX_GENERATED);
1930 } 2072 }
1931 } 2073 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698