blob: 9a40d783f83c12bbfac117591e9ade14e706ec32 [file] [log] [blame]
// 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.
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'abstract_rename.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(RenameConstructorClassTest);
defineReflectiveTests(RenameConstructorEnumTest);
});
}
@reflectiveTest
class RenameConstructorClassTest extends _RenameConstructorTest {
Future<void> test_checkInitialConditions_inSDK() async {
await indexTestUnit('''
main() {
new String.fromCharCodes([]);
}
''');
createRenameRefactoringAtString('fromCharCodes(');
// check status
refactoring.newName = 'newName';
var status = await refactoring.checkInitialConditions();
assertRefactoringStatus(status, RefactoringProblemSeverity.FATAL,
expectedMessage:
"The constructor 'String.fromCharCodes' is defined in the SDK, so cannot be renamed.");
}
Future<void> test_checkNewName() async {
await indexTestUnit('''
class A {
A.test() {}
}
''');
createRenameRefactoringAtString('test() {}');
expect(refactoring.oldName, 'test');
// same
refactoring.newName = 'test';
assertRefactoringStatus(
refactoring.checkNewName(), RefactoringProblemSeverity.FATAL,
expectedMessage:
'The new name must be different than the current name.');
// empty
refactoring.newName = '';
assertRefactoringStatusOK(refactoring.checkNewName());
// OK
refactoring.newName = 'newName';
assertRefactoringStatusOK(refactoring.checkNewName());
}
Future<void> test_checkNewName_hasMember_constructor() async {
await indexTestUnit('''
class A {
A.test() {}
A.newName() {} // existing
}
''');
_createConstructorDeclarationRefactoring('test() {}');
// check status
refactoring.newName = 'newName';
var status = refactoring.checkNewName();
assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
expectedMessage:
"Class 'A' already declares constructor with name 'newName'.",
expectedContextSearch: 'newName() {} // existing');
}
Future<void> test_checkNewName_hasMember_method() async {
await indexTestUnit('''
class A {
A.test() {}
newName() {} // existing
}
''');
_createConstructorDeclarationRefactoring('test() {}');
// check status
refactoring.newName = 'newName';
var status = refactoring.checkNewName();
assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
expectedMessage:
"Class 'A' already declares method with name 'newName'.",
expectedContextSearch: 'newName() {} // existing');
}
Future<void> test_createChange_add() async {
await indexTestUnit('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [new A] and [A.new]
class A {
A() {} // marker
factory A._() = A;
}
class B extends A {
B() : super() {}
}
main() {
new A();
A.new;
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('() {} // marker');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [new A.newName] and [A.newName]
class A {
A.newName() {} // marker
factory A._() = A.newName;
}
class B extends A {
B() : super.newName() {}
}
main() {
new A.newName();
A.newName;
}
''');
}
Future<void> test_createChange_add_toSynthetic() async {
await indexTestUnit('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [new A] and [A.new]
class A {
int field = 0;
}
class B extends A {
B() : super() {}
}
main() {
new A();
A.new;
}
''');
// configure refactoring
_createConstructorInvocationRefactoring('new A();');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [new A.newName] and [A.newName]
class A {
int field = 0;
A.newName();
}
class B extends A {
B() : super.newName() {}
}
main() {
new A.newName();
A.newName;
}
''');
}
Future<void> test_createChange_change() async {
await indexTestUnit('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [A.test] and [new A.test]
class A {
A.test() {} // marker
factory A._() = A.test;
}
class B extends A {
B() : super.test() {}
}
main() {
new A.test();
A.test;
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('test() {} // marker');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, 'test');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [A.newName] and [new A.newName]
class A {
A.newName() {} // marker
factory A._() = A.newName;
}
class B extends A {
B() : super.newName() {}
}
main() {
new A.newName();
A.newName;
}
''');
}
Future<void> test_createChange_lint_sortConstructorsFirst() async {
createAnalysisOptionsFile(lints: [LintNames.sort_constructors_first]);
await indexTestUnit('''
class A {
int field = 0;
}
main() {
new A();
}
''');
// configure refactoring
_createConstructorInvocationRefactoring('new A();');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
class A {
A.newName();
int field = 0;
}
main() {
new A.newName();
}
''');
}
Future<void> test_createChange_remove() async {
await indexTestUnit('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [A.test] and [new A.test]
class A {
A.test() {} // marker
factory A._() = A.test;
}
class B extends A {
B() : super.test() {}
}
main() {
new A.test();
A.test;
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('test() {} // marker');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, 'test');
// validate change
refactoring.newName = '';
return assertSuccessfulRefactoring('''
// ignore: deprecated_new_in_comment_reference
/// Documentation for [A] and [new A]
class A {
A() {} // marker
factory A._() = A;
}
class B extends A {
B() : super() {}
}
main() {
new A();
A.new;
}
''');
}
Future<void> test_newInstance_nullElement() async {
await indexTestUnit('');
var workspace = RefactoringWorkspace([driverFor(testFile)], searchEngine);
var refactoring =
RenameRefactoring.create(workspace, testAnalysisResult, null);
expect(refactoring, isNull);
}
}
@reflectiveTest
class RenameConstructorEnumTest extends _RenameConstructorTest {
Future<void> test_checkNewName() async {
await indexTestUnit('''
enum E {
v.test();
const E.test(); // 0
}
''');
createRenameRefactoringAtString('test(); // 0');
expect(refactoring.oldName, 'test');
// same
refactoring.newName = 'test';
assertRefactoringStatus(
refactoring.checkNewName(), RefactoringProblemSeverity.FATAL,
expectedMessage:
'The new name must be different than the current name.');
// empty
refactoring.newName = '';
assertRefactoringStatusOK(refactoring.checkNewName());
// OK
refactoring.newName = 'newName';
assertRefactoringStatusOK(refactoring.checkNewName());
}
Future<void> test_checkNewName_hasMember_constructor() async {
await indexTestUnit('''
enum E {
v.test();
const E.test(); // 0
const E.newName(); // existing
}
''');
_createConstructorDeclarationRefactoring('test(); // 0');
// check status
refactoring.newName = 'newName';
var status = refactoring.checkNewName();
assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
expectedMessage:
"Class 'E' already declares constructor with name 'newName'.",
expectedContextSearch: 'newName(); // existing');
}
Future<void> test_checkNewName_hasMember_method() async {
await indexTestUnit('''
enum E {
v.test();
const E.test(); // 0
void newName() {} // existing
}
''');
_createConstructorDeclarationRefactoring('test(); // 0');
// check status
refactoring.newName = 'newName';
var status = refactoring.checkNewName();
assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR,
expectedMessage:
"Class 'E' already declares method with name 'newName'.",
expectedContextSearch: 'newName() {} // existing');
}
Future<void> test_createChange_add() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3, v4.other();
const E(); // 0
const E.other() : this();
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('(); // 0');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName(), v4.other();
const E.newName(); // 0
const E.other() : this.newName();
}
''');
}
Future<void> test_createChange_add_toSynthetic_hasConstructor() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3;
factory E.other() => throw 0;
}
''');
// configure refactoring
_createEnumConstantRefactoring('v1()');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName();
factory E.other() => throw 0;
const E.newName();
}
''');
}
Future<void> test_createChange_add_toSynthetic_hasField() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3;
final int foo = 0;
}
''');
// configure refactoring
_createEnumConstantRefactoring('v1()');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName();
final int foo = 0;
const E.newName();
}
''');
}
Future<void> test_createChange_add_toSynthetic_hasMethod() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3;
void foo() {}
}
''');
// configure refactoring
_createEnumConstantRefactoring('v1()');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName();
const E.newName();
void foo() {}
}
''');
}
Future<void> test_createChange_add_toSynthetic_hasSemicolon() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3;
}
''');
// configure refactoring
_createEnumConstantRefactoring('v1()');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName();
const E.newName();
}
''');
}
Future<void> test_createChange_add_toSynthetic_noSemicolon() async {
await indexTestUnit('''
/// [E.new]
enum E {
v1(), v2.new(), v3
}
''');
// configure refactoring
_createEnumConstantRefactoring('v1()');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, '');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.newName(), v3.newName();
const E.newName();
}
''');
}
Future<void> test_createChange_change() async {
await indexTestUnit('''
/// [E.test]
enum E {
v1.test(), v2.other();
const E.test(); // 0
const E.other() : this.test();
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('test(); // 0');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, 'test');
// validate change
refactoring.newName = 'newName';
return assertSuccessfulRefactoring('''
/// [E.newName]
enum E {
v1.newName(), v2.other();
const E.newName(); // 0
const E.other() : this.newName();
}
''');
}
Future<void> test_createChange_remove() async {
await indexTestUnit('''
/// [E]
enum E {
v1.test(), v2.other();
const E.test(); // 0
const E.other() : this.test();
}
''');
// configure refactoring
_createConstructorDeclarationRefactoring('test(); // 0');
expect(refactoring.refactoringName, 'Rename Constructor');
expect(refactoring.elementKindName, 'constructor');
expect(refactoring.oldName, 'test');
// validate change
refactoring.newName = '';
return assertSuccessfulRefactoring('''
/// [E]
enum E {
v1(), v2.other();
const E(); // 0
const E.other() : this();
}
''');
}
void _createEnumConstantRefactoring(String search) {
var enumConstant = findNode.enumConstantDeclaration(search);
var element = enumConstant.constructorElement;
createRenameRefactoringForElement(element);
}
}
class _RenameConstructorTest extends RenameRefactoringTest {
void _createConstructorDeclarationRefactoring(String search) {
var element = findNode.constructor(search).declaredElement;
createRenameRefactoringForElement(element);
}
void _createConstructorInvocationRefactoring(String search) {
var instanceCreation = findNode.instanceCreation(search);
var element = instanceCreation.constructorName.staticElement;
createRenameRefactoringForElement(element);
}
}