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

Unified Diff: pkg/analysis_server/test/services/refactoring/extract_local_test.dart

Issue 489973002: Initial 'Extract Local' implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: tweaks Created 6 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_server/test/services/refactoring/extract_local_test.dart
diff --git a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1276ac97247db5b094e31982d34b038d0e1e89a0
--- /dev/null
+++ b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
@@ -0,0 +1,848 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test.services.refactoring.extract_local;
+
+import 'dart:async';
+
+import 'package:analysis_server/src/services/correction/change.dart';
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/extract_local.dart';
+import 'package:analysis_testing/reflective_tests.dart';
+import 'package:unittest/unittest.dart';
+
+import 'abstract_refactoring.dart';
+
+
+main() {
+ groupSep = ' | ';
+ runReflectiveTests(ExtractLocalTest);
+}
+
+
+@ReflectiveTestCase()
+class ExtractLocalTest extends RefactoringTest {
+ ExtractLocalRefactoringImpl refactoring;
+
+ test_checkFinalConditions_sameVariable_after() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2;
+ var res;
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // conflicting name
+ return refactoring.checkAllConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.WARNING,
+ expectedMessage:
+ "A variable with name 'res' is already defined in the visible scope.");
+ });
+ }
+
+ test_checkFinalConditions_sameVariable_before() {
+ indexTestUnit('''
+main() {
+ var res;
+ int a = 1 + 2;
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // conflicting name
+ return refactoring.checkAllConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.WARNING,
+ expectedMessage:
+ "A variable with name 'res' is already defined in the visible scope.");
+ });
+ }
+
+ test_checkInitialConditions_assignmentLeftHandSize() {
+ indexTestUnit('''
+main() {
+ var v = 0;
+ v = 1;
+}
+''');
+ _createRefactoringWithSuffix('v', ' = 1;');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Cannot extract the left-hand side of an assignment.');
+ });
+ }
+
+ test_checkInitialConditions_methodName_reference() {
+ indexTestUnit('''
+main() {
+ main();
+}
+''');
+ _createRefactoringWithSuffix('main', '();');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Cannot extract a single method name.');
+ });
+ }
+
+ test_checkInitialConditions_nameOfProperty_prefixedIdentifier() {
+ indexTestUnit('''
+main(p) {
+ p.value; // marker
+}
+''');
+ _createRefactoringWithSuffix('value', '; // marker');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Cannot extract name part of a property access.');
+ });
+ }
+
+ test_checkInitialConditions_nameOfProperty_propertyAccess() {
+ indexTestUnit('''
+main() {
+ foo().length; // marker
+}
+String foo() => '';
+''');
+ _createRefactoringWithSuffix('length', '; // marker');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Cannot extract name part of a property access.');
+ });
+ }
+
+ test_checkInitialConditions_namePartOfDeclaration_variable() {
+ indexTestUnit('''
+main() {
+ int vvv = 0;
+}
+''');
+ _createRefactoringWithSuffix('vvv', ' = 0;');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Cannot extract the name part of a declaration.');
+ });
+ }
+
+ test_checkInitialConditions_notPartOfFunction() {
+ indexTestUnit('''
+int a = 1 + 2;
+''');
+ _createRefactoringForString('1 + 2');
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage:
+ 'Expression inside of function must be selected to activate this refactoring.');
+ });
+ }
+
+ test_checkInitialConditions_stringSelection_leadingQuote() {
+ indexTestUnit('''
+main() {
+ var vvv = 'abc';
+}
+''');
+ _createRefactoringForString("'a");
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage:
+ 'Cannot extract only leading or trailing quote of string literal.');
+ });
+ }
+
+ test_checkInitialConditions_stringSelection_trailingQuote() {
+ indexTestUnit('''
+main() {
+ var vvv = 'abc';
+}
+''');
+ _createRefactoringForString("c'");
+ // check conditions
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage:
+ 'Cannot extract only leading or trailing quote of string literal.');
+ });
+ }
+
+ test_checkLocalName() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2;
+}
+''');
+ _createRefactoringForString('1 + 2');
+ expect(refactoring.refactoringName, 'Extract Local Variable');
+ // null
+ refactoring.name = null;
+ assertRefactoringStatus(
+ refactoring.checkName(),
+ RefactoringStatusSeverity.ERROR,
+ expectedMessage: "Variable name must not be null.");
+ // empty
+ refactoring.name = '';
+ assertRefactoringStatus(
+ refactoring.checkName(),
+ RefactoringStatusSeverity.ERROR,
+ expectedMessage: "Variable name must not be empty.");
+ // OK
+ refactoring.name = 'res';
+ assertRefactoringStatusOK(refactoring.checkName());
+ }
+
+ test_completeStatementExpression() {
+ indexTestUnit('''
+main(p) {
+ p.toString();
+}
+''');
+ _createRefactoringForString('p.toString()');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main(p) {
+ var res = p.toString();
+}
+''');
+ }
+
+ test_const_argument_inConstInstanceCreation() {
+ indexTestUnit('''
+class A {
+ const A(int a, int b);
+}
+main() {
+ const A(1, 2);
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+class A {
+ const A(int a, int b);
+}
+main() {
+ const res = 1;
+ const A(res, 2);
+}
+''');
+ }
+
+ test_const_inList() {
+ indexTestUnit('''
+main() {
+ const [1, 2];
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = 1;
+ const [res, 2];
+}
+''');
+ }
+
+ test_const_inList_inBinaryExpression() {
+ indexTestUnit('''
+main() {
+ const [1 + 2, 3];
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = 1;
+ const [res + 2, 3];
+}
+''');
+ }
+
+ test_const_inList_inConditionalExpression() {
+ indexTestUnit('''
+main(bool b) {
+ const [b ? 1 : 2, 3];
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main(bool b) {
+ const res = 1;
+ const [b ? res : 2, 3];
+}
+''');
+ }
+
+ test_const_inList_inParenthesis() {
+ indexTestUnit('''
+main() {
+ const [(1), 2];
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = 1;
+ const [(res), 2];
+}
+''');
+ }
+
+ test_const_inList_inPrefixExpression() {
+ indexTestUnit('''
+main() {
+ const [!true, 2];
+}
+''');
+ _createRefactoringForString('true');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = true;
+ const [!res, 2];
+}
+''');
+ }
+
+ test_const_inMap_key() {
+ indexTestUnit('''
+main() {
+ const {1: 2};
+}
+''');
+ _createRefactoringForString('1');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = 1;
+ const {res: 2};
+}
+''');
+ }
+
+ test_const_inMap_value() {
+ indexTestUnit('''
+main() {
+ const {1: 2};
+}
+''');
+ _createRefactoringForString('2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ const res = 2;
+ const {1: res};
+}
+''');
+ }
+
+ test_fragmentExpression() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('2 + 3');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 2 + 3;
+ int a = 1 + res + 4;
+}
+''');
+ }
+
+ test_fragmentExpression_leadingNotWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('+ 2');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_fragmentExpression_leadingPartialSelection() {
+ indexTestUnit('''
+main() {
+ int a = 111 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('11 + 2');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_fragmentExpression_leadingWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString(' 2 + 3');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 2 + 3;
+ int a = 1 +res + 4;
+}
+''');
+ }
+
+ test_fragmentExpression_notAssociativeOperator() {
+ indexTestUnit('''
+main() {
+ int a = 1 - 2 - 3 - 4;
+}
+''');
+ _createRefactoringForString('2 - 3');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_fragmentExpression_trailingNotWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('2 + 3 +');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_fragmentExpression_trailingPartialSelection() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 444;
+}
+''');
+ _createRefactoringForString('2 + 3 + 44');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_fragmentExpression_trailingWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('2 + 3 ');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 2 + 3 ;
+ int a = 1 + res+ 4;
+}
+''');
+ }
+
+ test_occurences_disableOccurences() {
+ indexTestUnit('''
+int foo() => 42;
+main() {
+ int a = 1 + foo();
+ int b = 2 + foo(); // marker
+}
+''');
+ _createRefactoringWithSuffix('foo()', '; // marker');
+ refactoring.extractAll = false;
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+int foo() => 42;
+main() {
+ int a = 1 + foo();
+ var res = foo();
+ int b = 2 + res; // marker
+}
+''');
+ }
+
+ test_occurences_ignore_assignmentLeftHandSize() {
+ indexTestUnit('''
+main() {
+ int v = 1;
+ v = 2;
+ print(() {v = 2;});
+ print(1 + (() {v = 2; return 3;})());
+ print(v); // marker
+}
+''');
+ _createRefactoringWithSuffix('v', '); // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ int v = 1;
+ v = 2;
+ print(() {v = 2;});
+ print(1 + (() {v = 2; return 3;})());
+ var res = v;
+ print(res); // marker
+}
+''');
+ }
+
+ test_occurences_ignore_nameOfVariableDeclariton() {
+ indexTestUnit('''
+main() {
+ int v = 1;
+ print(v); // marker
+}
+''');
+ _createRefactoringWithSuffix('v', '); // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ int v = 1;
+ var res = v;
+ print(res); // marker
+}
+''');
+ }
+
+ test_occurences_singleExpression() {
+ indexTestUnit('''
+int foo() => 42;
+main() {
+ int a = 1 + foo();
+ int b = 2 + foo(); // marker
+}
+''');
+ _createRefactoringWithSuffix('foo()', '; // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+int foo() => 42;
+main() {
+ var res = foo();
+ int a = 1 + res;
+ int b = 2 + res; // marker
+}
+''');
+ }
+
+ test_occurences_useDominator() {
+ indexTestUnit('''
+main() {
+ if (true) {
+ print(42);
+ } else {
+ print(42);
+ }
+}
+''');
+ _createRefactoringForString('42');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 42;
+ if (true) {
+ print(res);
+ } else {
+ print(res);
+ }
+}
+''');
+ }
+
+ test_occurences_whenComment() {
+ indexTestUnit('''
+int foo() => 42;
+main() {
+ /*int a = 1 + foo();*/
+ int b = 2 + foo(); // marker
+}
+''');
+ _createRefactoringWithSuffix('foo()', '; // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+int foo() => 42;
+main() {
+ /*int a = 1 + foo();*/
+ var res = foo();
+ int b = 2 + res; // marker
+}
+''');
+ }
+
+ test_occurences_withSpace() {
+ indexTestUnit('''
+int foo(String s) => 42;
+main() {
+ int a = 1 + foo('has space');
+ int b = 2 + foo('has space'); // marker
+}
+''');
+ _createRefactoringWithSuffix("foo('has space')", '; // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+int foo(String s) => 42;
+main() {
+ var res = foo('has space');
+ int a = 1 + res;
+ int b = 2 + res; // marker
+}
+''');
+ }
+
+ test_offsets_lengths() {
+ // TODO(scheglov) implement and test
+ }
+
+ test_singleExpression() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2;
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 1 + 2;
+ int a = res;
+}
+''');
+ }
+
+ test_singleExpression_getter() {
+ indexTestUnit('''
+class A {
+ int get foo => 42;
+}
+main() {
+ A a = new A();
+ int b = 1 + a.foo; // marker
+}
+''');
+ _createRefactoringWithSuffix('a.foo', '; // marker');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+class A {
+ int get foo => 42;
+}
+main() {
+ A a = new A();
+ var res = a.foo;
+ int b = 1 + res; // marker
+}
+''');
+ }
+
+ test_singleExpression_inMethod() {
+ indexTestUnit('''
+class A {
+ main() {
+ print(1 + 2);
+ }
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+class A {
+ main() {
+ var res = 1 + 2;
+ print(res);
+ }
+}
+''');
+ }
+
+ test_singleExpression_leadingNotWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 12 + 345;
+}
+''');
+ _createRefactoringForString('+ 345');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_singleExpression_leadingWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 12 /*abc*/ + 345;
+}
+''');
+ _createRefactoringForString('12 /*abc*/');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 12 /*abc*/;
+ int a = res + 345;
+}
+''');
+ }
+
+ /**
+ * Here we use knowledge how exactly `1 + 2 + 3 + 41 is parsed. We know that
+ * `1 + 2` will be a separate and complete binary expression, so it can be
+ * handled as a single expression.
+ */
+ test_singleExpression_partOfBinaryExpression() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 + 3 + 4;
+}
+''');
+ _createRefactoringForString('1 + 2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 1 + 2;
+ int a = res + 3 + 4;
+}
+''');
+ }
+
+ test_singleExpression_trailingComment() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2;
+}
+''');
+ _createRefactoringForString(' 1 + 2');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 1 + 2;
+ int a = res;
+}
+''');
+ }
+
+ test_singleExpression_trailingNotWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 12 + 345;
+}
+''');
+ _createRefactoringForString('12 +');
+ // check conditions
+ return _assertInitialConditions_fatal_selection();
+ }
+
+ test_singleExpression_trailingWhitespace() {
+ indexTestUnit('''
+main() {
+ int a = 1 + 2 ;
+}
+''');
+ _createRefactoringForString('1 + 2 ');
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 1 + 2 ;
+ int a = res;
+}
+''');
+ }
+
+ test_stringLiteral_part() {
+ indexTestUnit('''
+main() {
+ print('abcdefgh');
+}
+''');
+ _createRefactoringForString('cde');
+ // apply refactoring
+ return _assertSuccessfulRefactoring(r'''
+main() {
+ var res = 'cde';
+ print('ab${res}fgh');
+}
+''');
+ }
+
+ test_stringLiteral_whole() {
+ indexTestUnit('''
+main() {
+ print('abc');
+}
+''');
+ _createRefactoringForString("'abc'");
+ // apply refactoring
+ return _assertSuccessfulRefactoring('''
+main() {
+ var res = 'abc';
+ print(res);
+}
+''');
+ }
+
+ Future _assertInitialConditions_fatal_selection() {
+ return refactoring.checkInitialConditions().then((status) {
+ assertRefactoringStatus(
+ status,
+ RefactoringStatusSeverity.FATAL,
+ expectedMessage: 'Expression must be selected to activate this refactoring.');
+ });
+ }
+
+ /**
+ * Checks that all conditions are OK and the result of applying the [Change]
+ * to [testUnit] is [expectedCode].
+ */
+ Future _assertSuccessfulRefactoring(String expectedCode) {
+ return assertRefactoringConditionsOK().then((_) {
+ return refactoring.createChange().then((Change refactoringChange) {
+ this.refactoringChange = refactoringChange;
+ assertTestChangeResult(expectedCode);
+ });
+ });
+ }
+
+ void _createRefactoring(int offset, int length) {
+ refactoring = new ExtractLocalRefactoringImpl(testUnit, offset, length);
+ refactoring.name = 'res';
+ }
+
+ /**
+ * Creates a new refactoring in [refactoring] for the selection range of the
+ * given [search] pattern.
+ */
+ void _createRefactoringForString(String search) {
+ int offset = findOffset(search);
+ int length = search.length;
+ _createRefactoring(offset, length);
+ }
+
+ void _createRefactoringWithSuffix(String selectionSearch, String suffix) {
+ int offset = findOffset(selectionSearch + suffix);
+ int length = selectionSearch.length;
+ _createRefactoring(offset, length);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698