Skip to content

Commit 60553fc

Browse files
author
Dart CI
committed
Version 3.12.0-68.0.dev
Merge 78e254f into dev
2 parents 29918a5 + 78e254f commit 60553fc

6 files changed

Lines changed: 168 additions & 12 deletions

File tree

pkg/analysis_server/lib/src/services/refactoring/agnostic/change_method_signature.dart

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:analysis_server/src/services/search/hierarchy.dart';
1212
import 'package:analysis_server/src/services/search/search_engine.dart';
1313
import 'package:analysis_server_plugin/edit/correction_utils.dart';
1414
import 'package:analysis_server_plugin/src/utilities/selection.dart';
15+
import 'package:analyzer/dart/analysis/features.dart';
1516
import 'package:analyzer/dart/analysis/results.dart';
1617
import 'package:analyzer/dart/ast/ast.dart';
1718
import 'package:analyzer/dart/ast/token.dart';
@@ -63,11 +64,48 @@ sealed class Available extends Availability {
6364

6465
Available({required this.refactoringContext});
6566

66-
bool get hasPositionalParameters;
67+
/// Whether there are any positional parameters and, if so, if all of them
68+
/// can be converted to named parameters.
69+
///
70+
/// Even if a parameter is positional, it may not be convertible if it has a
71+
/// private name and isn't in a context where it could become a private named
72+
/// parameter. If that case, this returns `false`.
73+
bool get hasPositionalParametersToConvertToNamed {
74+
var supportsPrivateNamedParameters = refactoringContext
75+
.resolvedLibraryResult
76+
.element
77+
.featureSet
78+
.isEnabled(Feature.private_named_parameters);
79+
80+
var hasPositional = false;
81+
for (var parameter in _formalParameters) {
82+
if (parameter.isNamed) continue;
83+
84+
hasPositional = true;
85+
86+
// If the parameter has a private name, we must be able to convert it to
87+
// a private named parameter.
88+
if (Identifier.isPrivateName(parameter.name!)) {
89+
if (!supportsPrivateNamedParameters) {
90+
return false;
91+
}
92+
93+
// TODO(rnystrom): Check for primary constructor declaring parameter
94+
// here once those are implemented.
95+
if (parameter is! FieldFormalParameterElement) {
96+
return false;
97+
}
98+
}
99+
}
100+
101+
return hasPositional;
102+
}
67103

68104
bool get hasSelectedFormalParametersToConvertToNamed => false;
69105

70106
bool get hasSelectedFormalParametersToMoveLeft => false;
107+
108+
List<FormalParameterElement> get _formalParameters;
71109
}
72110

73111
/// The supertype return types from [computeSourceChange].
@@ -408,11 +446,6 @@ final class _AvailableWithDeclaration extends Available {
408446
required this.declaration,
409447
});
410448

411-
@override
412-
bool get hasPositionalParameters {
413-
return declaration.element.formalParameters.any((e) => e.isPositional);
414-
}
415-
416449
@override
417450
bool get hasSelectedFormalParametersToConvertToNamed {
418451
var selected = declaration.selected;
@@ -472,6 +505,10 @@ final class _AvailableWithDeclaration extends Available {
472505

473506
return true;
474507
}
508+
509+
@override
510+
List<FormalParameterElement> get _formalParameters =>
511+
declaration.element.formalParameters;
475512
}
476513

477514
final class _AvailableWithExecutableElement extends Available {
@@ -483,9 +520,8 @@ final class _AvailableWithExecutableElement extends Available {
483520
});
484521

485522
@override
486-
bool get hasPositionalParameters {
487-
return element.formalParameters.any((e) => e.isPositional);
488-
}
523+
List<FormalParameterElement> get _formalParameters =>
524+
element.formalParameters;
489525
}
490526

491527
/// The target method declaration.

pkg/analysis_server/lib/src/services/refactoring/convert_all_formal_parameters_to_named.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ConvertAllFormalParametersToNamed extends RefactoringProducer {
8787
if (availability is! Available) {
8888
return false;
8989
}
90-
return availability.hasPositionalParameters;
90+
91+
return availability.hasPositionalParametersToConvertToNamed;
9192
}
9293
}

