Swift: sourcekit-lsp y proyectos Xcode
Swift en Neovim 0.12 (macOS): sourcekit-lsp de la toolchain declarado en la carpeta lsp, xcode-build-server para proyectos Xcode, parser de Treesitter, formateo con swift-format y gestión de toolchains con swiftly.
Swift en Neovim es totalmente viable en macOS. El servidor de lenguaje, sourcekit-lsp, viene con la toolchain de Swift y de Xcode, así que no hay nada que instalar: solo hay que describirlo y activarlo. El trabajo de verdad está en que encuentre cómo se compila tu proyecto — trivial con SPM, un paso extra con Xcode.
- Declarar sourcekit-lsp en
lsp/sourcekit.luay activarlo convim.lsp.enable. - Evitar el choque de tipos de archivo con clangd.
- Generar
buildServer.jsoncon xcode-build-server para proyectos Xcode. - Parser de Swift, formateo con swift-format y toolchains con swiftly.
sourcekit-lsp funciona mejor en macOS con Xcode instalado. En Linux funciona con la toolchain de Swift, pero sin las APIs de Apple. Como desarrollas Swift, asumimos macOS con las herramientas de línea de comandos de Xcode.
Declarar sourcekit-lsp
sourcekit-lsp no se instala aparte: viene con la toolchain, así que Mason no pinta nada aquí (su trabajo es conseguir binarios, y este ya lo tienes). Tampoco necesitas nvim-lspconfig: en Neovim 0.12 basta con una ficha en la carpeta lsp/ de tu runtimepath y una línea para activarla.
return {
cmd = { "xcrun", "sourcekit-lsp" },
filetypes = { "swift" },
root_markers = {
"buildServer.json",
".bsp",
"Package.swift",
"compile_commands.json",
".git",
},
capabilities = {
workspace = {
didChangeWatchedFiles = { dynamicRegistration = true },
},
},
}
vim.lsp.enable("sourcekit")
Dos decisiones de esa ficha merecen explicación.
La primera es el cmd. El binario se llama sourcekit-lsp a secas, y si tu toolchain está en el PATH puedes invocarlo así. Anteponer xcrun obliga a usar el de la toolchain activa de Xcode, que es justo lo que quieres cuando tienes varias instaladas: el propio proyecto de xcode-build-server avisa de que los fallos raros —del tipo “no se puede cargar la biblioteca estándar”— casi siempre son una versión de build y una de sourcekit-lsp que no coinciden. Con xcode-select cambias de toolchain y xcrun sourcekit-lsp te sigue.
La segunda es filetypes. sourcekit-lsp también sabe de C, C++ y Objective-C, y su ficha por defecto en el catálogo de nvim-lspconfig los declara todos. Si además usas clangd (lección 2.5), los dos servidores se adjuntarán al mismo buffer de C y verás diagnósticos duplicados. Deja { "swift" } a secas, o añade "objc" y "objcpp" si trabajas con código mixto de Apple, y que C y C++ sean territorio de clangd.
Verifica en el terminal que la tienes: xcrun sourcekit-lsp --help y swift --version. Si falla, instala las herramientas con xcode-select --install o abre Xcode una vez para que termine de configurarse. Ya dentro de Neovim, :checkhealth vim.lsp te dice si el cliente está adjunto y qué raíz resolvió, y el comando :lsp te da el estado en el buffer actual.
SPM: funciona directo
En un paquete de Swift Package Manager (con Package.swift en la raíz), sourcekit-lsp funciona sin más: abre cualquier .swift y tendrás completado, ir a definición y diagnósticos. Es el caso ideal, y también el motivo de que Package.swift esté en los root_markers.
Proyectos Xcode: xcode-build-server
Para proyectos .xcodeproj o .xcworkspace, sourcekit-lsp necesita un buildServer.json que le explique el grafo de compilación. Lo genera xcode-build-server, una implementación del Build Server Protocol que traduce entre Xcode y sourcekit-lsp:
brew install xcode-build-server
# En la raíz del proyecto (donde vive el .xcodeproj o el .xcworkspace):
xcode-build-server config -project MiApp.xcodeproj -scheme MiApp
# o, para un workspace:
xcode-build-server config -workspace MiApp.xcworkspace -scheme MiApp
Esto crea o actualiza buildServer.json en ese directorio, que debe ser la raíz que resuelve tu cliente LSP — por eso buildServer.json va el primero en root_markers. A partir de ahí, el servidor toma los flags de compilación del registro de la última build de Xcode. Si el proyecto cambia (archivos nuevos, otro SDK, macros condicionales) y algo deja de funcionar, no toques la configuración: compila en Xcode y los flags se refrescan solos.
sourcekit-lsp usa indexado durante la compilación: el índice de símbolos se construye cuando construyes el proyecto, no cuando abres el archivo. En un proyecto recién clonado, ir a definición y buscar referencias funcionarán a medias hasta la primera build completa. No es un fallo de configuración, es cómo está diseñado.
El parser de Swift
Nada de require("nvim-treesitter.configs").setup(...), ensure_installed ni highlight: ese módulo ya no existe en la rama main, que es la única viva. El plugin instala parsers y aporta queries; el resaltado y el plegado los pone Neovim.
require("nvim-treesitter").install({ "swift" })
-- Sin foldlevelstart = 99, cada archivo se abre ENTERO PLEGADO.
-- Ponlo una vez en tus opciones (leccion 2.3).
vim.o.foldlevelstart = 99
vim.api.nvim_create_autocmd("FileType", {
pattern = { "swift" },
callback = function()
vim.treesitter.start()
vim.wo[0][0].foldexpr = "v:lua.vim.treesitter.foldexpr()"
vim.wo[0][0].foldmethod = "expr"
end,
})
En SwiftUI, donde las vistas anidan mucho, el plegado por sintaxis cambia la vida: zc cierra el bloque bajo el cursor y zR lo abre todo. Y los objetos de texto de la lección 2.3 (vaf, cif, ]f) funcionan igual que en cualquier otro lenguaje con parser.
Formateo con swift-format
Ya declaraste swift = { "swift_format" } en conform (lección 2.4). Desde Swift 6, swift-format viene incluido en la toolchain y puedes invocarlo como swift format (con espacio) o localizar el binario con xcrun --find swift-format; si tu toolchain es más antigua, brew install swift-format.
Para el estilo, swift-format busca un fichero JSON llamado .swift-format en el directorio del archivo y va subiendo. La forma sensata de crearlo no es escribirlo a mano, sino volcar el que ya usa y editarlo:
swift-format dump-configuration > .swift-format
Con swift-format dump-configuration --effective compruebas qué configuración se aplicaría de verdad desde el directorio actual, teniendo en cuenta los .swift-format encontrados.
Gestionar toolchains con swiftly
swiftly es el gestor oficial de toolchains de Swift: instala varias versiones, cambia la activa y actualiza. Instálalo desde la página de instalación de swift.org y a partir de ahí:
swiftly list-available # qué toolchains puedes instalar
swiftly install main-snapshot # una nightly de la rama main
swiftly use main-snapshot # cámbiate a ella
swiftly self-update # actualizar el propio swiftly
Un detalle que ahorra discusiones en equipo: swiftly lee un fichero .swift-version en el proyecto, así que la versión recomendada puede viajar con el repositorio en lugar de vivir en la cabeza de cada uno.
Para builds, simuladores, tests y depuración de apps de Xcode desde el editor, mira xcodebuild.nvim (wojciech-kulik/xcodebuild.nvim): cubre iOS, iPadOS, watchOS, tvOS, visionOS y macOS, tiene explorador de tests, cobertura, gestión de simuladores e integración con nvim-dap. Es un plugin grande y con muchas piezas opcionales, así que su instalación y configuración están documentadas en su wiki; sigue esa, no un fragmento copiado de un blog.
El ecosistema Swift en Neovim es más pequeño que el de Rust o el del frontend, y sourcekit-lsp puede tardar en indexar proyectos Xcode grandes. Aun así, para editar Swift —SwiftUI, paquetes SPM, lógica de servidor— tienes completado, navegación, diagnósticos, formateo y depuración. Fíjate en dónde ha estado el trabajo de esta lección: casi nada ha sido “configurar el editor”. Ha sido explicarle al servidor cómo se compila el proyecto, que es un problema del sistema de build, no del editor. Esa distinción se generaliza: cuando un LSP va mal, pregúntate primero si el problema está en el editor, en el servidor o en el proyecto. Nueve de cada diez veces está en el tercero, y ninguna configuración de Neovim lo va a arreglar.
- Confirma
xcrun sourcekit-lsp --helpen el terminal. - Escribe
lsp/sourcekit.luaconfiletypeslimitado a Swift y actívalo convim.lsp.enable. - Abre un paquete SPM y verifica completado con
Kygd. - En un proyecto Xcode, genera
buildServer.jsoncon xcode-build-server, compila una vez en Xcode y vuelve a probargd. - Instala el parser de Swift y pliega una vista de SwiftUI con
zc. - Vuelca un
.swift-formatcondump-configuration, baja el ancho de línea y guarda un archivo mal formateado.