Files
sourcekit-lsp/Sources/SourceKitLSP/Swift/RewriteSourceKitPlaceholders.swift
Alex Hoppen a0453673f5 Don’t include internal parameter names in LSP snippets
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
2024-03-01 21:38:01 -08:00

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
}
}
}