blob: 93b95a7ea15dbc239a21fe4af7a99290f36b3db8 [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 'dart:async';
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/ast_provider_driver.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/ast_provider.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
hide AnalysisError;
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../abstract_single_unit.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FixProcessorTest);
defineReflectiveTests(LintFixTest);
});
}
typedef bool AnalysisErrorFilter(AnalysisError error);
/**
* Base class for fix processor tests.
*/
class BaseFixProcessorTest extends AbstractSingleUnitTest {
AnalysisErrorFilter errorFilter = (AnalysisError error) {
return error.errorCode != HintCode.UNUSED_CATCH_CLAUSE &&
error.errorCode != HintCode.UNUSED_CATCH_STACK &&
error.errorCode != HintCode.UNUSED_ELEMENT &&
error.errorCode != HintCode.UNUSED_FIELD &&
error.errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
};
String myPkgLibPath = '/packages/my_pkg/lib';
String flutterPkgLibPath = '/packages/flutter/lib';
Fix fix;
SourceChange change;
String resultCode;
assert_undefinedFunction_create_returnType_bool(String lineWithTest) async {
await resolveTestUnit('''
main() {
bool b = true;
$lineWithTest
}
''');
await assertHasFix(DartFixKind.CREATE_FUNCTION, '''
main() {
bool b = true;
$lineWithTest
}
bool test() {
}
''');
}
assertHasFix(FixKind kind, String expected, {String target}) async {
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(kind, error);
change = fix.change;
// apply to "file"
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
String fileContent = testCode;
if (target != null) {
expect(fileEdits.first.file, convertPath(target));
fileContent = getFile(target).readAsStringSync();
}
resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits);
// verify
expect(resultCode, expected);
}
assertHasFixAllFix(ErrorCode errorCode, FixKind kind, String expected,
{String target}) async {
AnalysisError error = await _findErrorToFixOfType(errorCode);
fix = await _assertHasFix(kind, error, hasFixAllFix: true);
change = fix.change;
// apply to "file"
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
String fileContent = testCode;
if (target != null) {
expect(fileEdits.first.file, convertPath(target));
fileContent = getFile(target).readAsStringSync();
}
resultCode = SourceEdit.applySequence(fileContent, change.edits[0].edits);
// verify
expect(resultCode, expected);
}
assertNoFix(FixKind kind) async {
AnalysisError error = await _findErrorToFix();
await _assertNoFix(kind, error);
}
List<LinkedEditSuggestion> expectedSuggestions(
LinkedEditSuggestionKind kind, List<String> values) {
return values.map((value) {
return new LinkedEditSuggestion(value, kind);
}).toList();
}
void setUp() {
super.setUp();
verifyNoTestUnitErrors = false;
}
/**
* Computes fixes and verifies that there is a fix of the given kind.
*/
Future<Fix> _assertHasFix(FixKind kind, AnalysisError error,
{bool hasFixAllFix: false}) async {
if (hasFixAllFix && !kind.canBeAppliedTogether()) {
fail('Expected to find and return fix-all FixKind for $kind, '
'but kind.canBeAppliedTogether is ${kind.canBeAppliedTogether}');
}
// Compute the fixes for this AnalysisError
final List<Fix> fixes = await _computeFixes(error);
// If hasFixAllFix is false, assert that none of the fixes are a fix-all fix
if (!hasFixAllFix) {
for (Fix fix in fixes) {
if (fix.isFixAllFix()) {
fail('The boolean hasFixAllFix is false, but such a fix was found '
'in the computed set of fixes: $fixes, error: $error.');
}
}
}
// If hasFixAllFix is true, assert that there exists such a fix in the list
else {
bool foundFixAllFix = false;
for (Fix fix in fixes) {
if (fix.isFixAllFix()) {
foundFixAllFix = true;
break;
}
}
if (!foundFixAllFix) {
fail('The boolean hasFixAllFix is true, but no fix-all fix was found '
'in the computed set of fixes: $fixes, error: $error.');
}
}
Fix foundFix = null;
if (!hasFixAllFix) {
foundFix = fixes.firstWhere(
(fix) => fix.kind == kind && !fix.isFixAllFix(),
orElse: () => null,
);
} else {
foundFix = fixes.lastWhere(
(fix) => fix.kind == kind && fix.isFixAllFix(),
orElse: () => null,
);
}
if (foundFix == null) {
fail('Expected to find fix $kind in\n${fixes.join('\n')}, hasFixAllFix = '
'$hasFixAllFix');
}
return foundFix;
}
void _assertLinkedGroup(LinkedEditGroup group, List<String> expectedStrings,
[List<LinkedEditSuggestion> expectedSuggestions]) {
List<Position> expectedPositions = _findResultPositions(expectedStrings);
expect(group.positions, unorderedEquals(expectedPositions));
if (expectedSuggestions != null) {
expect(group.suggestions, unorderedEquals(expectedSuggestions));
}
}
Future _assertNoFix(FixKind kind, AnalysisError error) async {
List<Fix> fixes = await _computeFixes(error);
for (Fix fix in fixes) {
if (fix.kind == kind) {
fail('Unexpected fix $kind in\n${fixes.join('\n')}');
}
}
}
Future<List<AnalysisError>> _computeErrors() async {
return (await driver.getResult(convertPath(testFile))).errors;
}
/**
* Computes fixes for the given [error] in [testUnit].
*/
Future<List<Fix>> _computeFixes(AnalysisError error) async {
DartFixContext fixContext = new _DartFixContextImpl(
resourceProvider,
driver,
new AstProviderForDriver(driver),
testUnit,
error,
await _computeErrors());
return await new DefaultFixContributor().internalComputeFixes(fixContext);
}
/**
* Configures the [SourceFactory] to have the `my_pkg` package in
* `/packages/my_pkg/lib` folder.
*/
void _configureMyPkg(Map<String, String> pathToCode) {
pathToCode.forEach((path, code) {
newFile('$myPkgLibPath/$path', content: code);
});
// configure SourceFactory
Folder myPkgFolder = getFolder(myPkgLibPath);
UriResolver pkgResolver = new PackageMapUriResolver(resourceProvider, {
'my_pkg': [myPkgFolder]
});
SourceFactory sourceFactory = new SourceFactory(
[new DartUriResolver(sdk), pkgResolver, resourceResolver]);
driver.configure(sourceFactory: sourceFactory);
// force 'my_pkg' resolution
addSource(
'/tmp/other.dart',
pathToCode.keys
.map((path) => "import 'package:my_pkg/$path';")
.join('\n'));
}
Future<AnalysisError> _findErrorToFix() async {
List<AnalysisError> errors = await _computeErrors();
List<AnalysisError> filteredErrors = errors;
if (errorFilter != null) {
filteredErrors = filteredErrors.where(errorFilter).toList();
}
if (filteredErrors.length != 1) {
StringBuffer buffer = new StringBuffer();
buffer.writeln('Expected one error, found:');
for (AnalysisError error in errors) {
buffer.writeln(' $error [${error.errorCode}]');
}
fail(buffer.toString());
}
return filteredErrors[0];
}
Future<AnalysisError> _findErrorToFixOfType(ErrorCode errorCode) async {
List<AnalysisError> errors = await _computeErrors();
if (errorFilter != null) {
errors = errors.where(errorFilter).toList();
}
return errors.firstWhere((error) => errorCode == error.errorCode);
}
List<Position> _findResultPositions(List<String> searchStrings) {
List<Position> positions = <Position>[];
for (String search in searchStrings) {
int offset = resultCode.indexOf(search);
positions.add(new Position(testFile, offset));
}
return positions;
}
}
@reflectiveTest
class FixProcessorTest extends BaseFixProcessorTest {
test_addAsync_asyncFor() async {
await resolveTestUnit('''
import 'dart:async';
void main(Stream<String> names) {
await for (String name in names) {
print(name);
}
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
import 'dart:async';
Future main(Stream<String> names) async {
await for (String name in names) {
print(name);
}
}
''');
}
test_addAsync_BAD_nullFunctionBody() async {
await resolveTestUnit('''
var F = await;
''');
await assertNoFix(DartFixKind.ADD_ASYNC);
}
test_addAsync_blockFunctionBody() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
foo() {}
main() {
await foo();
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
foo() {}
main() async {
await foo();
}
''');
}
test_addAsync_blockFunctionBody_getter() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
int get foo => null;
int f() {
await foo;
return 1;
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
import \'dart:async\';
int get foo => null;
Future<int> f() async {
await foo;
return 1;
}
''');
}
test_addAsync_closure() async {
errorFilter = (AnalysisError error) {
return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT;
};
await resolveTestUnit('''
import 'dart:async';
void takeFutureCallback(Future callback()) {}
void doStuff() => takeFutureCallback(() => await 1);
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
import 'dart:async';
void takeFutureCallback(Future callback()) {}
void doStuff() => takeFutureCallback(() async => await 1);
''');
}
test_addAsync_expressionFunctionBody() async {
errorFilter = (AnalysisError error) {
return error.errorCode == ParserErrorCode.UNEXPECTED_TOKEN;
};
await resolveTestUnit('''
foo() {}
main() => await foo();
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
foo() {}
main() async => await foo();
''');
}
test_addAsync_returnFuture() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
foo() {}
int main() {
await foo();
return 42;
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
import 'dart:async';
foo() {}
Future<int> main() async {
await foo();
return 42;
}
''');
}
test_addAsync_returnFuture_alreadyFuture() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
import 'dart:async';
foo() {}
Future<int> main() {
await foo();
return 42;
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
import 'dart:async';
foo() {}
Future<int> main() async {
await foo();
return 42;
}
''');
}
test_addAsync_returnFuture_dynamic() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
foo() {}
dynamic main() {
await foo();
return 42;
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
foo() {}
dynamic main() async {
await foo();
return 42;
}
''');
}
test_addAsync_returnFuture_noType() async {
errorFilter = (AnalysisError error) {
return error.errorCode ==
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE;
};
await resolveTestUnit('''
foo() {}
main() {
await foo();
return 42;
}
''');
await assertHasFix(DartFixKind.ADD_ASYNC, '''
foo() {}
main() async {
await foo();
return 42;
}
''');
}
test_addExplicitCast_assignment_general() async {
await resolveTestUnit('''
f(A a) {
B b;
b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b;
b = a as B;
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_general_all() async {
await resolveTestUnit('''
f(A a) {
B b, b2;
b = a;
b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b, b2;
b = a as B;
b2 = a as B;
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_list() async {
await resolveTestUnit('''
f(List<A> a) {
List<B> b;
b = a.where((e) => e is B).toList();
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
List<B> b;
b = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_list_all() async {
await resolveTestUnit('''
f(List<A> a) {
List<B> b, b2;
b = a.where((e) => e is B).toList();
b2 = a.where((e) => e is B).toList();
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
List<B> b, b2;
b = a.where((e) => e is B).cast<B>().toList();
b2 = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_map() async {
await resolveTestUnit('''
f(Map<A, B> a) {
Map<B, A> b;
b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(Map<A, B> a) {
Map<B, A> b;
b = a.cast<B, A>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_map_all() async {
await resolveTestUnit('''
f(Map<A, B> a) {
Map<B, A> b, b2;
b = a;
b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(Map<A, B> a) {
Map<B, A> b, b2;
b = a.cast<B, A>();
b2 = a.cast<B, A>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_needsParens() async {
await resolveTestUnit('''
f(A a) {
B b;
b = a..m();
}
class A {
int m() => 0;
}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b;
b = (a..m()) as B;
}
class A {
int m() => 0;
}
class B {}
''');
}
test_addExplicitCast_assignment_needsParens_all() async {
await resolveTestUnit('''
f(A a) {
B b, b2;
b = a..m();
b2 = a..m();
}
class A {
int m() => 0;
}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b, b2;
b = (a..m()) as B;
b2 = (a..m()) as B;
}
class A {
int m() => 0;
}
class B {}
''');
}
test_addExplicitCast_assignment_set() async {
await resolveTestUnit('''
f(Set<A> a) {
Set<B> b;
b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(Set<A> a) {
Set<B> b;
b = a.cast<B>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_assignment_set_all() async {
await resolveTestUnit('''
f(Set<A> a) {
Set<B> b, b2;
b = a;
b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(Set<A> a) {
Set<B> b, b2;
b = a.cast<B>();
b2 = a.cast<B>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_BAD_as() async {
await resolveTestUnit('''
f(A a) {
C c = a as B;
}
class A {}
class B {}
class C {}
''');
await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
}
test_addExplicitCast_BAD_cast() async {
await resolveTestUnit('''
f(List<A> a) {
List<B> b = a.cast<A>();
}
class A {}
class B {}
''');
await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
}
test_addExplicitCast_declaration_general() async {
await resolveTestUnit('''
f(A a) {
B b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b = a as B;
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_general_all() async {
await resolveTestUnit('''
f(A a) {
B b = a;
B b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b = a as B;
B b2 = a as B;
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_list() async {
await resolveTestUnit('''
f(List<A> a) {
List<B> b = a.where((e) => e is B).toList();
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
List<B> b = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_list_all() async {
await resolveTestUnit('''
f(List<A> a) {
List<B> b = a.where((e) => e is B).toList();
List<B> b2 = a.where((e) => e is B).toList();
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
List<B> b = a.where((e) => e is B).cast<B>().toList();
List<B> b2 = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_map() async {
await resolveTestUnit('''
f(Map<A, B> a) {
Map<B, A> b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(Map<A, B> a) {
Map<B, A> b = a.cast<B, A>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_map_all() async {
await resolveTestUnit('''
f(Map<A, B> a) {
Map<B, A> b = a;
Map<B, A> b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(Map<A, B> a) {
Map<B, A> b = a.cast<B, A>();
Map<B, A> b2 = a.cast<B, A>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_needsParens() async {
await resolveTestUnit('''
f(A a) {
B b = a..m();
}
class A {
int m() => 0;
}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b = (a..m()) as B;
}
class A {
int m() => 0;
}
class B {}
''');
}
test_addExplicitCast_declaration_needsParens_all() async {
await resolveTestUnit('''
f(A a) {
B b = a..m();
B b2 = a..m();
}
class A {
int m() => 0;
}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(A a) {
B b = (a..m()) as B;
B b2 = (a..m()) as B;
}
class A {
int m() => 0;
}
class B {}
''');
}
test_addExplicitCast_declaration_set() async {
await resolveTestUnit('''
f(Set<A> a) {
Set<B> b = a;
}
class A {}
class B {}
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(Set<A> a) {
Set<B> b = a.cast<B>();
}
class A {}
class B {}
''');
}
test_addExplicitCast_declaration_set_all() async {
await resolveTestUnit('''
f(Set<A> a) {
Set<B> b = a;
Set<B> b2 = a;
}
class A {}
class B {}
''');
await assertHasFixAllFix(StaticTypeWarningCode.INVALID_ASSIGNMENT,
DartFixKind.ADD_EXPLICIT_CAST, '''
f(Set<A> a) {
Set<B> b = a.cast<B>();
Set<B> b2 = a.cast<B>();
}
class A {}
class B {}
''');
}
test_addFieldFormalParameters_flutter() async {
addFlutterPackage();
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final int b;
final int c;
MyWidget({Key key, this.a}) : super(key: key);
}
''');
await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final int b;
final int c;
MyWidget({Key key, this.a, this.b, this.c}) : super(key: key);
}
''');
}
test_addFieldFormalParameters_hasRequiredParameter() async {
await resolveTestUnit('''
class Test {
final int a;
final int b;
final int c;
Test(this.a);
}
''');
await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
class Test {
final int a;
final int b;
final int c;
Test(this.a, this.b, this.c);
}
''');
}
test_addFieldFormalParameters_noParameters() async {
await resolveTestUnit('''
class Test {
final int a;
final int b;
final int c;
Test();
}
''');
await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
class Test {
final int a;
final int b;
final int c;
Test(this.a, this.b, this.c);
}
''');
}
test_addFieldFormalParameters_noRequiredParameter() async {
await resolveTestUnit('''
class Test {
final int a;
final int b;
final int c;
Test([this.c]);
}
''');
await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
class Test {
final int a;
final int b;
final int c;
Test(this.a, this.b, [this.c]);
}
''');
}
test_addFieldFormalParameters_notAllFinal() async {
await resolveTestUnit('''
class Test {
final int a;
int b;
final int c;
Test();
}
''');
await assertHasFix(DartFixKind.ADD_FIELD_FORMAL_PARAMETERS, '''
class Test {
final int a;
int b;
final int c;
Test(this.a, this.c);
}
''');
}
test_addMissingParameter_constructor_named_required_hasOne() async {
await resolveTestUnit('''
class A {
A.named(int a) {}
}
main() {
new A.named(1, 2.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
class A {
A.named(int a, double d) {}
}
main() {
new A.named(1, 2.0);
}
''');
}
test_addMissingParameter_constructor_unnamed_required_hasOne() async {
await resolveTestUnit('''
class A {
A(int a) {}
}
main() {
new A(1, 2.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
class A {
A(int a, double d) {}
}
main() {
new A(1, 2.0);
}
''');
}
test_addMissingParameter_function_positional_hasNamed() async {
await resolveTestUnit('''
test({int a}) {}
main() {
test(1);
}
''');
await assertNoFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL);
}
test_addMissingParameter_function_positional_hasZero() async {
await resolveTestUnit('''
test() {}
main() {
test(1);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, '''
test([int i]) {}
main() {
test(1);
}
''');
}
test_addMissingParameter_function_required_hasNamed() async {
await resolveTestUnit('''
test({int a}) {}
main() {
test(1);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
test(int i, {int a}) {}
main() {
test(1);
}
''');
}
test_addMissingParameter_function_required_hasOne() async {
await resolveTestUnit('''
test(int a) {}
main() {
test(1, 2.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
test(int a, double d) {}
main() {
test(1, 2.0);
}
''');
}
test_addMissingParameter_function_required_hasZero() async {
await resolveTestUnit('''
test() {}
main() {
test(1);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
test(int i) {}
main() {
test(1);
}
''');
}
test_addMissingParameter_method_positional_hasOne() async {
await resolveTestUnit('''
class A {
test(int a) {}
main() {
test(1, 2.0);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_POSITIONAL, '''
class A {
test(int a, [double d]) {}
main() {
test(1, 2.0);
}
}
''');
}
test_addMissingParameter_method_required_hasOne() async {
await resolveTestUnit('''
class A {
test(int a) {}
main() {
test(1, 2.0);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
class A {
test(int a, double d) {}
main() {
test(1, 2.0);
}
}
''');
}
test_addMissingParameter_method_required_hasZero() async {
await resolveTestUnit('''
class A {
test() {}
main() {
test(1);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_REQUIRED, '''
class A {
test(int i) {}
main() {
test(1);
}
}
''');
}
test_addMissingParameterNamed_constructor_hasNamed() async {
await resolveTestUnit('''
class A {
A(int a, {int b}) {}
}
main() {
new A(1, b: 2, named: 3.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
A(int a, {int b, double named}) {}
}
main() {
new A(1, b: 2, named: 3.0);
}
''');
}
test_addMissingParameterNamed_constructor_hasRequired() async {
await resolveTestUnit('''
class A {
A(int a) {}
}
main() {
new A(1, named: 2.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
A(int a, {double named}) {}
}
main() {
new A(1, named: 2.0);
}
''');
}
test_addMissingParameterNamed_constructor_noParameters() async {
await resolveTestUnit('''
class A {
A() {}
}
main() {
new A(named: 42);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
A({int named}) {}
}
main() {
new A(named: 42);
}
''');
}
test_addMissingParameterNamed_constructor_noParameters_named() async {
await resolveTestUnit('''
class A {
A.aaa() {}
}
main() {
new A.aaa(named: 42);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
A.aaa({int named}) {}
}
main() {
new A.aaa(named: 42);
}
''');
}
test_addMissingParameterNamed_function_hasNamed() async {
await resolveTestUnit('''
test(int a, {int b: 0}) {}
main() {
test(1, b: 2, named: 3.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
test(int a, {int b: 0, double named}) {}
main() {
test(1, b: 2, named: 3.0);
}
''');
}
test_addMissingParameterNamed_function_hasRequired() async {
await resolveTestUnit('''
test(int a) {}
main() {
test(1, named: 2.0);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
test(int a, {double named}) {}
main() {
test(1, named: 2.0);
}
''');
}
test_addMissingParameterNamed_function_noParameters() async {
await resolveTestUnit('''
test() {}
main() {
test(named: 42);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
test({int named}) {}
main() {
test(named: 42);
}
''');
}
test_addMissingParameterNamed_method_hasNamed() async {
await resolveTestUnit('''
class A {
test(int a, {int b: 0}) {}
main() {
test(1, b: 2, named: 3.0);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
test(int a, {int b: 0, double named}) {}
main() {
test(1, b: 2, named: 3.0);
}
}
''');
}
test_addMissingParameterNamed_method_hasOptionalPositional() async {
await resolveTestUnit('''
class A {
test(int a, [int b]) {}
main() {
test(1, 2, named: 3.0);
}
}
''');
await assertNoFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED);
}
test_addMissingParameterNamed_method_hasRequired() async {
await resolveTestUnit('''
class A {
test(int a) {}
main() {
test(1, named: 2.0);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
test(int a, {double named}) {}
main() {
test(1, named: 2.0);
}
}
''');
}
test_addMissingParameterNamed_method_noParameters() async {
await resolveTestUnit('''
class A {
test() {}
main() {
test(named: 42);
}
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_PARAMETER_NAMED, '''
class A {
test({int named}) {}
main() {
test(named: 42);
}
}
''');
}
test_addMissingRequiredArg_cons_flutter_children() async {
addFlutterPackage();
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
class MyWidget extends Widget {
MyWidget({@required List<Widget> children});
}
build() {
return new MyWidget();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
class MyWidget extends Widget {
MyWidget({@required List<Widget> children});
}
build() {
return new MyWidget(children: <Widget>[],);
}
''');
}
test_addMissingRequiredArg_cons_flutter_hasTrailingComma() async {
addFlutterPackage();
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
class MyWidget extends Widget {
MyWidget({@required int a, @required int b});
}
build() {
return new MyWidget(a: 1,);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
class MyWidget extends Widget {
MyWidget({@required int a, @required int b});
}
build() {
return new MyWidget(a: 1, b: null,);
}
''');
}
test_addMissingRequiredArg_cons_single() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
class A {
A({@required int a}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(a: null);
}
''');
}
test_addMissingRequiredArg_cons_single_closure() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
typedef void VoidCallback();
class A {
A({@required VoidCallback onPressed}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(onPressed: () {});
}
''');
}
test_addMissingRequiredArg_cons_single_closure_2() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
typedef void Callback(e);
class A {
A({@required Callback callback}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(callback: (e) {});
}
''');
}
test_addMissingRequiredArg_cons_single_closure_3() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
typedef void Callback(a,b,c);
class A {
A({@required Callback callback}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(callback: (a, b, c) {});
}
''');
}
test_addMissingRequiredArg_cons_single_closure_4() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
typedef int Callback(int a, String b,c);
class A {
A({@required Callback callback}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(callback: (int a, String b, c) {});
}
''');
}
test_addMissingRequiredArg_cons_single_list() async {
_addMetaPackageSource();
addSource('/project/libA.dart', r'''
library libA;
import 'package:meta/meta.dart';
class A {
A({@required List<String> names}) {}
}
''');
await resolveTestUnit('''
import 'libA.dart';
main() {
A a = new A();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'libA.dart';
main() {
A a = new A(names: <String>[]);
}
''');
}
test_addMissingRequiredArg_multiple() async {
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:meta/meta.dart';
test({@required int a, @required int bcd}) {}
main() {
test(a: 3);
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:meta/meta.dart';
test({@required int a, @required int bcd}) {}
main() {
test(a: 3, bcd: null);
}
''');
}
test_addMissingRequiredArg_multiple_2() async {
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:meta/meta.dart';
test({@required int a, @required int bcd}) {}
main() {
test();
}
''');
// For now we expect one error per missing arg (dartbug.com/28830).
List<AnalysisError> errors = await _computeErrors();
expect(errors, hasLength(2));
List<AnalysisError> filteredErrors = errors
.where((e) => e.message == "The parameter 'a' is required.")
.toList();
expect(filteredErrors, hasLength(1));
List<Fix> fixes = await _computeFixes(filteredErrors.first);
List<Fix> filteredFixes = fixes
.where((fix) => fix.change.message == "Add required argument 'a'")
.toList();
expect(filteredFixes, hasLength(1));
change = filteredFixes.first.change;
resultCode = SourceEdit.applySequence(testCode, change.edits[0].edits);
// verify
expect(resultCode, '''
import 'package:meta/meta.dart';
test({@required int a, @required int bcd}) {}
main() {
test(a: null);
}
''');
}
test_addMissingRequiredArg_single() async {
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:meta/meta.dart';
test({@required int abc}) {}
main() {
test();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:meta/meta.dart';
test({@required int abc}) {}
main() {
test(abc: null);
}
''');
}
test_addMissingRequiredArg_single_normal() async {
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:meta/meta.dart';
test(String x, {@required int abc}) {}
main() {
test("foo");
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:meta/meta.dart';
test(String x, {@required int abc}) {}
main() {
test("foo", abc: null);
}
''');
}
test_addMissingRequiredArg_single_with_details() async {
_addMetaPackageSource();
await resolveTestUnit('''
import 'package:meta/meta.dart';
test({@Required("Really who doesn't need an abc?") int abc}) {}
main() {
test();
}
''');
await assertHasFix(DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT, '''
import 'package:meta/meta.dart';
test({@Required("Really who doesn't need an abc?") int abc}) {}
main() {
test(abc: null);
}
''');
}
test_addStatic_multipleFields() async {
await resolveTestUnit('''
class C {
const int x = 0, y = 0;
}
''');
await assertHasFix(DartFixKind.ADD_STATIC, '''
class C {
static const int x = 0, y = 0;
}
''');
}
test_addStatic_oneField() async {
await resolveTestUnit('''
class C {
const int x = 0;
}
''');
await assertHasFix(DartFixKind.ADD_STATIC, '''
class C {
static const int x = 0;
}
''');
}
test_boolean() async {
await resolveTestUnit('''
main() {
boolean v;
}
''');
await assertHasFix(DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, '''
main() {
bool v;
}
''');
}
test_boolean_all() async {
await resolveTestUnit('''
main() {
boolean v;
boolean w;
}
''');
await assertHasFixAllFix(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN,
DartFixKind.REPLACE_BOOLEAN_WITH_BOOL, '''
main() {
bool v;
bool w;
}
''');
}
test_canBeNullAfterNullAware_chain() async {
await resolveTestUnit('''
main(x) {
x?.a.b.c;
}
''');
await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, '''
main(x) {
x?.a?.b?.c;
}
''');
}
test_canBeNullAfterNullAware_methodInvocation() async {
await resolveTestUnit('''
main(x) {
x?.a.b();
}
''');
await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, '''
main(x) {
x?.a?.b();
}
''');
}
test_canBeNullAfterNullAware_propertyAccess() async {
await resolveTestUnit('''
main(x) {
x?.a().b;
}
''');
await assertHasFix(DartFixKind.REPLACE_WITH_NULL_AWARE, '''
main(x) {
x?.a()?.b;
}
''');
}
test_changeToStaticAccess_method() async {
await resolveTestUnit('''
class A {
static foo() {}
}
main(A a) {
a.foo();
}
''');
await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
class A {
static foo() {}
}
main(A a) {
A.foo();
}
''');
}
test_changeToStaticAccess_method_importType() async {
addSource('/project/libA.dart', r'''
library libA;
class A {
static foo() {}
}
''');
addSource('/project/libB.dart', r'''
library libB;
import 'libA.dart';
class B extends A {}
''');
await resolveTestUnit('''
import 'libB.dart';
main(B b) {
b.foo();
}
''');
await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
import 'libA.dart';
import 'libB.dart';
main(B b) {
A.foo();
}
''');
}
test_changeToStaticAccess_method_prefixLibrary() async {
await resolveTestUnit('''
import 'dart:async' as pref;
main(pref.Future f) {
f.wait([]);
}
''');
await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
import 'dart:async' as pref;
main(pref.Future f) {
pref.Future.wait([]);
}
''');
}
test_changeToStaticAccess_property() async {
await resolveTestUnit('''
class A {
static get foo => 42;
}
main(A a) {
a.foo;
}
''');
await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
class A {
static get foo => 42;
}
main(A a) {
A.foo;
}
''');
}
test_changeToStaticAccess_property_importType() async {
addSource('/project/libA.dart', r'''
library libA;
class A {
static get foo => null;
}
''');
addSource('/project/libB.dart', r'''
library libB;
import 'libA.dart';
class B extends A {}
''');
await resolveTestUnit('''
import 'libB.dart';
main(B b) {
b.foo;
}
''');
await assertHasFix(DartFixKind.CHANGE_TO_STATIC_ACCESS, '''
import 'libA.dart';
import 'libB.dart';
main(B b) {
A.foo;
}
''');
}
test_changeTypeAnnotation_BAD_multipleVariables() async {
await resolveTestUnit('''
main() {
String a, b = 42;
}
''');
await assertNoFix(DartFixKind.CHANGE_TYPE_ANNOTATION);
}
test_changeTypeAnnotation_BAD_notVariableDeclaration() async {
await resolveTestUnit('''
main() {
String v;
v = 42;
}
''');
await assertNoFix(DartFixKind.CHANGE_TYPE_ANNOTATION);
}
test_changeTypeAnnotation_OK_generic() async {
await resolveTestUnit('''
main() {
String v = <int>[];
}
''');
await assertHasFix(DartFixKind.CHANGE_TYPE_ANNOTATION, '''
main() {
List<int> v = <int>[];
}
''');
}
test_changeTypeAnnotation_OK_simple() async {
await resolveTestUnit('''
main() {
String v = 'abc'.length;
}
''');
await assertHasFix(DartFixKind.CHANGE_TYPE_ANNOTATION, '''
main() {
int v = 'abc'.length;
}
''');
}
test_convertToNamedArguments_BAD_ambiguous() async {
await resolveTestUnit('''
class A {
A({int a, int b});
}
main() {
new A(1, 2);
}
''');
await assertNoFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS);
}
test_convertToNamedArguments_BAD_noCompatibleParameter() async {
await resolveTestUnit('''
class A {
A({String a});
}
main() {
new A(1);
}
''');
await assertNoFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS);
}
test_convertToNamedArguments_OK_instanceCreation() async {
await resolveTestUnit('''
class A {
A({int a, double b});
}
main() {
new A(1.2, 3);
}
''');
await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, '''
class A {
A({int a, double b});
}
main() {
new A(b: 1.2, a: 3);
}
''');
}
test_convertToNamedArguments_OK_instanceCreation_hasPositional() async {
await resolveTestUnit('''
class A {
A(int a, {int b});
}
main() {
new A(1, 2);
}
''');
await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, '''
class A {
A(int a, {int b});
}
main() {
new A(1, b: 2);
}
''');
}
test_convertToNamedArguments_OK_methodInvocation() async {
await resolveTestUnit('''
class C {
void foo({int a}) {}
}
main(C c) {
c.foo(1);
}
''');
await assertHasFix(DartFixKind.CONVERT_TO_NAMED_ARGUMENTS, '''
class C {
void foo({int a}) {}
}
main(C c) {
c.foo(a: 1);
}
''');
}
test_createClass() async {
await resolveTestUnit('''
main() {
Test v = null;
}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
main() {
Test v = null;
}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']);
}
test_createClass_BAD_hasUnresolvedPrefix() async {
await resolveTestUnit('''
main() {
prefix.Test v = null;
}
''');
await assertNoFix(DartFixKind.CREATE_CLASS);
}
test_createClass_inLibraryOfPrefix() async {
String libCode = r'''
library my.lib;
class A {}
''';
addSource('/project/lib.dart', libCode);
await resolveTestUnit('''
import 'lib.dart' as lib;
main() {
lib.A a = null;
lib.Test t = null;
}
''');
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_CLASS, error);
change = fix.change;
// apply to "lib.dart"
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file, convertPath('/project/lib.dart'));
expect(SourceEdit.applySequence(libCode, fileEdit.edits), r'''
library my.lib;
class A {}
class Test {
}
''');
expect(change.linkedEditGroups, hasLength(1));
}
test_createClass_innerLocalFunction() async {
await resolveTestUnit('''
f() {
g() {
Test v = null;
}
}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
f() {
g() {
Test v = null;
}
}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test v =', 'Test {']);
}
test_createClass_instanceCreation_withoutNew_fromFunction() async {
await resolveTestUnit('''
main() {
Test ();
}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
main() {
Test ();
}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']);
}
test_createClass_instanceCreation_withoutNew_fromMethod() async {
await resolveTestUnit('''
class A {
main() {
Test ();
}
}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
class A {
main() {
Test ();
}
}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test ()', 'Test {']);
}
test_createClass_itemOfList() async {
await resolveTestUnit('''
main() {
var a = [Test];
}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
main() {
var a = [Test];
}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test];', 'Test {']);
}
test_createClass_itemOfList_inAnnotation() async {
errorFilter = (AnalysisError error) {
return error.errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER;
};
await resolveTestUnit('''
class MyAnnotation {
const MyAnnotation(a, b);
}
@MyAnnotation(int, const [Test])
main() {}
''');
await assertHasFix(DartFixKind.CREATE_CLASS, '''
class MyAnnotation {
const MyAnnotation(a, b);
}
@MyAnnotation(int, const [Test])
main() {}
class Test {
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['Test])', 'Test {']);
}
test_createConstructor_forFinalFields() async {
errorFilter = (AnalysisError error) {
return error.message.contains("'a'");
};
await resolveTestUnit('''
class Test {
final int a;
final int b = 2;
final int c;
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, '''
class Test {
final int a;
final int b = 2;
final int c;
Test(this.a, this.c);
}
''');
}
test_createConstructor_forFinalFields_flutter() async {
addFlutterPackage();
errorFilter = (AnalysisError error) {
return error.message.contains("'a'");
};
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final int b = 2;
final int c;
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, '''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final int b = 2;
final int c;
const MyWidget({Key key, this.a, this.c}) : super(key: key);
}
''');
}
test_createConstructor_forFinalFields_flutter_childLast() async {
addFlutterPackage();
errorFilter = (AnalysisError error) {
return error.message.contains("'a'");
};
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final Widget child;
final int b;
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, '''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final Widget child;
final int b;
const MyWidget({Key key, this.a, this.b, this.child}) : super(key: key);
}
''');
}
test_createConstructor_forFinalFields_flutter_childrenLast() async {
addFlutterPackage();
errorFilter = (AnalysisError error) {
return error.message.contains("'a'");
};
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final List<Widget> children;
final int b;
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS, '''
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final int a;
final List<Widget> children;
final int b;
const MyWidget({Key key, this.a, this.b, this.children}) : super(key: key);
}
''');
}
test_createConstructor_insteadOfSyntheticDefault() async {
await resolveTestUnit('''
class A {
int field;
method() {}
}
main() {
new A(1, 2.0);
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, '''
class A {
int field;
A(int i, double d);
method() {}
}
main() {
new A(1, 2.0);
}
''');
}
test_createConstructor_named() async {
await resolveTestUnit('''
class A {
method() {}
}
main() {
new A.named(1, 2.0);
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, '''
class A {
A.named(int i, double d);
method() {}
}
main() {
new A.named(1, 2.0);
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']);
}
test_createConstructor_named_emptyClassBody() async {
await resolveTestUnit('''
class A {}
main() {
new A.named(1);
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR, '''
class A {
A.named(int i);
}
main() {
new A.named(1);
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['named(int ', 'named(1']);
}
test_createConstructorForFinalFields_inTopLevelMethod() async {
await resolveTestUnit('''
main() {
final int v;
}
''');
await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS);
}
test_createConstructorForFinalFields_topLevelField() async {
await resolveTestUnit('''
final int v;
''');
await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_FOR_FINAL_FIELDS);
}
test_createConstructorSuperExplicit() async {
await resolveTestUnit('''
class A {
A(bool p1, int p2, double p3, String p4, {p5});
}
class B extends A {
B() {}
}
''');
await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
class A {
A(bool p1, int p2, double p3, String p4, {p5});
}
class B extends A {
B() : super(false, 0, 0.0, '') {}
}
''');
}
test_createConstructorSuperExplicit_hasInitializers() async {
await resolveTestUnit('''
class A {
A(int p);
}
class B extends A {
int field;
B() : field = 42 {}
}
''');
await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
class A {
A(int p);
}
class B extends A {
int field;
B() : field = 42, super(0) {}
}
''');
}
test_createConstructorSuperExplicit_named() async {
await resolveTestUnit('''
class A {
A.named(int p);
}
class B extends A {
B() {}
}
''');
await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
class A {
A.named(int p);
}
class B extends A {
B() : super.named(0) {}
}
''');
}
test_createConstructorSuperExplicit_named_private() async {
await resolveTestUnit('''
class A {
A._named(int p);
}
class B extends A {
B() {}
}
''');
await assertNoFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION);
}
test_createConstructorSuperExplicit_typeArgument() async {
await resolveTestUnit('''
class A<T> {
A(T p);
}
class B extends A<int> {
B();
}
''');
await assertHasFix(DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, '''
class A<T> {
A(T p);
}
class B extends A<int> {
B() : super(0);
}
''');
}
test_createConstructorSuperImplicit() async {
await resolveTestUnit('''
class A {
A(p1, int p2, List<String> p3, [int p4]);
}
class B extends A {
int existingField;
void existingMethod() {}
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
class A {
A(p1, int p2, List<String> p3, [int p4]);
}
class B extends A {
int existingField;
B(p1, int p2, List<String> p3) : super(p1, p2, p3);
void existingMethod() {}
}
''');
}
test_createConstructorSuperImplicit_fieldInitializer() async {
await resolveTestUnit('''
class A {
int _field;
A(this._field);
}
class B extends A {
int existingField;
void existingMethod() {}
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
class A {
int _field;
A(this._field);
}
class B extends A {
int existingField;
B(int field) : super(field);
void existingMethod() {}
}
''');
}
test_createConstructorSuperImplicit_importType() async {
addSource('/project/libA.dart', r'''
library libA;
class A {}
''');
addSource('/project/libB.dart', r'''
library libB;
import 'libA.dart';
class B {
B(A a);
}
''');
await resolveTestUnit('''
import 'libB.dart';
class C extends B {
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
import 'libA.dart';
import 'libB.dart';
class C extends B {
C(A a) : super(a);
}
''');
}
test_createConstructorSuperImplicit_named() async {
await resolveTestUnit('''
class A {
A.named(p1, int p2);
}
class B extends A {
int existingField;
void existingMethod() {}
}
''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
class A {
A.named(p1, int p2);
}
class B extends A {
int existingField;
B.named(p1, int p2) : super.named(p1, p2);
void existingMethod() {}
}
''');
}
test_createConstructorSuperImplicit_private() async {
await resolveTestUnit('''
class A {
A._named(p);
}
class B extends A {
}
''');
await assertNoFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER);
}
test_createConstructorSuperImplicit_typeArgument() async {
await resolveTestUnit('''
class C<T> {
final T x;
C(this.x);
}
class D extends C<int> {
}''');
await assertHasFix(DartFixKind.CREATE_CONSTRUCTOR_SUPER, '''
class C<T> {
final T x;
C(this.x);
}
class D extends C<int> {
D(int x) : super(x);
}''');
}
test_createField_BAD_inEnum() async {
await resolveTestUnit('''
enum MyEnum {
AAA, BBB
}
main() {
MyEnum.foo;
}
''');
await assertNoFix(DartFixKind.CREATE_FIELD);
}
test_createField_BAD_inSDK() async {
await resolveTestUnit('''
main(List p) {
p.foo = 1;
}
''');
await assertNoFix(DartFixKind.CREATE_FIELD);
}
test_createField_getter_multiLevel() async {
await resolveTestUnit('''
class A {
}
class B {
A a;
}
class C {
B b;
}
main(C c) {
int v = c.b.a.test;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
}
class B {
A a;
}
class C {
B b;
}
main(C c) {
int v = c.b.a.test;
}
''');
}
test_createField_getter_qualified_instance() async {
await resolveTestUnit('''
class A {
}
main(A a) {
int v = a.test;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
}
main(A a) {
int v = a.test;
}
''');
}
test_createField_getter_qualified_instance_differentLibrary() async {
addSource('/project/other.dart', '''
/**
* A comment to push the offset of the braces for the following class
* declaration past the end of the content of the test file. Used to catch an
* index out of bounds exception that occurs when using the test source instead
* of the target source to compute the location at which to insert the field.
*/
class A {
}
''');
await resolveTestUnit('''
import 'other.dart';
main(A a) {
int v = a.test;
}
''');
await assertHasFix(
DartFixKind.CREATE_FIELD,
'''
/**
* A comment to push the offset of the braces for the following class
* declaration past the end of the content of the test file. Used to catch an
* index out of bounds exception that occurs when using the test source instead
* of the target source to compute the location at which to insert the field.
*/
class A {
int test;
}
''',
target: '/project/other.dart');
}
test_createField_getter_qualified_instance_dynamicType() async {
await resolveTestUnit('''
class A {
B b;
void f(Object p) {
p == b.test;
}
}
class B {
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
B b;
void f(Object p) {
p == b.test;
}
}
class B {
var test;
}
''');
}
test_createField_getter_qualified_propagatedType() async {
await resolveTestUnit('''
class A {
A get self => this;
}
main() {
var a = new A();
int v = a.self.test;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
A get self => this;
}
main() {
var a = new A();
int v = a.self.test;
}
''');
}
test_createField_getter_unqualified_instance_asInvocationArgument() async {
await resolveTestUnit('''
class A {
main() {
f(test);
}
}
f(String s) {}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
String test;
main() {
f(test);
}
}
f(String s) {}
''');
}
test_createField_getter_unqualified_instance_assignmentRhs() async {
await resolveTestUnit('''
class A {
main() {
int v = test;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
main() {
int v = test;
}
}
''');
}
test_createField_getter_unqualified_instance_asStatement() async {
await resolveTestUnit('''
class A {
main() {
test;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
var test;
main() {
test;
}
}
''');
}
test_createField_hint() async {
await resolveTestUnit('''
class A {
}
main(A a) {
var x = a;
int v = x.test;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
}
main(A a) {
var x = a;
int v = x.test;
}
''');
}
test_createField_hint_setter() async {
await resolveTestUnit('''
class A {
}
main(A a) {
var x = a;
x.test = 0;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
}
main(A a) {
var x = a;
x.test = 0;
}
''');
}
test_createField_importType() async {
addSource('/project/libA.dart', r'''
library libA;
class A {}
''');
addSource('/project/libB.dart', r'''
library libB;
import 'libA.dart';
A getA() => null;
''');
await resolveTestUnit('''
import 'libB.dart';
class C {
}
main(C c) {
c.test = getA();
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
import 'libA.dart';
import 'libB.dart';
class C {
A test;
}
main(C c) {
c.test = getA();
}
''');
}
test_createField_invalidInitializer_withoutType() async {
await resolveTestUnit('''
class C {
C(this.text);
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class C {
var text;
C(this.text);
}
''');
}
test_createField_invalidInitializer_withType() async {
await resolveTestUnit('''
class C {
C(String this.text);
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class C {
String text;
C(String this.text);
}
''');
}
test_createField_setter_generic_BAD() async {
await resolveTestUnit('''
class A {
}
class B<T> {
List<T> items;
main(A a) {
a.test = items;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
List test;
}
class B<T> {
List<T> items;
main(A a) {
a.test = items;
}
}
''');
}
test_createField_setter_generic_OK_local() async {
await resolveTestUnit('''
class A<T> {
List<T> items;
main(A a) {
test = items;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A<T> {
List<T> items;
List<T> test;
main(A a) {
test = items;
}
}
''');
}
test_createField_setter_qualified_instance_hasField() async {
await resolveTestUnit('''
class A {
int aaa;
int zzz;
existingMethod() {}
}
main(A a) {
a.test = 5;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int aaa;
int zzz;
int test;
existingMethod() {}
}
main(A a) {
a.test = 5;
}
''');
}
test_createField_setter_qualified_instance_hasMethod() async {
await resolveTestUnit('''
class A {
existingMethod() {}
}
main(A a) {
a.test = 5;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
existingMethod() {}
}
main(A a) {
a.test = 5;
}
''');
}
test_createField_setter_qualified_static() async {
await resolveTestUnit('''
class A {
}
main() {
A.test = 5;
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
static int test;
}
main() {
A.test = 5;
}
''');
}
test_createField_setter_unqualified_instance() async {
await resolveTestUnit('''
class A {
main() {
test = 5;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
int test;
main() {
test = 5;
}
}
''');
}
test_createField_setter_unqualified_static() async {
await resolveTestUnit('''
class A {
static main() {
test = 5;
}
}
''');
await assertHasFix(DartFixKind.CREATE_FIELD, '''
class A {
static int test;
static main() {
test = 5;
}
}
''');
}
test_createFile_forImport() async {
testFile = '/my/project/bin/test.dart';
await resolveTestUnit('''
import 'my_file.dart';
''');
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_FILE, error);
change = fix.change;
// validate change
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file, convertPath('/my/project/bin/my_file.dart'));
expect(fileEdit.fileStamp, -1);
expect(fileEdit.edits, hasLength(1));
expect(fileEdit.edits[0].replacement, contains('library my_file;'));
}
test_createFile_forImport_BAD_inPackage_lib_justLib() async {
newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package');
testFile = '/projects/my_package/test.dart';
await resolveTestUnit('''
import 'lib';
''');
await assertNoFix(DartFixKind.CREATE_FILE);
}
test_createFile_forImport_BAD_notDart() async {
testFile = '/my/project/bin/test.dart';
await resolveTestUnit('''
import 'my_file.txt';
''');
await assertNoFix(DartFixKind.CREATE_FILE);
}
test_createFile_forImport_inPackage_lib() async {
newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package');
testFile = '/projects/my_package/lib/test.dart';
newFolder('/projects/my_package/lib');
await resolveTestUnit('''
import 'a/bb/c_cc/my_lib.dart';
''');
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_FILE, error);
change = fix.change;
// validate change
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file,
convertPath('/projects/my_package/lib/a/bb/c_cc/my_lib.dart'));
expect(fileEdit.fileStamp, -1);
expect(fileEdit.edits, hasLength(1));
expect(fileEdit.edits[0].replacement,
contains('library my_package.a.bb.c_cc.my_lib;'));
}
test_createFile_forImport_inPackage_test() async {
newFile('/projects/my_package/pubspec.yaml', content: 'name: my_package');
testFile = '/projects/my_package/test/misc/test_all.dart';
await resolveTestUnit('''
import 'a/bb/my_lib.dart';
''');
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_FILE, error);
change = fix.change;
// validate change
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file,
convertPath('/projects/my_package/test/misc/a/bb/my_lib.dart'));
expect(fileEdit.fileStamp, -1);
expect(fileEdit.edits, hasLength(1));
expect(fileEdit.edits[0].replacement,
contains('library my_package.test.misc.a.bb.my_lib;'));
}
test_createFile_forPart() async {
testFile = convertPath('/my/project/bin/test.dart');
await resolveTestUnit('''
library my.lib;
part 'my_part.dart';
''');
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_FILE, error);
change = fix.change;
// validate change
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file, convertPath('/my/project/bin/my_part.dart'));
expect(fileEdit.fileStamp, -1);
expect(fileEdit.edits, hasLength(1));
expect(fileEdit.edits[0].replacement, contains('part of my.lib;'));
}
test_createFile_forPart_inPackageLib() async {
newFile('/my/pubspec.yaml', content: r'''
name: my_test
''');
testFile = '/my/lib/test.dart';
addTestSource('''
library my.lib;
part 'my_part.dart';
''', Uri.parse('package:my/test.dart'));
// configure SourceFactory
UriResolver pkgResolver = new PackageMapUriResolver(resourceProvider, {
'my': <Folder>[getFolder('/my/lib')],
});
SourceFactory sourceFactory = new SourceFactory(
[new DartUriResolver(sdk), pkgResolver, resourceResolver]);
driver.configure(sourceFactory: sourceFactory);
testUnit = (await driver.getResult(convertPath(testFile))).unit;
// prepare fix
AnalysisError error = await _findErrorToFix();
fix = await _assertHasFix(DartFixKind.CREATE_FILE, error);
change = fix.change;
// validate change
List<SourceFileEdit> fileEdits = change.edits;
expect(fileEdits, hasLength(1));
SourceFileEdit fileEdit = change.edits[0];
expect(fileEdit.file, convertPath('/my/lib/my_part.dart'));
expect(fileEdit.fileStamp, -1);
expect(fileEdit.edits, hasLength(1));
expect(fileEdit.edits[0].replacement, contains('part of my.lib;'));
}
test_createGetter_BAD_inSDK() async {
await resolveTestUnit('''
main(List p) {
int v = p.foo;
}
''');
await assertNoFix(DartFixKind.CREATE_GETTER);
}
test_createGetter_hint_getter() async {
await resolveTestUnit('''
class A {
}
main(A a) {
var x = a;
int v = x.test;
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
int get test => null;
}
main(A a) {
var x = a;
int v = x.test;
}
''');
}
test_createGetter_location_afterLastGetter() async {
await resolveTestUnit('''
class A {
int existingField;
int get existingGetter => null;
existingMethod() {}
}
main(A a) {
int v = a.test;
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
int existingField;
int get existingGetter => null;
int get test => null;
existingMethod() {}
}
main(A a) {
int v = a.test;
}
''');
}
test_createGetter_multiLevel() async {
await resolveTestUnit('''
class A {
}
class B {
A a;
}
class C {
B b;
}
main(C c) {
int v = c.b.a.test;
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
int get test => null;
}
class B {
A a;
}
class C {
B b;
}
main(C c) {
int v = c.b.a.test;
}
''');
}
test_createGetter_qualified_instance() async {
await resolveTestUnit('''
class A {
}
main(A a) {
int v = a.test;
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
int get test => null;
}
main(A a) {
int v = a.test;
}
''');
}
test_createGetter_qualified_instance_differentLibrary() async {
addSource('/project/other.dart', '''
/**
* A comment to push the offset of the braces for the following class
* declaration past the end of the content of the test file. Used to catch an
* index out of bounds exception that occurs when using the test source instead
* of the target source to compute the location at which to insert the field.
*/
class A {
}
''');
await resolveTestUnit('''
import 'other.dart';
main(A a) {
int v = a.test;
}
''');
await assertHasFix(
DartFixKind.CREATE_GETTER,
'''
/**
* A comment to push the offset of the braces for the following class
* declaration past the end of the content of the test file. Used to catch an
* index out of bounds exception that occurs when using the test source instead
* of the target source to compute the location at which to insert the field.
*/
class A {
int get test => null;
}
''',
target: '/project/other.dart');
}
test_createGetter_qualified_instance_dynamicType() async {
await resolveTestUnit('''
class A {
B b;
void f(Object p) {
p == b.test;
}
}
class B {
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
B b;
void f(Object p) {
p == b.test;
}
}
class B {
get test => null;
}
''');
}
test_createGetter_qualified_propagatedType() async {
await resolveTestUnit('''
class A {
A get self => this;
}
main() {
var a = new A();
int v = a.self.test;
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
A get self => this;
int get test => null;
}
main() {
var a = new A();
int v = a.self.test;
}
''');
}
test_createGetter_setterContext() async {
await resolveTestUnit('''
class A {
}
main(A a) {
a.test = 42;
}
''');
await assertNoFix(DartFixKind.CREATE_GETTER);
}
test_createGetter_unqualified_instance_asInvocationArgument() async {
await resolveTestUnit('''
class A {
main() {
f(test);
}
}
f(String s) {}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
String get test => null;
main() {
f(test);
}
}
f(String s) {}
''');
}
test_createGetter_unqualified_instance_assignmentLhs() async {
await resolveTestUnit('''
class A {
main() {
test = 42;
}
}
''');
await assertNoFix(DartFixKind.CREATE_GETTER);
}
test_createGetter_unqualified_instance_assignmentRhs() async {
await resolveTestUnit('''
class A {
main() {
int v = test;
}
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
int get test => null;
main() {
int v = test;
}
}
''');
}
test_createGetter_unqualified_instance_asStatement() async {
await resolveTestUnit('''
class A {
main() {
test;
}
}
''');
await assertHasFix(DartFixKind.CREATE_GETTER, '''
class A {
get test => null;
main() {
test;
}
}
''');
}
test_createLocalVariable_functionType_named() async {
await resolveTestUnit('''
typedef MY_FUNCTION(int p);
foo(MY_FUNCTION f) {}
main() {
foo(bar);
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
typedef MY_FUNCTION(int p);
foo(MY_FUNCTION f) {}
main() {
MY_FUNCTION bar;
foo(bar);
}
''');
}
test_createLocalVariable_functionType_named_generic() async {
await resolveTestUnit('''
typedef MY_FUNCTION<T>(T p);
foo(MY_FUNCTION<int> f) {}
main() {
foo(bar);
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
typedef MY_FUNCTION<T>(T p);
foo(MY_FUNCTION<int> f) {}
main() {
MY_FUNCTION<int> bar;
foo(bar);
}
''');
}
test_createLocalVariable_functionType_synthetic() async {
await resolveTestUnit('''
foo(f(int p)) {}
main() {
foo(bar);
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
foo(f(int p)) {}
main() {
Function(int p) bar;
foo(bar);
}
''');
}
test_createLocalVariable_read_typeAssignment() async {
await resolveTestUnit('''
main() {
int a = test;
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
int test;
int a = test;
}
''');
}
test_createLocalVariable_read_typeCondition() async {
await resolveTestUnit('''
main() {
if (!test) {
print(42);
}
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
bool test;
if (!test) {
print(42);
}
}
''');
}
test_createLocalVariable_read_typeInvocationArgument() async {
await resolveTestUnit('''
main() {
f(test);
}
f(String p) {}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
String test;
f(test);
}
f(String p) {}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['String test;']);
_assertLinkedGroup(change.linkedEditGroups[1], ['test;', 'test);']);
}
test_createLocalVariable_read_typeInvocationTarget() async {
await resolveTestUnit('''
main() {
test.add('hello');
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
var test;
test.add('hello');
}
''');
_assertLinkedGroup(change.linkedEditGroups[0], ['test;', 'test.add(']);
}
test_createLocalVariable_withImport() async {
addPackageSource('pkg', 'a/a.dart', '''
class A {}
''');
addPackageSource('pkg', 'b/b.dart', '''
class B {}
''');
addPackageSource('pkg', 'c/c.dart', '''
import 'package:pkg/a/a.dart';
import 'package:pkg/b/b.dart';
class C {
C(A a, B b);
}
''');
await resolveTestUnit('''
import 'package:pkg/a/a.dart';
import 'package:pkg/c/c.dart';
main() {
A a;
new C(a, b);
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
import 'package:pkg/a/a.dart';
import 'package:pkg/b/b.dart';
import 'package:pkg/c/c.dart';
main() {
A a;
B b;
new C(a, b);
}
''');
List<LinkedEditGroup> groups = change.linkedEditGroups;
expect(groups, hasLength(2));
LinkedEditGroup typeGroup = groups[0];
List<Position> typePositions = typeGroup.positions;
expect(typePositions, hasLength(1));
expect(typePositions[0].offset, 112);
LinkedEditGroup nameGroup = groups[1];
List<Position> groupPositions = nameGroup.positions;
expect(groupPositions, hasLength(2));
expect(groupPositions[0].offset, 114);
expect(groupPositions[1].offset, 128);
}
test_createLocalVariable_write_assignment() async {
await resolveTestUnit('''
main() {
test = 42;
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
var test = 42;
}
''');
}
test_createLocalVariable_write_assignment_compound() async {
await resolveTestUnit('''
main() {
test += 42;
}
''');
await assertHasFix(DartFixKind.CREATE_LOCAL_VARIABLE, '''
main() {
int test;
test += 42;
}
''');
}
test_createMissingOverrides_field_untyped() async {
await resolveTestUnit('''
class A {
var f;
}
class B implements A {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
class A {
var f;
}
class B implements A {
@override
var f;
}
''');
}
test_createMissingOverrides_functionTypeAlias() async {
await resolveTestUnit('''
typedef int Binary(int left, int right);
abstract class Emulator {
void performBinary(Binary binary);
}
class MyEmulator extends Emulator {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
typedef int Binary(int left, int right);
abstract class Emulator {
void performBinary(Binary binary);
}
class MyEmulator extends Emulator {
@override
void performBinary(Binary binary) {
// TODO: implement performBinary
}
}
''');
}
test_createMissingOverrides_functionTypedParameter() async {
await resolveTestUnit('''
abstract class A {
forEach(int f(double p1, String p2));
}
class B extends A {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
abstract class A {
forEach(int f(double p1, String p2));
}
class B extends A {
@override
forEach(int Function(double p1, String p2) f) {
// TODO: implement forEach
}
}
''');
}
test_createMissingOverrides_generics_typeArguments() async {
await resolveTestUnit('''
class Iterator<T> {
}
abstract class IterableMixin<T> {
Iterator<T> get iterator;
}
class Test extends IterableMixin<int> {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
class Iterator<T> {
}
abstract class IterableMixin<T> {
Iterator<T> get iterator;
}
class Test extends IterableMixin<int> {
// TODO: implement iterator
@override
Iterator<int> get iterator => null;
}
''');
}
test_createMissingOverrides_generics_typeParameters() async {
await resolveTestUnit('''
abstract class ItemProvider<T> {
List<T> getItems();
}
class Test<V> extends ItemProvider<V> {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
abstract class ItemProvider<T> {
List<T> getItems();
}
class Test<V> extends ItemProvider<V> {
@override
List<V> getItems() {
// TODO: implement getItems
}
}
''');
}
test_createMissingOverrides_getter() async {
await resolveTestUnit('''
abstract class A {
get g1;
int get g2;
}
class B extends A {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
abstract class A {
get g1;
int get g2;
}
class B extends A {
// TODO: implement g1
@override
get g1 => null;
// TODO: implement g2
@override
int get g2 => null;
}
''');
}
test_createMissingOverrides_importPrefix() async {
await resolveTestUnit('''
import 'dart:async' as aaa;
abstract class A {
Map<aaa.Future, List<aaa.Future>> g(aaa.Future p);
}
class B extends A {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
import 'dart:async' as aaa;
abstract class A {
Map<aaa.Future, List<aaa.Future>> g(aaa.Future p);
}
class B extends A {
@override
Map<aaa.Future, List<aaa.Future>> g(aaa.Future p) {
// TODO: implement g
}
}
''');
}
test_createMissingOverrides_mergeToField_getterSetter() async {
await resolveTestUnit('''
class A {
int ma;
void mb() {}
double mc;
}
class B implements A {
}
''');
await assertHasFix(DartFixKind.CREATE_MISSING_OVERRIDES, '''
class A {
int ma;
void mb() {}
double mc;
}
class B implements A {
@override
int ma;
@override
double mc;
@override
void mb() {
// TODO: implement mb
}
}
''');
}
test_createMissingOverrides_method() async {
await resolveTestUnit('''
abstract class A {
m1();
int m2();
String m3(int p1, double p2, Map<int, List<String>> p3);
String m4(p1, p2);
String m5(p1, [int p2 = 2, int p3, p4 = 4]);
String m6(p1, {int p2 = 2, int p3, p4: 4});
}
class B extends A {
}
''');
String expectedCode = '''
abstract class A {
m1();
int m2();
String m3(int p1, double p2, Map<int, List<String>> p3);
String m4(p1, p2);
String m5(p1, [int p2 = 2, int p3, p4 = 4]);
String m6(p1, {int p2 = 2, int p3, p4: 4});
}
class B extends A {
@override
m1() {
// TODO: implement m1
}
@override
int m2() {
// TODO: implement m2
}
@override
String m3(int p1, double p2, Map<int, List<String>> p3) {
// TODO: implement m3
}
@override
String m4(p1, p2) {
// TODO: implement m4
}
@override
String m5(p1, [int p2 = 2, int p3, p4 = 4]) {
// TODO: implement m5
}
@override
String m6(p1, {int p2 = 2, int p3, p4 = 4}) {
// TODO: implement m6
}