pkg/analysis_server/lib/src/services/refactoring/framework/write_invocation_arguments.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
56
import 'package:analysis_server/src/services/refactoring/framework/formal_parameter.dart';
67
import 'package:analysis_server_plugin/edit/correction_utils.dart';
78
import 'package:analyzer/dart/analysis/results.dart';
@@ -49,8 +50,11 @@ Future<WriteArgumentsStatus> writeArguments({
4950
return WriteArgumentsStatusFailure();
5051
}
5152
if (update is FormalParameterUpdateExistingNamed) {
53+
// If the parameter's name is private, then the argument uses the
54+
// corresponding public name.
55+
var name = correspondingPublicName(update.name) ?? update.name;
5256
newArguments.add(
53-
_ArgumentAddName(name: update.name, argument: argument),
57+
_ArgumentAddName(name: name, argument: argument),
5458
);
5559
} else {
5660
newArguments.add(_ArgumentAsIs(argument: argument));

pkg/analysis_server/test/src/services/refactoring/convert_all_formal_parameters_to_named_test.dart

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,82 @@ void f() {
155155
await _assertNoRefactoring();
156156
}
157157

158+
Future<void> test_private_constructor() async {
159+
addTestSource(r'''
160+
class C {
161+
int? _a;
162+
int? _b;
163+
164+
^C(this._a, {this._b});
165+
}
166+
167+
void f() {
168+
C(0, b: 1);
169+
}
170+
''');
171+
172+
await verifyRefactoring(r'''
173+
>>>>>>>>>> lib/main.dart
174+
class C {
175+
int? _a;
176+
int? _b;
177+
178+
C({required this._a, this._b});
179+
}
180+
181+
void f() {
182+
C(a: 0, b: 1);
183+
}
184+
''');
185+
}
186+
187+
Future<void> test_private_constructor_unsupported() async {
188+
addTestSource(r'''
189+
// @dart=3.10
190+
class C {
191+
int? _a;
192+
int? _b;
193+
194+
^C(this._a, {int? b}) : _b = b;
195+
}
196+
197+
void f() {
198+
C(0, b: 1);
199+
}
200+
''');
201+
202+
await _assertNoRefactoring();
203+
}
204+
205+
Future<void> test_private_function() async {
206+
// Functions can't have private named parameters, so the refactoring can't
207+
// be applied.
208+
addTestSource(r'''
209+
^test(int _a, int _b) {}
210+
211+
void f() {
212+
test(0, 1);
213+
}
214+
''');
215+
216+
await _assertNoRefactoring();
217+
}
218+
219+
Future<void> test_private_function_unsupported() async {
220+
// Functions can't have private named parameters, so the refactoring can't
221+
// be applied.
222+
addTestSource(r'''
223+
// @dart=3.10
224+
^test(int _a, int _b) {}
225+
226+
void f() {
227+
test(0, 1);
228+
}
229+
''');
230+
231+
await _assertNoRefactoring();
232+
}
233+
158234
Future<void> test_target_methodInvocation_name() async {
159235
addTestSource(r'''
160236
void test(int a) {}

pkg/analyzer/test/src/diagnostics/missing_override_of_must_be_overridden_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ class B extends A {}
3737
);
3838
}
3939

40+
test_field_declaredInPrimaryConstructor() async {
41+
await assertErrorsInCode(
42+
'''
43+
import 'package:meta/meta.dart';
44+
45+
class A(@mustBeOverridden var int f);
46+
47+
class B(super.f) extends A {}
48+
''',
49+
[error(diag.missingOverrideOfMustBeOverriddenOne, 79, 1)],
50+
);
51+
}
52+
4053
test_field_method() async {
4154
await assertErrorsInCode(
4255
'''
@@ -78,6 +91,19 @@ class B extends A {
7891
''');
7992
}
8093

94+
test_field_overriddenWithField_inPrimaryConstructor() async {
95+
await assertNoErrorsInCode('''
96+
import 'package:meta/meta.dart';
97+
98+
class A {
99+
@mustBeOverridden
100+
int f = 0;
101+
}
102+
103+
class B(var int f) extends A;
104+
''');
105+
}
106+
81107
test_field_overriddenWithGetterSetterPair() async {
82108
await assertNoErrorsInCode('''
83109
import 'package:meta/meta.dart';
@@ -159,6 +185,19 @@ class B extends A {
159185
''');
160186
}
161187

188+
test_getter_overriddenWithField_inPrimaryConstructor() async {
189+
await assertNoErrorsInCode('''
190+
import 'package:meta/meta.dart';
191+
192+
class A {
193+
@mustBeOverridden
194+
int get f => 0;
195+
}
196+
197+
class B(var int f) extends A;
198+
''');
199+
}
200+
162201
test_getter_overriddenWithGetter() async {
163202
await assertNoErrorsInCode('''
164203
import 'package:meta/meta.dart';

tools/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ CHANNEL dev
2727
MAJOR 3
2828
MINOR 12
2929
PATCH 0
30-
PRERELEASE 67
30+
PRERELEASE 68
3131
PRERELEASE_PATCH 0

0 commit comments

Comments
 (0)