Skip to content

Commit 113219a

Browse files
authored
Merge pull request #941 from joehsieh/report-codeActions-for-fix-its-produced-by-swift-syntax
Report codeActions for fixIts produced by swift syntax
2 parents 8f53d08 + a095810 commit 113219a

File tree

2 files changed

+86
-18
lines changed

2 files changed

+86
-18
lines changed

Sources/SourceKitLSP/Swift/Diagnostic.swift

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,10 @@ extension CodeAction {
4444
if let fromNote = fromNote {
4545
title = fromNote
4646
} else {
47-
guard let startIndex = snapshot.index(of: edits[0].range.lowerBound),
48-
let endIndex = snapshot.index(of: edits[0].range.upperBound),
49-
startIndex <= endIndex,
50-
snapshot.text.indices.contains(startIndex),
51-
endIndex <= snapshot.text.endIndex
52-
else {
53-
logger.fault("position mapped, but indices failed for edit range \(String(reflecting: edits[0]))")
47+
guard let generatedTitle = Self.title(for: edits, in: snapshot) else {
5448
return nil
5549
}
56-
let oldText = String(snapshot.text[startIndex..<endIndex])
57-
let description = Self.fixitTitle(replace: oldText, with: edits[0].newText)
58-
if edits.count == 1 {
59-
title = description
60-
} else {
61-
title = description + "..."
62-
}
50+
title = generatedTitle
6351
}
6452

6553
self.init(
@@ -71,10 +59,43 @@ extension CodeAction {
7159
}
7260

7361
init?(_ fixIt: FixIt, in snapshot: DocumentSnapshot) {
74-
// FIXME: Once https://github.com/apple/swift-syntax/pull/2226 is merged and
75-
// FixItApplier is public, use it to compute the edits that should be
76-
// applied to the source.
77-
return nil
62+
var textEdits = [TextEdit]()
63+
for edit in fixIt.edits {
64+
guard let startPosition = snapshot.position(of: edit.range.lowerBound),
65+
let endPosition = snapshot.position(of: edit.range.upperBound)
66+
else {
67+
continue
68+
}
69+
textEdits.append(TextEdit(range: startPosition..<endPosition, newText: edit.replacement))
70+
}
71+
72+
self.init(
73+
title: fixIt.message.message.withFirstLetterUppercased(),
74+
kind: .quickFix,
75+
diagnostics: nil,
76+
edit: WorkspaceEdit(changes: [snapshot.uri: textEdits])
77+
)
78+
}
79+
80+
private static func title(for edits: [TextEdit], in snapshot: DocumentSnapshot) -> String? {
81+
if edits.isEmpty {
82+
return nil
83+
}
84+
guard let startIndex = snapshot.index(of: edits[0].range.lowerBound),
85+
let endIndex = snapshot.index(of: edits[0].range.upperBound),
86+
startIndex <= endIndex,
87+
snapshot.text.indices.contains(startIndex),
88+
endIndex <= snapshot.text.endIndex
89+
else {
90+
logger.fault("position mapped, but indices failed for edit range \(String(reflecting: edits[0]))")
91+
return nil
92+
}
93+
let oldText = String(snapshot.text[startIndex..<endIndex])
94+
let description = Self.fixitTitle(replace: oldText, with: edits[0].newText)
95+
if edits.count == 1 {
96+
return description
97+
}
98+
return description + "..."
7899
}
79100

80101
/// Describe a fixit's edit briefly.

Tests/SourceKitLSPTests/CodeActionTests.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,4 +425,51 @@ final class CodeActionTests: XCTestCase {
425425

426426
try await fulfillmentOfOrThrow([editReceived])
427427
}
428+
429+
func testCodeActionForFixItsProducedBySwiftSyntax() async throws {
430+
let ws = try await MultiFileTestWorkspace(files: [
431+
"test.swift": "protocol 1️⃣Multi 2️⃣ident 3️⃣{}",
432+
"compile_commands.json": "[]",
433+
])
434+
435+
let (uri, positions) = try ws.openDocument("test.swift")
436+
437+
let report = try await ws.testClient.send(DocumentDiagnosticsRequest(textDocument: TextDocumentIdentifier(uri)))
438+
guard case .full(let fullReport) = report else {
439+
XCTFail("Expected full diagnostics report")
440+
return
441+
}
442+
443+
XCTAssertEqual(fullReport.items.count, 1)
444+
let diagnostic = try XCTUnwrap(fullReport.items.first)
445+
let codeActions = try XCTUnwrap(diagnostic.codeActions)
446+
447+
let expectedCodeActions = [
448+
CodeAction(
449+
title: "Join the identifiers together",
450+
kind: .quickFix,
451+
edit: WorkspaceEdit(
452+
changes: [
453+
uri: [
454+
TextEdit(range: positions["1️⃣"]..<positions["2️⃣"], newText: "Multiident "),
455+
TextEdit(range: positions["2️⃣"]..<positions["3️⃣"], newText: ""),
456+
]
457+
]
458+
)
459+
),
460+
CodeAction(
461+
title: "Join the identifiers together with camel-case",
462+
kind: .quickFix,
463+
edit: WorkspaceEdit(
464+
changes: [
465+
uri: [
466+
TextEdit(range: positions["1️⃣"]..<positions["2️⃣"], newText: "MultiIdent "),
467+
TextEdit(range: positions["2️⃣"]..<positions["3️⃣"], newText: ""),
468+
]
469+
]
470+
)
471+
),
472+
]
473+
XCTAssertEqual(expectedCodeActions, codeActions)
474+
}
428475
}

0 commit comments

Comments
 (0)