mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-06 18:24:36 +01:00
When translating editor placeholders to snippets, we should not include internal parameter names into the snippet. The problem is that once you leave snippet editing mode (essentially by moving the cursor to any place that’s not the snippet, eg. by typing a string literal for one of the parameters or moving the cursor), all snippets become verbatim text. And then it’s impossible to tell whether `paramName: ` was an annotation inside the snippet describing the internal parameter’s name or the external parameter label. rdar://123772474
44 lines
1.6 KiB
Swift
44 lines
1.6 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import LSPLogging
|
|
@_spi(SourceKitLSP) import SwiftRefactor
|
|
|
|
func rewriteSourceKitPlaceholders(in string: String, clientSupportsSnippets: Bool) -> String {
|
|
var result = string
|
|
var index = 1
|
|
while let start = result.range(of: "<#") {
|
|
guard let end = result[start.upperBound...].range(of: "#>") else {
|
|
logger.error("invalid placeholder in \(string)")
|
|
return string
|
|
}
|
|
let rawPlaceholder = String(result[start.lowerBound..<end.upperBound])
|
|
guard let displayName = EditorPlaceholderData(text: rawPlaceholder)?.nameForSnippet else {
|
|
logger.error("failed to decode placeholder \(rawPlaceholder) in \(string)")
|
|
return string
|
|
}
|
|
let snippet = clientSupportsSnippets ? "${\(index):\(displayName)}" : ""
|
|
result.replaceSubrange(start.lowerBound..<end.upperBound, with: snippet)
|
|
index += 1
|
|
}
|
|
return result
|
|
}
|
|
|
|
fileprivate extension EditorPlaceholderData {
|
|
var nameForSnippet: Substring {
|
|
switch self {
|
|
case .basic(text: let text): return text
|
|
case .typed(text: let text, type: _): return text
|
|
}
|
|
}
|
|
}
|