Skip to content

Commit f5d15f4

Browse files
authored
Merge pull request #74241 from ahoppen/enum-case-rename
Fix renaming enum case parameters with unnamed associated arguments
2 parents 1ef8d5c + 155773c commit f5d15f4

File tree

8 files changed

+186
-10
lines changed

8 files changed

+186
-10
lines changed

include/swift/IDE/IDEBridging.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ enum class LabelRangeType {
3838
/// `func foo([a b]: Int)`
3939
Param,
4040

41+
/// The parameter of an enum case declaration
42+
///
43+
/// ### Examples
44+
/// - `case myCase([a]: Int)`
45+
/// - `case myCase([]Int)`
46+
EnumCaseParam,
47+
4148
/// Parameters of a function that can't be collapsed if they are the same.
4249
///
4350
/// This is the case for parameters of subscripts since subscripts have

include/swift/IDE/Utils.h

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -465,15 +465,34 @@ enum class RegionType {
465465
};
466466

467467
enum class RefactoringRangeKind {
468-
BaseName, // func [foo](a b: Int)
469-
KeywordBaseName, // [init](a: Int)
470-
ParameterName, // func foo(a[ b]: Int)
471-
NoncollapsibleParameterName, // subscript(a[ a]: Int)
472-
DeclArgumentLabel, // func foo([a] b: Int)
473-
CallArgumentLabel, // foo([a]: 1)
474-
CallArgumentColon, // foo(a[: ]1)
475-
CallArgumentCombined, // foo([]1) could expand to foo([a: ]1)
476-
SelectorArgumentLabel, // foo([a]:)
468+
/// `func [foo](a b: Int)`
469+
BaseName,
470+
471+
/// `[init](a: Int)`
472+
KeywordBaseName,
473+
474+
/// `func foo(a[ b]: Int)`
475+
ParameterName,
476+
477+
/// `subscript(a[ a]: Int)`
478+
NoncollapsibleParameterName,
479+
480+
/// `func foo([a] b: Int)`
481+
DeclArgumentLabel,
482+
483+
/// `foo([a]: 1)`
484+
CallArgumentLabel,
485+
486+
/// `foo(a[: ]1)`
487+
CallArgumentColon,
488+
489+
/// `foo([]1) could expand to foo([a: ]1)`
490+
/// Also used for enum case declarations without a label, eg.
491+
/// `case foo([]String)` should expand to `case foo([a: ]String)`.
492+
CallArgumentCombined,
493+
494+
/// `foo([a]:)`
495+
SelectorArgumentLabel,
477496
};
478497

479498
struct NoteRegion {

lib/ASTGen/Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fileprivate extension IDEBridging.LabelRangeType {
5050
case .noArguments: self = .None
5151
case .call: self = .CallArg
5252
case .parameters: self = .Param
53+
case .enumCaseParameters: self = .EnumCaseParam
5354
case .noncollapsibleParameters: self = .NoncollapsibleParam
5455
case .selector: self = .CompoundName
5556
#if RESILIENT_SWIFT_SYNTAX
@@ -72,6 +73,7 @@ extension BridgedResolvedLoc {
7273
case .noArguments: arguments = []
7374
case .call(let arguments2, _): arguments = arguments2
7475
case .parameters(let arguments2): arguments = arguments2
76+
case .enumCaseParameters(let arguments2): arguments = arguments2
7577
case .noncollapsibleParameters(let arguments2): arguments = arguments2
7678
case .selector(let arguments2): arguments = arguments2
7779
#if RESILIENT_SWIFT_SYNTAX

lib/Refactoring/SyntacticRenameRangeDetails.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ void RenameRangeDetailCollector::splitAndRenameLabel(CharSourceRange Range,
146146
return splitAndRenameCallArg(Range, NameIndex);
147147
case LabelRangeType::Param:
148148
return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/true);
149+
case LabelRangeType::EnumCaseParam:
150+
if (Range.getByteLength() == 0) {
151+
// If the associated value currently doesn't have a label, emit a
152+
// `CallArgumentCombined` range, which will cause a new label followed by
153+
// `:` to be inserted in the same fashion that call arguments get inserted
154+
// to calls
155+
return addRenameRange(Range, RefactoringRangeKind::CallArgumentCombined, NameIndex);
156+
} else {
157+
// If the associated value has a label already, we are in the same case as
158+
// function parameters.
159+
return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/true);
160+
}
149161
case LabelRangeType::NoncollapsibleParam:
150162
return splitAndRenameParamLabel(Range, NameIndex,
151163
/*IsCollapsible=*/false);
@@ -248,6 +260,7 @@ bool RenameRangeDetailCollector::labelRangeMatches(CharSourceRange Range,
248260
LLVM_FALLTHROUGH;
249261
case LabelRangeType::CallArg:
250262
case LabelRangeType::Param:
263+
case LabelRangeType::EnumCaseParam:
251264
case LabelRangeType::CompoundName:
252265
return ExistingLabel == (Expected.empty() ? "_" : Expected);
253266
case LabelRangeType::None:
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s
4+
5+
// CHECK: source.edit.kind.active:
6+
// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename
7+
// CHECK-NEXT: 2:15-2:20 source.refactoring.range.kind.decl-argument-label arg-index=0
8+
// CHECK-NEXT: 2:20-2:20 source.refactoring.range.kind.parameter-and-whitespace arg-index=0
9+
// CHECK-NEXT: source.edit.kind.active:
10+
// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename
11+
// CHECK-NEXT: 6:21-6:26 source.refactoring.range.kind.call-argument-label arg-index=0
12+
// CHECK-NEXT: 6:26-6:28 source.refactoring.range.kind.call-argument-colon arg-index=0
13+
14+
//--- input.swift
15+
enum MyEnum {
16+
case myCase(label: String)
17+
}
18+
19+
func test() {
20+
_ = MyEnum.myCase(label: "abc")
21+
}
22+
23+
//--- rename-spec.json
24+
25+
[
26+
{
27+
"key.name": "myCase(label:)",
28+
"key.locations": [
29+
{
30+
"key.line": 2,
31+
"key.column": 8,
32+
"key.nametype": source.syntacticrename.definition
33+
}
34+
]
35+
},
36+
{
37+
"key.name": "myCase(label:)",
38+
"key.locations": [
39+
{
40+
"key.line": 6,
41+
"key.column": 14,
42+
"key.nametype": source.syntacticrename.call
43+
}
44+
]
45+
}
46+
]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s
4+
5+
// CHECK: source.edit.kind.active:
6+
// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename
7+
// CHECK-NEXT: 2:15-2:15 source.refactoring.range.kind.call-argument-combined arg-index=0
8+
// CHECK-NEXT: source.edit.kind.active:
9+
// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename
10+
// CHECK-NEXT: 6:21-6:21 source.refactoring.range.kind.call-argument-combined arg-index=0
11+
12+
//--- input.swift
13+
enum MyEnum {
14+
case myCase(String)
15+
}
16+
17+
func test() {
18+
_ = MyEnum.myCase("abc")
19+
}
20+
21+
//--- rename-spec.json
22+
23+
[
24+
{
25+
"key.name": "myCase(_:)",
26+
"key.locations": [
27+
{
28+
"key.line": 2,
29+
"key.column": 8,
30+
"key.nametype": source.syntacticrename.definition
31+
}
32+
]
33+
},
34+
{
35+
"key.name": "myCase(_:)",
36+
"key.locations": [
37+
{
38+
"key.line": 6,
39+
"key.column": 14,
40+
"key.nametype": source.syntacticrename.call
41+
}
42+
]
43+
}
44+
]
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %sourcekitd-test -req=find-rename-ranges -rename-spec %t/rename-spec.json %t/input.swift | %FileCheck %s
4+
5+
// CHECK: source.edit.kind.active:
6+
// CHECK-NEXT: 2:8-2:14 source.refactoring.range.kind.basename
7+
// CHECK-NEXT: 2:15-2:16 source.refactoring.range.kind.decl-argument-label arg-index=0
8+
// CHECK-NEXT: 2:16-2:22 source.refactoring.range.kind.parameter-and-whitespace arg-index=0
9+
// CHECK-NEXT: source.edit.kind.active:
10+
// CHECK-NEXT: 6:14-6:20 source.refactoring.range.kind.basename
11+
// CHECK-NEXT: 6:21-6:21 source.refactoring.range.kind.call-argument-combined arg-index=0
12+
13+
//--- input.swift
14+
enum MyEnum {
15+
case myCase(_ label: String)
16+
}
17+
18+
func test() {
19+
_ = MyEnum.myCase("abc")
20+
}
21+
22+
//--- rename-spec.json
23+
24+
[
25+
{
26+
"key.name": "myCase(:)",
27+
"key.locations": [
28+
{
29+
"key.line": 2,
30+
"key.column": 8,
31+
"key.nametype": source.syntacticrename.definition
32+
}
33+
]
34+
},
35+
{
36+
"key.name": "myCase(:)",
37+
"key.locations": [
38+
{
39+
"key.line": 6,
40+
"key.column": 14,
41+
"key.nametype": source.syntacticrename.call
42+
}
43+
]
44+
}
45+
]

test/refactoring/SyntacticRename/Outputs/types/case-other.swift.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extension /*class-Animal:def*/Animal {
2727
enum /*enum-Barcode:def*/Barcode {
2828
case upc(Int, Int, Int, Int)
2929
case /*case-qrCode:def*/qrCode(code: String)
30-
case /*case-other:def*/<base>other</base>(<arglabel index=0></arglabel><param index=0></param>Int)
30+
case /*case-other:def*/<base>other</base>(<callcombo index=0></callcombo>Int)
3131
case /*case-another:def*/another
3232
}
3333
var barCode: /*enum-Barcode*/Barcode = /*enum-Barcode*/Barcode.upc(1, 1, 1, 1)

0 commit comments

Comments
 (0)