Skip to content

Commit a095810

Browse files
committed
Implement an initializer of CodeAction with the FixIt from swift-syntax
Finetune the code Finetune the code Finetune the code Update the code per comments Use location marker instead of hard coded indexes Update the test to align the code convention Rename a variable Correct unit tests Format the code Update Package.swift
1 parent 8f53d08 commit a095810

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)