Swift Development using NeoVim

Hello, i'm struggling to try setup my Swift environment inside NeoVim. I've try here and there but none of them works, like show code completions/suggestions inside UIKit or SwiftUI project based.

This is my current lsp configuration for NeoVim:

If you successfully migrate from XCode into NeoVim distro, please give some example of how you setup your configuration, and maybe step-by-step from zero.

Have a nice day, and thank you :beers:

1 Like

I do pretty much all of my development with neovim in both macOS and Linux environments. My full config is available here; dotfiles/nvim at main · etcwilde/dotfiles · GitHub, and the LSP setup is here dotfiles/nvim/lua/plugins/lsp.lua at main · etcwilde/dotfiles · GitHub. The neovim/nvim-lspconfig plugin is sourcekit-lsp-aware, so you just enable it and it pretty much works with a little configuration. I have the root-dir configurations, but it looks like someone fixed the default in newer versions of the plugin so my setup looks a little redundant here, though it looks like the docs are still missing bits. I know this config works with projects that emit compile-commands JSON databases and with swift packages. Not sure if sourcekit-lsp has Xcode-project support. That's a question for @ahoppen. Sourcekit-lsp also has information on setting up the LSP support here: sourcekit-lsp/Editors at main · apple/sourcekit-lsp · GitHub.

If you have sourcekit-lsp in your path, you don't need to explicitly set the full path to sourcekit-lsp. On macOS, I believe /usr/bin/sourcekit-lsp already exists if you install Xcode, and is on your path. It's a shim through xcrun, which will then grab the appropriate sourcekit-lsp from Xcode without you needing to hard-code the full path to the binary.

What do you get when you run :LspInfo after opening a Swift file? It should show a list of clients (lsp-servers), one of which should be sourcekit. It should list what filetypes it supports (swift, c, cpp, objective-c, and objective-cpp). Mine is set to autostart. Then it should list the root directory, the command run, and then a list of other configured servers. In your case, it looks like you only have the one, so it should only list sourcekit there.

Once you've made sure that it's actually initializing things, it should mostly be a matter of setting up the keymaps. I use which-key so if I forget a keymapping, it'll remind me. Alternatively, you can call through the nvim lua APIs directly to test things out. Those are global to all of the servers you configure.

5 Likes

Hello, mate. Thank you for you reactions.

I've try to copy and paste your lsp.lua into my NeoVim configurations, but the results i get still the same, no code suggestions/completions for my Swift file.

This is your edited code inside my configurations:

This is LspConfig results:

This is my swift file when typing import but the LSP not give code completions/suggestions:

And this is my working directories:

If you want me to show or check something, feel free to guide me, i'll try to give my best.
Thank you for your helps :beers:

It looks like you are connecting to the sourcekit-lsp server and finding the root directory correctly. Start with something simple. E.g let str: String, put the cursor on String and ask for hover info. It should bring up the docs for String. If that works, it should be a matter of setting up the right key maps and checking the sourcekit docs to see what it supports. If you aren’t using which-key, I wouldn’t expect that to work. You’ll have to set up the key maps by hand. IIRC it will look something like vim.keymap.set('n', 'K', '<cmd>lua vim.lsp.buf.hover()<cr>') to match my hover-info keymapping.

Hello, i've try to create new simple project and it seems the SourceKit-LSP starting to work, but something missing. Like if i want to import UIKit module or import internal library, then the SourceKit-LSP cannot give the code completions/suggestions, like SourceKit-LSP doesn't know what the UIKit module is. And when i try to check LSP log using LspLog command, then some errors was thrown, please check my screenshoots below:

Thank you for your feedback :beers:

Okay, the good news is, everything is configured and working on the nvim side. You wouldn't be getting hover info for things like String if it weren't.

The missing UIKit module suggests that the SwiftPM integration doesn't know where to look for the SDK, but given that it is finding Foundation, I would hazard a guess that it's assuming you're building for macOS. Does it auto-complete AppKit? I'm not sure how to tell a Swift package that it's built for iOS and to provide completions for iOS, but I'm assuming you'll need to do that and then you should get auto-complete for the right SDK.

Hello, i think you're correct. The SwiftPM think that i want to build for macOS, and when i try to typing import appk, then SourceKit-LSP shows AppKit as Module.

I've try to change the sysroot into iPhone, but no luck. I try to change the sysroot into iPhone because from this article, maybe when the sysroot changed into iPhone, then SwiftPM know that i want to build the package for iOS, not for macOS.

Please check my screenshoots below:

Even when i try to generate simple iOS project from XCode, and run it using NeoVim, the SourceKit-LSP still treat the project as for macOS build:

Maybe SourceKit-LSP hate NeoVim, mate.

Thank you for your response, and have a good day :beers:

I'm afraid this is a more general issue with SourceKitLSP not supporting SwiftPM's cross-compilation/custom-SDK flags. Here's a related issue on their GitHub repository.

SwiftPM has flags for using a custom SDK or specifying a custom triple (the default is usually the host triple/SDK). SourceKitLSP hasn't added support for these yet. So for all IDE functionality relying on SourceKitLSP, you can't currently do cross compilation; only Xcode supports that.

So, if that SourceKitLSP not supporting SwiftPM features yet, then why SourceKitLSP didn't give the code completions/suggestions from project generated by XCode?

And ofcourse we've already set the platform into iOS when we generate the project using XCode.

Correct me if i'm wrong and i'm sorry for my bad English.
Thank you for your response :beers:

Hi Bengi,

I’m sorry my first response was rather unclear. I meant to say that the reason Xcode supports better cross compilation is because it has its own build system and language-server system. That is, Xcode doesn’t use SourceKitLSP and is not bound by its limitations.

If I understand correctly, you chose the iOS project on the Xcode project setup dialog. However, because NeoVim and other 3rd party IDEs use SwiftPM and SourceKitLSP (not Xcode’s proprietary build system), they still don’t support cross compiling. So it doesn’t matter if you set up your project in Xcode, but the tools you’re using to build it.

I hope this helps! Let me know if you have any other questions.

1 Like

SourceKitLSP didn't give the code completions/suggestions from project generated by Xcode

yeah, pretty sure SourceKitLSP doesn't support the Xcode project format. The expectation is that you use Xcode when working with Xcode projects.

SourceKitLSP hasn't added support for these yet. So for all IDE functionality relying on SourceKitLSP, you can't currently do cross compilation; only Xcode supports that.

Well sort of. SPM doesn't let you configure builds outside of the manifest very easily, so it's more on the side of SPM to tell SourceKit-LSP what it should be showing results for. Most folks don't directly interact with LSP server any more than Xcode users directly interact with the indexing mechanism. It's up to the build system to know what you're configuring a build for and to relay that info to the server somehow. The upcoming CMake 3.29 will have support for generating compile-commands for Swift. The commands in that file tell the LSP server what SDK is available, what defines are set, header/module search-paths, etc so that you get information that is specific to your build. I just double-checked, if you tell CMake you're cross-compiling for iOS, SourceKit-LSP will pick up the generated compile_commands.json and give you completions/information for that build.

2 Likes

My recommendation is to use Xcode-build-server and use BSP instead of LSP.

Most LSP servers if not all works with BSP (Build Server Protocol)

1 Like

I've try that way, but unfortunately there's no luck.

You can see in the issue section of that repo, i've submit the same issue in that repo too.

That sounds great, mate. Hope the Apple Engineers and Swift Communities make it works.

And can you tell us, where we can see the CMake updates?