mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Merge pull request #2262 from xedin/adopt-refactoring-actions-to-use-edit-provider
[SwiftLanguageService] Adopt changes to package manifest refactoring …
This commit is contained in:
@@ -50,16 +50,20 @@ struct PackageManifestEdits: SyntaxCodeActionProvider {
|
||||
type: type
|
||||
)
|
||||
|
||||
let edits = try AddPackageTarget.manifestRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(target: target)
|
||||
)
|
||||
guard
|
||||
let edit = try AddPackageTarget.textRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(target: target)
|
||||
).asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
actions.append(
|
||||
CodeAction(
|
||||
title: "Add \(name) target",
|
||||
kind: .refactor,
|
||||
edit: edits.asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
edit: edit
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -98,16 +102,20 @@ struct PackageManifestEdits: SyntaxCodeActionProvider {
|
||||
dependencies: [.byName(name: targetName)],
|
||||
)
|
||||
|
||||
let edits = try AddPackageTarget.manifestRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(target: target, testHarness: testingLibrary)
|
||||
)
|
||||
guard
|
||||
let edit = try AddPackageTarget.textRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(target: target, testHarness: testingLibrary)
|
||||
).asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
actions.append(
|
||||
CodeAction(
|
||||
title: "Add test target (\(libraryName))",
|
||||
kind: .refactor,
|
||||
edit: edits.asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
edit: edit
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -151,16 +159,20 @@ struct PackageManifestEdits: SyntaxCodeActionProvider {
|
||||
targets: [targetName]
|
||||
)
|
||||
|
||||
let edits = try AddProduct.manifestRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(product: product)
|
||||
)
|
||||
guard
|
||||
let edit = try AddProduct.textRefactor(
|
||||
syntax: scope.file,
|
||||
in: .init(product: product)
|
||||
).asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
else {
|
||||
return []
|
||||
}
|
||||
|
||||
return [
|
||||
CodeAction(
|
||||
title: "Add product to export this target",
|
||||
kind: .refactor,
|
||||
edit: edits.asWorkspaceEdit(snapshot: scope.snapshot)
|
||||
edit: edit
|
||||
)
|
||||
]
|
||||
} catch {
|
||||
@@ -175,85 +187,6 @@ struct PackageManifestEdits: SyntaxCodeActionProvider {
|
||||
]
|
||||
}
|
||||
|
||||
fileprivate extension PackageEdit {
|
||||
/// Translate package manifest edits into a workspace edit. This can
|
||||
/// involve both modifications to the manifest file as well as the creation
|
||||
/// of new files.
|
||||
/// `snapshot` is the latest snapshot of the `Package.swift` file.
|
||||
func asWorkspaceEdit(snapshot: DocumentSnapshot) -> WorkspaceEdit {
|
||||
// The edits to perform on the manifest itself.
|
||||
let manifestTextEdits = manifestEdits.map { edit in
|
||||
TextEdit(
|
||||
range: snapshot.absolutePositionRange(of: edit.range),
|
||||
newText: edit.replacement
|
||||
)
|
||||
}
|
||||
|
||||
// If we couldn't figure out the manifest directory, or there are no
|
||||
// files to add, the only changes are the manifest edits. We're done
|
||||
// here.
|
||||
let manifestDirectoryURL = snapshot.uri.fileURL?
|
||||
.deletingLastPathComponent()
|
||||
guard let manifestDirectoryURL, !auxiliaryFiles.isEmpty else {
|
||||
return WorkspaceEdit(
|
||||
changes: [snapshot.uri: manifestTextEdits]
|
||||
)
|
||||
}
|
||||
|
||||
// Use the more full-featured documentChanges, which takes precedence
|
||||
// over the individual changes to documents.
|
||||
var documentChanges: [WorkspaceEditDocumentChange] = []
|
||||
|
||||
// Put the manifest changes into the array.
|
||||
documentChanges.append(
|
||||
.textDocumentEdit(
|
||||
TextDocumentEdit(
|
||||
textDocument: .init(snapshot.uri, version: snapshot.version),
|
||||
edits: manifestTextEdits.map { .textEdit($0) }
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Create an populate all of the auxiliary files.
|
||||
for (relativePath, contents) in auxiliaryFiles {
|
||||
guard
|
||||
let url = URL(
|
||||
string: relativePath,
|
||||
relativeTo: manifestDirectoryURL
|
||||
)
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
let documentURI = DocumentURI(url)
|
||||
let createFile = CreateFile(
|
||||
uri: documentURI
|
||||
)
|
||||
|
||||
let zeroPosition = Position(line: 0, utf16index: 0)
|
||||
let edit = TextEdit(
|
||||
range: zeroPosition..<zeroPosition,
|
||||
newText: contents.description
|
||||
)
|
||||
|
||||
documentChanges.append(.createFile(createFile))
|
||||
documentChanges.append(
|
||||
.textDocumentEdit(
|
||||
TextDocumentEdit(
|
||||
textDocument: .init(documentURI, version: snapshot.version),
|
||||
edits: [.textEdit(edit)]
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return WorkspaceEdit(
|
||||
changes: [snapshot.uri: manifestTextEdits],
|
||||
documentChanges: documentChanges
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension SyntaxProtocol {
|
||||
// Find an enclosing call syntax expression.
|
||||
func findEnclosingCall() -> FunctionCallExprSyntax? {
|
||||
|
||||
@@ -37,18 +37,7 @@ extension SyntaxRefactoringCodeActionProvider where Self.Context == Void {
|
||||
return []
|
||||
}
|
||||
|
||||
let textEdits = sourceEdits.compactMap { (edit) -> TextEdit? in
|
||||
let edit = TextEdit(
|
||||
range: scope.snapshot.absolutePositionRange(of: edit.range),
|
||||
newText: edit.replacement
|
||||
)
|
||||
if edit.isNoOp(in: scope.snapshot) {
|
||||
return nil
|
||||
}
|
||||
return edit
|
||||
}
|
||||
|
||||
if textEdits.isEmpty {
|
||||
guard let workspaceEdit = sourceEdits.asWorkspaceEdit(snapshot: scope.snapshot) else {
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -56,7 +45,7 @@ extension SyntaxRefactoringCodeActionProvider where Self.Context == Void {
|
||||
CodeAction(
|
||||
title: Self.title,
|
||||
kind: .refactorInline,
|
||||
edit: WorkspaceEdit(changes: [scope.snapshot.uri: textEdits])
|
||||
edit: workspaceEdit
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -140,3 +129,30 @@ extension SyntaxProtocol {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension [SourceEdit] {
|
||||
/// Translate source edits into a workspace edit.
|
||||
/// `snapshot` is the latest snapshot of the document to which these edits belong.
|
||||
func asWorkspaceEdit(snapshot: DocumentSnapshot) -> WorkspaceEdit? {
|
||||
let textEdits = compactMap { edit -> TextEdit? in
|
||||
let edit = TextEdit(
|
||||
range: snapshot.absolutePositionRange(of: edit.range),
|
||||
newText: edit.replacement
|
||||
)
|
||||
|
||||
if edit.isNoOp(in: snapshot) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return edit
|
||||
}
|
||||
|
||||
if textEdits.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
return WorkspaceEdit(
|
||||
changes: [snapshot.uri: textEdits]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,29 +623,19 @@ final class CodeActionTests: XCTestCase {
|
||||
}
|
||||
)
|
||||
|
||||
guard let addTestChanges = addTestAction?.edit?.documentChanges else {
|
||||
guard let addTestChanges = addTestAction?.edit?.changes else {
|
||||
XCTFail("Didn't have changes in the 'Add test target (Swift Testing)' action")
|
||||
return
|
||||
}
|
||||
|
||||
guard
|
||||
let addTestEdit = addTestChanges.lazy.compactMap({ change in
|
||||
switch change {
|
||||
case .textDocumentEdit(let edit): edit
|
||||
default: nil
|
||||
}
|
||||
}).first
|
||||
else {
|
||||
guard let manifestEdits = addTestChanges[uri] else {
|
||||
XCTFail("Didn't have edits")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertTrue(
|
||||
addTestEdit.edits.contains { edit in
|
||||
switch edit {
|
||||
case .textEdit(let edit): edit.newText.contains("testTarget")
|
||||
case .annotatedTextEdit(let edit): edit.newText.contains("testTarget")
|
||||
}
|
||||
manifestEdits.contains { edit in
|
||||
edit.newText.contains("testTarget")
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user