Skip to content

Commit af1f6e1

Browse files
committed
SwiftFixIt: Skip duplicate insertion fix-its
This will prevent repeated fix-it application in various scenarios where multiple elements in a protocol composition type are diagnosed with the same insertion fix-it.
1 parent 0c7ebf2 commit af1f6e1

File tree

6 files changed

+75
-13
lines changed

6 files changed

+75
-13
lines changed

Fixtures/SwiftMigrate/ExistentialAnyMigration/Sources/Fixed/Test.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
protocol P {
22
}
3+
protocol Q {
4+
}
35

46
func test1(_: any P) {
57
}
@@ -14,3 +16,6 @@ func test3() {
1416
func test4() {
1517
var x = 42
1618
}
19+
20+
func test5(_: any P & Q) {
21+
}

Fixtures/SwiftMigrate/ExistentialAnyMigration/Sources/Test.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
protocol P {
22
}
3+
protocol Q {
4+
}
35

46
func test1(_: P) {
57
}
@@ -14,3 +16,6 @@ func test3() {
1416
func test4() {
1517
var x = 42
1618
}
19+
20+
func test5(_: P & Q) {
21+
}

Sources/SwiftFixIt/SwiftFixIt.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,11 @@ extension SwiftFixIt {
301301
}
302302
}
303303

304-
let result = SwiftIDEUtils.FixItApplier.apply(edits: consume edits, to: sourceFile.syntax)
304+
let result = SwiftIDEUtils.FixItApplier.apply(
305+
edits: consume edits,
306+
to: sourceFile.syntax,
307+
allowDuplicateInsertions: false
308+
)
305309

306310
try self.fileSystem.writeFileContents(sourceFile.path, string: consume result)
307311
}

Tests/CommandsTests/PackageCommandTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,7 @@ class PackageCommandTestCase: CommandsBuildProviderTestCase {
21512151
}
21522152
}
21532153

2154-
try await doMigration(featureName: "ExistentialAny", expectedSummary: "Applied 3 fix-its in 1 file")
2154+
try await doMigration(featureName: "ExistentialAny", expectedSummary: "Applied 4 fix-its in 1 file")
21552155
try await doMigration(featureName: "StrictMemorySafety", expectedSummary: "Applied 1 fix-it in 1 file")
21562156
try await doMigration(featureName: "InferIsolatedConformances", expectedSummary: "Applied 1 fix-it in 1 file")
21572157
}

Tests/SwiftFixItTests/BasicTests.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,61 @@ struct BasicTests {
278278
}
279279
}
280280

281+
@Test
282+
func testOverlappingFixIts2() throws {
283+
try testAPI1File { path in
284+
.init(
285+
edits: .init(input: "var x = 1", result: "_ == 1"),
286+
summary: .init(
287+
// 2 because skipped by SwiftIDEUtils.FixItApplier, not SwiftFixIt.
288+
numberOfFixItsApplied: 3 /**/,
289+
numberOfFilesChanged: 1
290+
),
291+
diagnostics: [
292+
PrimaryDiagnostic(
293+
level: .error,
294+
text: "error1",
295+
location: .init(path: path, line: 1, column: 1),
296+
fixIts: [
297+
// Applied.
298+
.init(
299+
start: .init(path: path, line: 1, column: 1),
300+
end: .init(path: path, line: 1, column: 6),
301+
text: "_"
302+
),
303+
]
304+
),
305+
PrimaryDiagnostic(
306+
level: .error,
307+
text: "error2",
308+
location: .init(path: path, line: 1, column: 1),
309+
fixIts: [
310+
// Skipped, overlaps with previous fix-it.
311+
.init(
312+
start: .init(path: path, line: 1, column: 7),
313+
end: .init(path: path, line: 1, column: 8),
314+
text: "=="
315+
),
316+
]
317+
),
318+
PrimaryDiagnostic(
319+
level: .error,
320+
text: "error3",
321+
location: .init(path: path, line: 1, column: 1),
322+
fixIts: [
323+
// Skipped, overlaps with previous fix-it.
324+
.init(
325+
start: .init(path: path, line: 1, column: 1),
326+
end: .init(path: path, line: 1, column: 4),
327+
text: "let"
328+
),
329+
]
330+
),
331+
]
332+
)
333+
}
334+
}
335+
281336
@Test
282337
func testFixItsMultipleFiles() throws {
283338
try testAPI2Files { path1, path2 in

Tests/SwiftFixItTests/FilteringTests.swift

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -412,19 +412,12 @@ struct FilteringTests {
412412
}
413413
}
414414

415-
@Test
416415
func testDuplicateInsertionFixIts() throws {
417-
withKnownIssue("FIXME: Filter out duplicate insertion fix-its") {
418-
try self._testDuplicateInsertionFixIts()
419-
}
420-
}
421-
422-
func _testDuplicateInsertionFixIts() throws {
423416
try testAPI1File { path in
424417
.init(
425418
edits: .init(input: "var x = 1", result: "@W var yx = 21"),
426419
summary: .init(
427-
// 4 because skipped by SwiftIDEUtils.FixItApplier, not SwiftFixIt.
420+
// 6 because skipped by SwiftIDEUtils.FixItApplier, not SwiftFixIt.
428421
numberOfFixItsApplied: 6,
429422
numberOfFilesChanged: 1
430423
),
@@ -470,7 +463,7 @@ struct FilteringTests {
470463
text: "error3_fixit1",
471464
location: .init(path: path, line: 1, column: 3),
472465
fixIts: [
473-
// FIXME: Should be skipped.
466+
// Skipped, duplicate insertion.
474467
.init(
475468
start: .init(path: path, line: 1, column: 1),
476469
end: .init(path: path, line: 1, column: 1),
@@ -500,7 +493,7 @@ struct FilteringTests {
500493
text: "error5_note1",
501494
location: .init(path: path, line: 1, column: 9),
502495
fixIts: [
503-
// FIXME: Should be skipped.
496+
// Skipped, duplicate insertion.
504497
.init(
505498
start: .init(path: path, line: 1, column: 9),
506499
end: .init(path: path, line: 1, column: 9),
@@ -519,7 +512,7 @@ struct FilteringTests {
519512
text: "error6_note1",
520513
location: .init(path: path, line: 1, column: 5),
521514
fixIts: [
522-
// FIXME: Should be skipped.
515+
// Skipped, duplicate insertion.
523516
.init(
524517
start: .init(path: path, line: 1, column: 5),
525518
end: .init(path: path, line: 1, column: 5),

0 commit comments

Comments
 (0)