diff --git a/test/rule_test_support.dart b/test/rule_test_support.dart index 3e2555675..41aa70cb8 100644 --- a/test/rule_test_support.dart +++ b/test/rule_test_support.dart @@ -18,6 +18,7 @@ import 'package:linter/src/rules.dart'; import 'package:meta/meta.dart'; import 'package:test/test.dart'; +export 'package:analyzer/src/dart/error/syntactic_errors.dart'; export 'package:analyzer/src/error/codes.dart'; export 'package:analyzer/src/test_utilities/package_config_file_builder.dart'; @@ -214,32 +215,6 @@ abstract class LintRuleTest extends PubPackageResolutionTest { fail(buffer.toString()); } } - - /// todo(pq): consider migrating all calls to assertDiagnostics - Future assertLint(String code) async { - addTestFile(code); - await resolveTestFile(); - - for (var error in errors) { - if (error.errorCode.name == lintRule) { - return; - } - } - - fail('Expected: $lintRule, found none'); - } - - /// todo(pq): consider migrating all calls to assertDiagnostics - Future assertNoLint(String code) async { - addTestFile(code); - await resolveTestFile(); - - for (var error in errors) { - if (error.errorCode.name == lintRule) { - fail(error.message); - } - } - } } class PubPackageResolutionTest extends _ContextResolutionTest { diff --git a/test/rules/all.dart b/test/rules/all.dart index a92b5c312..8e4c6001d 100644 --- a/test/rules/all.dart +++ b/test/rules/all.dart @@ -5,6 +5,8 @@ import 'avoid_function_literals_in_foreach_calls.dart' as avoid_function_literals_in_foreach_calls; import 'avoid_init_to_null.dart' as avoid_init_to_null; +import 'missing_whitespace_between_adjacent_strings.dart' + as missing_whitespace_between_adjacent_strings; import 'overridden_fields.dart' as overridden_fields; import 'prefer_asserts_in_initializer_lists.dart' as prefer_asserts_in_initializer_lists; @@ -12,15 +14,18 @@ import 'prefer_const_constructors_in_immutables.dart' as prefer_const_constructors_in_immutables; import 'prefer_contains.dart' as prefer_contains; import 'prefer_spread_collections.dart' as prefer_spread_collections; +import 'type_init_formals.dart' as type_init_formals; import 'void_checks.dart' as void_checks; void main() { avoid_function_literals_in_foreach_calls.main(); avoid_init_to_null.main(); + missing_whitespace_between_adjacent_strings.main(); overridden_fields.main(); prefer_asserts_in_initializer_lists.main(); prefer_const_constructors_in_immutables.main(); prefer_contains.main(); prefer_spread_collections.main(); + type_init_formals.main(); void_checks.main(); } diff --git a/test/rules/avoid_function_literals_in_foreach_calls.dart b/test/rules/avoid_function_literals_in_foreach_calls.dart index 59859c8a9..04060c844 100644 --- a/test/rules/avoid_function_literals_in_foreach_calls.dart +++ b/test/rules/avoid_function_literals_in_foreach_calls.dart @@ -18,9 +18,11 @@ class AvoidFunctionLiteralsInForeachCalls extends LintRuleTest { String get lintRule => 'avoid_function_literals_in_foreach_calls'; test_expectedIdentifier() async { - // Produces an expected identifier diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' void f(dynamic iter) => iter?.forEach(...); -'''); +''', [ + // No lint + error(ParserErrorCode.MISSING_IDENTIFIER, 38, 3), + ]); } } diff --git a/test/rules/avoid_init_to_null.dart b/test/rules/avoid_init_to_null.dart index c5543015f..35b00c342 100644 --- a/test/rules/avoid_init_to_null.dart +++ b/test/rules/avoid_init_to_null.dart @@ -18,43 +18,53 @@ class AvoidInitToNullTest extends LintRuleTest { String get lintRule => 'avoid_init_to_null'; test_invalidAssignment_field() async { - // Produces an invalid_assignment compilation error. - await assertNoLint(r''' + await assertDiagnostics(r''' class X { int x = null; } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 20, 4), + ]); } test_invalidAssignment_namedParameter() async { - // Produces an invalid_assignment compilation error. - await assertNoLint(r''' + await assertDiagnostics(r''' class X { X({int a: null}); } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 22, 4), + ]); } test_invalidAssignment_namedParameter_fieldFormal() async { - // Produces an invalid_assignment compilation error. - await assertNoLint(r''' + await assertDiagnostics(r''' class X { int x; X({this.x: null}); } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 32, 4), + ]); } test_invalidAssignment_topLevelVariable() async { - // Produces an invalid_assignment compilation error. - await assertNoLint(r''' + await assertDiagnostics(r''' int i = null; -'''); +''', [ + // No lint + error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 8, 4), + ]); } test_nullable_topLevelVariable() async { - await assertLint(r''' + await assertDiagnostics(r''' int? ii = null; -'''); +''', [ + lint('avoid_init_to_null', 5, 9), + ]); } } diff --git a/test/rules/missing_whitespace_between_adjacent_strings.dart b/test/rules/missing_whitespace_between_adjacent_strings.dart new file mode 100644 index 000000000..892f679fb --- /dev/null +++ b/test/rules/missing_whitespace_between_adjacent_strings.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2021, 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:test_reflective_loader/test_reflective_loader.dart'; + +import '../rule_test_support.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(MissingWhitespaceBetweenAdjacentStringsTest); + }); +} + +@reflectiveTest +class MissingWhitespaceBetweenAdjacentStringsTest extends LintRuleTest { + @override + String get lintRule => 'missing_whitespace_between_adjacent_strings'; + + test_extraPositionalArgument() async { + await assertDiagnostics(r''' +void f() { + new Unresolved('aaa' 'bbb'); +} +''', [ + // No lint + error(CompileTimeErrorCode.NEW_WITH_NON_TYPE, 17, 10), + ]); + } +} diff --git a/test/rules/overridden_fields.dart b/test/rules/overridden_fields.dart index bad493f9a..e7e17d16f 100644 --- a/test/rules/overridden_fields.dart +++ b/test/rules/overridden_fields.dart @@ -19,7 +19,7 @@ class OverriddenFieldsTest extends LintRuleTest { /// https://github.com/dart-lang/linter/issues/2874 test_conflictingStaticAndInstance() async { - await assertNoLint(r''' + await assertDiagnostics(r''' class A { static final String field = 'value'; } @@ -27,17 +27,23 @@ class A { class B extends A { String field = 'otherValue'; } -'''); +''', [ + // No lint + ]); } test_recursiveInterfaceInheritance() async { // Produces a recursive_interface_inheritance diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' class A extends B {} class B extends A { int field = 0; } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 6, 1), + error(CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, 27, 1), + ]); } test_mixinInheritsFromNotObject() async { diff --git a/test/rules/prefer_asserts_in_initializer_lists.dart b/test/rules/prefer_asserts_in_initializer_lists.dart index 9097bb11a..0739230cc 100644 --- a/test/rules/prefer_asserts_in_initializer_lists.dart +++ b/test/rules/prefer_asserts_in_initializer_lists.dart @@ -18,8 +18,7 @@ class PreferAssertsInInitializerListsTest extends LintRuleTest { String get lintRule => 'prefer_asserts_in_initializer_lists'; test_nonBoolExpression() async { - // Produces an non_bool_expression diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' class A { bool? f; A() { @@ -30,6 +29,9 @@ class A { }); } } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.NON_BOOL_EXPRESSION, 40, 50), + ]); } } diff --git a/test/rules/prefer_const_constructors_in_immutables.dart b/test/rules/prefer_const_constructors_in_immutables.dart index 16a427289..5a2a7257e 100644 --- a/test/rules/prefer_const_constructors_in_immutables.dart +++ b/test/rules/prefer_const_constructors_in_immutables.dart @@ -18,11 +18,14 @@ class PreferConstConstructorsInImmutablesTest extends LintRuleTest { String get lintRule => 'prefer_const_constructors_in_immutables'; test_returnOfInvalidType() async { - // Produces an return_of_invalid_type diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' class F { factory F.fc() => null; } -'''); +''', [ + // No lint + error( + CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CONSTRUCTOR, 30, 4), + ]); } } diff --git a/test/rules/prefer_contains.dart b/test/rules/prefer_contains.dart index d04f1b731..8c7ea166e 100644 --- a/test/rules/prefer_contains.dart +++ b/test/rules/prefer_contains.dart @@ -18,20 +18,24 @@ class PreferContainsTest extends LintRuleTest { String get lintRule => 'prefer_contains'; test_argumentTypeNotAssignable() async { - // Produces an argument_type_not_assignable diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' List list = []; condition() { var next; while ((next = list.indexOf('{')) != -1) {} } -'''); +''', [ + // No lint + error(HintCode.UNUSED_LOCAL_VARIABLE, 41, 4), + ]); } test_unnecessaryCast() async { - // Produces an unnecessary_cast diagnostic. - await assertLint(r''' + await assertDiagnostics(r''' bool le3 = ([].indexOf(1) as int) > -1; -'''); +''', [ + lint('prefer_contains', 11, 27), + error(HintCode.UNNECESSARY_CAST, 12, 20), + ]); } } diff --git a/test/rules/prefer_spread_collections.dart b/test/rules/prefer_spread_collections.dart index e93715110..939a34edf 100644 --- a/test/rules/prefer_spread_collections.dart +++ b/test/rules/prefer_spread_collections.dart @@ -18,10 +18,13 @@ class PreferSpreadCollectionsTest extends LintRuleTest { String get lintRule => 'prefer_spread_collections'; test_constInitializedWithNonConstantValue() async { - // Produces a const_initialized_with_non_constant_value diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' const thangs = []; const cc = []..addAll(thangs); -'''); +''', [ + // No lint + error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 30, + 18), + ]); } } diff --git a/test/rules/type_init_formals.dart b/test/rules/type_init_formals.dart new file mode 100644 index 000000000..36ba8403c --- /dev/null +++ b/test/rules/type_init_formals.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2021, 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:test_reflective_loader/test_reflective_loader.dart'; + +import '../rule_test_support.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(TypeInitFormalsTest); + }); +} + +@reflectiveTest +class TypeInitFormalsTest extends LintRuleTest { + @override + String get lintRule => 'type_init_formals'; + + test_extraPositionalArgument() async { + await assertDiagnostics(r''' +class A { + String? p1; + String p2 = ''; + A.y({required String? this.p2}); +} +''', [ + // No lint + error(CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, 49, + 24), + ]); + } +} diff --git a/test/rules/void_checks.dart b/test/rules/void_checks.dart index 7a95d3dc5..ac10786a0 100644 --- a/test/rules/void_checks.dart +++ b/test/rules/void_checks.dart @@ -18,21 +18,25 @@ class VoidChecksTest extends LintRuleTest { String get lintRule => 'void_checks'; test_extraPositionalArgument() async { - // Produces an extra_positional_arguments diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' missing_parameter_for_argument() { void foo() {} foo(0); } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 57, 1), + ]); } test_returnOfInvalidType() async { - // Produces a return_of_invalid_type diagnostic. - await assertNoLint(r''' + await assertDiagnostics(r''' void bug2813() { return 1; } -'''); +''', [ + // No lint + error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 26, 1), + ]); } } diff --git a/test_data/rules/experiments/nnbd/rules/type_init_formals.dart b/test_data/rules/experiments/nnbd/rules/type_init_formals.dart index cfe5f434d..185c3cacb 100644 --- a/test_data/rules/experiments/nnbd/rules/type_init_formals.dart +++ b/test_data/rules/experiments/nnbd/rules/type_init_formals.dart @@ -6,10 +6,9 @@ class A { String? p1; - String p2; + String p2 = ''; A.w({required String this.p1}); // OK A.x({required String? this.p1}); // LINT - A.y({required String? this.p2}); // OK A.z({required String this.p2}); // LINT } diff --git a/test_data/rules/experiments/nnbd/rules/unrelated_type_equality_checks.dart b/test_data/rules/experiments/nnbd/rules/unrelated_type_equality_checks.dart index 7a88737d9..d4c98af8f 100644 --- a/test_data/rules/experiments/nnbd/rules/unrelated_type_equality_checks.dart +++ b/test_data/rules/experiments/nnbd/rules/unrelated_type_equality_checks.dart @@ -4,7 +4,7 @@ // test w/ `dart test -N unrelated_type_equality_checks` -bool m(int? a1, num a2) { +void m(int? a1, num a2) { var b1 = a1 == a2; // OK var b2 = a2 == a1; // OK } diff --git a/test_data/rules/missing_whitespace_between_adjacent_strings.dart b/test_data/rules/missing_whitespace_between_adjacent_strings.dart index 726d369b0..590527214 100644 --- a/test_data/rules/missing_whitespace_between_adjacent_strings.dart +++ b/test_data/rules/missing_whitespace_between_adjacent_strings.dart @@ -18,7 +18,6 @@ f(o) { f('long line\t' 'is long'); // OK f(RegExp('(\n)+' '(\n)+' '(\n)+')); // OK - new Unresolved('aaa' 'bbb'); // OK matches('(\n)+' '(\n)+' '(\n)+'); // OK f('Hello' // OK diff --git a/test_data/rules/prefer_collection_literals.dart b/test_data/rules/prefer_collection_literals.dart index 6ec462ce6..5127a76e3 100644 --- a/test_data/rules/prefer_collection_literals.dart +++ b/test_data/rules/prefer_collection_literals.dart @@ -62,8 +62,8 @@ void main() { printUnresolved(LinkedHashSet()); // OK - Set ss7 = LinkedHashSet.from([1, 2, 3]); // LINT - LinkedHashSet ss8 = LinkedHashSet.from([1, 2, 3]); // OK + Set ss8 = LinkedHashSet.from([1, 2, 3]); // LINT + LinkedHashSet ss9 = LinkedHashSet.from([1, 2, 3]); // OK Iterable iter = Iterable.empty(); // OK var sss = Set.from(iter); // OK diff --git a/test_data/rules/prefer_initializing_formals.dart b/test_data/rules/prefer_initializing_formals.dart index 395adafd8..3c912e258 100644 --- a/test_data/rules/prefer_initializing_formals.dart +++ b/test_data/rules/prefer_initializing_formals.dart @@ -53,7 +53,7 @@ num sin(num theta) { } class SimpleBadCase { - num x, y; + num x = 0, y = 0; SimpleBadCase(num x, num y) { this.x = x; // LINT this.y = y; // LINT @@ -66,7 +66,7 @@ class SimpleGoodCase { } class SimpleBadCaseWithOnlyOneLint { - num x, y; + num x, y = 0; SimpleBadCaseWithOnlyOneLint(this.x, num y) { this.y = y; // LINT } @@ -74,7 +74,7 @@ class SimpleBadCaseWithOnlyOneLint { /// https://github.com/dart-lang/linter/issues/2605 class RenamedFieldsForReadability { - num x, y; + num x = 0, y = 0; RenamedFieldsForReadability(num a, num b) { x = a; // OK y = b; // OK @@ -83,8 +83,8 @@ class RenamedFieldsForReadability { /// https://github.com/dart-lang/linter/issues/2605 class RenamedFieldsForReadability2 { - num x; - num y; + num x = 0; + num y = 0; RenamedFieldsForReadability2(num a, num b) { x = a; // OK y = b; // OK @@ -92,7 +92,7 @@ class RenamedFieldsForReadability2 { } class NoFieldsJustSetters { - String name; + String name = ''; NoFieldsJustSetters(num x, num y) { this.x = x; // OK this.y = y; // OK @@ -107,12 +107,12 @@ class NoFieldsJustSetters { } class NoFieldsJustSettersWithoutThisAndWithOneGetter { - String name; + String name = ''; NoFieldsJustSettersWithoutThisAndWithOneGetter(num a, num b) { x = a; // OK y = b; // OK } - get x { + num get x { return 0; } @@ -126,7 +126,7 @@ class NoFieldsJustSettersWithoutThisAndWithOneGetter { } class SuperCallWithConstructorParameters extends SimpleGoodCase { - num r, theta; + num r = 0, theta = 0; SuperCallWithConstructorParameters(num r, num theta) : super(r * cos(theta), r * sin(theta)) { this.r = r; // LINT @@ -154,7 +154,7 @@ class BadCaseWithNamedConstructorAndSuperCall extends SimpleGoodCase { class GoodCaseWithPrivateFields { // ignore: unused_field - num _x, _y; + num? _x, _y; GoodCaseWithPrivateFields(num x, num y) { this._x = x; // OK // This should be lint for other rule this._y = y; // OK // This should be lint for other rule @@ -163,7 +163,7 @@ class GoodCaseWithPrivateFields { class GoodCaseWithPrivateFieldsWithoutThis { // ignore: unused_field - num _x, _y; + num _x = 0, _y = 0; GoodCaseWithPrivateFieldsWithoutThis(num x, num y) { _x = x; // OK // This should be lint for other rule _y = y; // OK // This should be lint for other rule @@ -187,7 +187,7 @@ class GoodCaseWithPrivateFieldsInInitializersWithoutThis { } class BadCaseWithTwoFieldsOneArgument { - num x, y; + num x = 0, y = 0; BadCaseWithTwoFieldsOneArgument(num x) { this.x = x; // LINT this.y = x; // OK @@ -195,14 +195,14 @@ class BadCaseWithTwoFieldsOneArgument { } class GoodCaseWithTwoFieldsOneArgument { - num x, y; + num x = 0, y = 0; GoodCaseWithTwoFieldsOneArgument(this.x) { y = this.x; // OK } } class GoodCaseWithTwoFieldsOneArgumentWithoutThis { - num x, y; + num x = 0, y = 0; GoodCaseWithTwoFieldsOneArgumentWithoutThis(this.x) { y = x; // OK } @@ -231,31 +231,31 @@ class GoodCaseWithOneParameterToTwoFieldsBecauseTheyHaveDifferentNames { } class BadCaseWithNamedArgs { - num x, y; - BadCaseWithNamedArgs({num x, num y = 1}) { + num? x, y; + BadCaseWithNamedArgs({num? x, num y = 1}) { this.x = x; // LINT this.y = y; // LINT } } class GoodCaseWithDifferentNamedArgs { - num x, y; - GoodCaseWithDifferentNamedArgs({num a, num b = 1}) { + num? x, y; + GoodCaseWithDifferentNamedArgs({num? a, num b = 1}) { this.x = a; // OK this.y = b; // OK } } class BadCaseWithNamedArgsInitializer { - num x, y; - BadCaseWithNamedArgsInitializer({num x, num y = 1}) + num? x, y; + BadCaseWithNamedArgsInitializer({num? x, num y = 1}) : this.x = x, // LINT this.y = y; // LINT } class GoodCaseWithDifferentNamedArgsInitializer { - num x, y; - GoodCaseWithDifferentNamedArgsInitializer({num a, num b = 1}) + num? x, y; + GoodCaseWithDifferentNamedArgsInitializer({num? a, num b = 1}) : this.x = a, // OK this.y = b; // OK }