[PE] [linter] don’t report `require_trailing_commas` if language >=3.7
Fixes: https://github.com/dart-lang/sdk/issues/60119
Change-Id: If4821300dcae05cd1283558a87481d2bad7dae9c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/411182
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
index 67f8225..d28930c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
@@ -26,6 +26,9 @@
Future<void> test_bulk() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
Object f(a, b) {
f(f('a',
'b'), 'b');
@@ -33,6 +36,9 @@
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
Object f(a, b) {
f(f('a',
'b',), 'b',);
@@ -47,6 +53,9 @@
Future<void> test_File() async {
createAnalysisOptionsFile(lints: [LintNames.require_trailing_commas]);
await resolveTestCode(r'''
+// @dart = 3.6
+// (pre tall-style)
+
Object f(a, b) {
f(f('a',
'b'), 'b');
@@ -56,6 +65,9 @@
var fixes = await getFixesForFirstError();
expect(fixes, hasLength(1));
assertProduces(fixes.first, r'''
+// @dart = 3.6
+// (pre tall-style)
+
Object f(a, b) {
f(f('a',
'b',), 'b',);
@@ -73,9 +85,15 @@
Future<void> test_parse_literal_initialization() async {
// ParserErrorCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
var r = const (1);
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
var r = const (1,);
''');
}
@@ -83,9 +101,15 @@
Future<void> test_parse_type_initialization() async {
// ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
(int) record = const (1,);
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
(int,) record = const (1,);
''');
}
@@ -93,11 +117,17 @@
Future<void> test_warning_literal_assignment() async {
// WarningCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f((int,) r) {
r = (1);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f((int,) r) {
r = (1,);
}
@@ -107,9 +137,15 @@
Future<void> test_warning_literal_initialization() async {
// WarningCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
(int,) r = (1);
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
(int,) r = (1,);
''');
}
@@ -117,9 +153,15 @@
Future<void> test_warning_literal_return() async {
// WarningCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
(int,) f() { return (1); }
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
(int,) f() { return (1,); }
''');
}
@@ -135,12 +177,18 @@
Future<void> test_assert_initializer() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(a) : assert(a,
'');
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(a) : assert(a,
'',);
@@ -150,12 +198,18 @@
Future<void> test_assert_statement() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a, b) {
assert(a ||
b);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a, b) {
assert(a ||
b,);
@@ -165,6 +219,9 @@
Future<void> test_list_literal() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = [
'a',
@@ -174,6 +231,9 @@
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = [
'a',
@@ -186,18 +246,26 @@
Future<void> test_list_literal_withNullAwareElement() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? s) {
var l = [
'a',
+ // ignore: EXPERIMENT_NOT_ENABLED
?s
];
print(l);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? s) {
var l = [
'a',
+ // ignore: EXPERIMENT_NOT_ENABLED
?s,
];
print(l);
@@ -207,6 +275,9 @@
Future<void> test_map_literal() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = {
'a': 1,
@@ -216,6 +287,9 @@
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = {
'a': 1,
@@ -228,18 +302,26 @@
Future<void> test_map_literal_withNullAwareKey() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? k) {
var l = {
'a': 1,
+ // ignore: EXPERIMENT_NOT_ENABLED
?k: 2
};
print(l);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? k) {
var l = {
'a': 1,
+ // ignore: EXPERIMENT_NOT_ENABLED
?k: 2,
};
print(l);
@@ -249,18 +331,26 @@
Future<void> test_map_literal_withNullAwareValue() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(int? v) {
var l = {
'a': 1,
+ // ignore: EXPERIMENT_NOT_ENABLED
'b': ?v
};
print(l);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(int? v) {
var l = {
'a': 1,
+ // ignore: EXPERIMENT_NOT_ENABLED
'b': ?v,
};
print(l);
@@ -270,12 +360,18 @@
Future<void> test_named() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f({a, b}) {
f(a: 'a',
b: 'b');
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f({a, b}) {
f(a: 'a',
b: 'b',);
@@ -285,10 +381,16 @@
Future<void> test_parameters() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a,
b) {}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a,
b,) {}
''');
@@ -296,12 +398,18 @@
Future<void> test_positional() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a, b) {
f('a',
'b');
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(a, b) {
f('a',
'b',);
@@ -311,6 +419,9 @@
Future<void> test_set_literal() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = {
'a',
@@ -320,6 +431,9 @@
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var l = {
'a',
@@ -332,18 +446,26 @@
Future<void> test_set_literal_withNullAwareElement() async {
await resolveTestCode('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? s) {
var l = {
'a',
+ // ignore: EXPERIMENT_NOT_ENABLED
?s
};
print(l);
}
''');
await assertHasFix('''
+// @dart = 3.6
+// (pre tall-style)
+
void f(String? s) {
var l = {
'a',
+ // ignore: EXPERIMENT_NOT_ENABLED
?s,
};
print(l);
diff --git a/pkg/linter/lib/src/rules/require_trailing_commas.dart b/pkg/linter/lib/src/rules/require_trailing_commas.dart
index 729185c..279e12b 100644
--- a/pkg/linter/lib/src/rules/require_trailing_commas.dart
+++ b/pkg/linter/lib/src/rules/require_trailing_commas.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:pub_semver/pub_semver.dart';
import '../analyzer.dart';
@@ -12,6 +13,9 @@
r'Use trailing commas for all parameter lists and argument lists.';
class RequireTrailingCommas extends LintRule {
+ /// The version when tall-style was introduced in the formatter.
+ static final Version language37 = Version(3, 7, 0);
+
RequireTrailingCommas()
: super(name: LintNames.require_trailing_commas, description: _desc);
@@ -23,6 +27,10 @@
NodeLintRegistry registry,
LinterContext context,
) {
+ // Don't report if tall-style is enforced by the formatter.
+ var languageVersion = context.libraryElement2?.languageVersion.effective;
+ if (languageVersion != null && languageVersion >= language37) return;
+
var visitor = _Visitor(this);
registry
..addArgumentList(this, visitor)
diff --git a/pkg/linter/test/rules/require_trailing_commas_test.dart b/pkg/linter/test/rules/require_trailing_commas_test.dart
index 5a42bc9..5ddf592 100644
--- a/pkg/linter/test/rules/require_trailing_commas_test.dart
+++ b/pkg/linter/test/rules/require_trailing_commas_test.dart
@@ -20,18 +20,24 @@
test_argumentList_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text',
'Text');
}
void g(Object p1, Object p2) {}
''',
- [lint(35, 1)],
+ [lint(71, 1)],
);
}
test_argumentList_multiLine_containsFunctionalBlockBody_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -47,31 +53,40 @@
test_argumentList_multiLine_containsFunctionBlockBody() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(() {
}, 'Text');
}
void g(Object p1, Object p2) {}
''',
- [lint(31, 1)],
+ [lint(67, 1)],
);
}
test_argumentList_multiLine_containsFunctionBlockBody_endsWithNamed() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', () {
}, p3: 'Text');
}
void g(Object p1, Object p2, {Object? p3}) {}
''',
- [lint(43, 1)],
+ [lint(79, 1)],
);
}
test_argumentList_multiLine_containsFunctionBlockBody_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
() {
@@ -86,6 +101,9 @@
test_argumentList_multiLine_containsListLiteral() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g([
'one',
@@ -94,13 +112,16 @@
}
void g(Object p1, Object p2) {}
''',
- [lint(50, 1)],
+ [lint(86, 1)],
);
}
test_argumentList_multiLine_containsMapLiteral() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g({
'one': 'Text',
@@ -109,7 +130,7 @@
}
void g(Object p1, Object p2) {}
''',
- [lint(66, 1)],
+ [lint(102, 1)],
);
}
@@ -128,6 +149,9 @@
test_argumentList_multiLine_containsSetLiteral() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g({
'one',
@@ -136,12 +160,15 @@
}
void g(Object p1, Object p2) {}
''',
- [lint(50, 1)],
+ [lint(86, 1)],
);
}
test_argumentList_multiLine_endsWithConstantListLiteral() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -155,18 +182,24 @@
test_argumentList_multiLine_endsWithFunctionBlockBody() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text',
() {}); // LINT
}
void g(Object p1, Object p2) {}
''',
- [lint(34, 1)],
+ [lint(70, 1)],
);
}
test_argumentList_multiLine_endsWithFunctionBlockBody_multiLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('test', () {
});
@@ -178,18 +211,24 @@
test_argumentList_multiLine_endsWithFunctionBlockBody_multiLine_named() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', 'Text', p3: () {
});
}
void g(Object p1, Object p2, {Object? p3}) {}
''',
- [lint(43, 1)],
+ [lint(79, 1)],
);
}
test_argumentList_multiLine_endsWithFunctionBlockBody_multiLine_named_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -204,6 +243,9 @@
test_argumentList_multiLine_endsWithFunctionBlockBody_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -216,6 +258,9 @@
test_argumentList_multiLine_endsWithListLiteral() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', [
'one',
@@ -229,18 +274,24 @@
test_argumentList_multiLine_endsWithListLiteral_onSingleLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text',
const ['one', 'two']);
}
void g(Object p1, Object p2) {}
''',
- [lint(49, 1)],
+ [lint(85, 1)],
);
}
test_argumentList_multiLine_endsWithListLiteral_withTrailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', const [
'one',
@@ -254,18 +305,24 @@
test_argumentList_multiLine_endsWithMapLiteral() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text',
const {'one': '1', 'two': '2', 'three': '3'}); // LINT
}
void g(Object p1, Object p2) {}
''',
- [lint(73, 1)],
+ [lint(109, 1)],
);
}
test_argumentList_multiLine_endsWithMapLiteral_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -302,6 +359,9 @@
test_argumentList_multiLine_endsWithSetLiteral_withTrailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', const {
'one',
@@ -314,6 +374,9 @@
test_argumentList_multiLine_multiLineString() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
print("""
Text
@@ -322,8 +385,22 @@
''');
}
+ /// A representative test to ensure the lint is disabled when the language is 3.7 or higher.
+ test_argumentList_multiLine_post37() async {
+ await assertNoDiagnostics(r'''
+void f() {
+ g('Text',
+ 'Text');
+}
+void g(Object p1, Object p2) {}
+''');
+ }
+
test_argumentList_multiLine_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g(
'Text',
@@ -336,6 +413,9 @@
test_argumentList_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
g('Text', 'Text');
}
@@ -345,6 +425,9 @@
test_assertStateent_multiLine_message_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(
false,
@@ -356,6 +439,9 @@
test_assertStatement_closure() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(() {
return true;
@@ -367,18 +453,24 @@
test_assertStatement_closure_message() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(() {
return true;
}(), 'Text');
}
''',
- [lint(55, 1)],
+ [lint(91, 1)],
);
}
test_assertStatement_closure_message_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(
() {
@@ -392,6 +484,9 @@
test_assertStatement_message() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(false, 'Text');
}
@@ -401,29 +496,38 @@
test_assertStatement_multiLine_message() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(false,
'Text');
}
''',
- [lint(39, 1)],
+ [lint(75, 1)],
);
}
test_assertStatement_oneArgument_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert('Text'
.isNotEmpty);
}
''',
- [lint(44, 1)],
+ [lint(80, 1)],
);
}
test_assertStatement_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
assert(
'Text'.isNotEmpty,
@@ -435,18 +539,24 @@
test_constructorAssertInitializer_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C()
: assert(true,
'Text');
}
''',
- [lint(55, 1)],
+ [lint(91, 1)],
);
}
test_constructorAssertInitializer_multiLine_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C()
: assert(
@@ -460,15 +570,21 @@
test_function_parameters_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void method4(int one,
int two) {}
''',
- [lint(33, 1)],
+ [lint(69, 1)],
);
}
test_function_parameters_multiLine_withComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f(
int one,
int two,
@@ -478,6 +594,9 @@
test_function_parameters_withNamed_mulitLine_withComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f(
int one, {
int? two,
@@ -488,34 +607,46 @@
test_function_parameters_withNamed_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f(int one,
{int two = 2}) {}
''',
- [lint(32, 1)],
+ [lint(68, 1)],
);
}
test_function_parameters_withNamed_singleLine() async {
await assertNoDiagnostics(r'''
- void method1(Object p1, Object p2, {Object? param3, Object? param4}) {}
+// @dart = 3.6
+// (pre tall-style)
+
+void method1(Object p1, Object p2, {Object? param3, Object? param4}) {}
''');
}
test_functionLiteral_parameters_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
(int one,
int two)
{};
}
''',
- [lint(36, 1)],
+ [lint(72, 1)],
);
}
test_functionLiteral_parameters_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
(a, b) {};
}
@@ -525,6 +656,9 @@
test_listLiteral_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = [
1,
@@ -532,12 +666,15 @@
];
}
''',
- [lint(48, 1)],
+ [lint(84, 1)],
);
}
test_listLiteral_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = [1, if (true) 2];
}
@@ -547,6 +684,9 @@
test_mapLiteral_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = {
1: 1,
@@ -554,12 +694,15 @@
};
}
''',
- [lint(54, 1)],
+ [lint(90, 1)],
);
}
test_mapLiteral_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = {1: 1, if (true) 2: 2};
}
@@ -568,6 +711,9 @@
test_parameterList_multiLine_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(
Object p1,
@@ -581,6 +727,9 @@
test_parameterList_multiLineDefaultValue_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(Object p1, Object p2,
[Object p3 = const [
@@ -588,12 +737,15 @@
]]);
}
''',
- [lint(86, 1)],
+ [lint(122, 1)],
);
}
test_parameterList_multiLineDefaultValue_multiLine_trailingComma() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(
Object p1,
@@ -608,6 +760,9 @@
test_parameterList_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(Object p1, Object p2);
}
@@ -617,18 +772,24 @@
test_parameterList_singleLine_blankLineBefore() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
class C {
C(
Object p1, Object p2, Object p3);
}
''',
- [lint(52, 1)],
+ [lint(88, 1)],
);
}
test_setLiteral_multiLine() async {
await assertDiagnostics(
r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = {
1,
@@ -636,12 +797,15 @@
};
}
''',
- [lint(48, 1)],
+ [lint(84, 1)],
);
}
test_setLiteral_singleLine() async {
await assertNoDiagnostics(r'''
+// @dart = 3.6
+// (pre tall-style)
+
void f() {
var x = {1, if (true) 2};
}