VSCode settings for Swift

Hi all,

I'm relatively new to swift but wanted to document how I set up VSCode as a fairly good IDE. I don't have anything particularly AGAINST XCode (except that, for me, it's the IDE equivalent of iTunes), but I use VSCode as my primary editor for my other languages and wanted to see whether I could get it working with Swift. This is on my Mac, btw. YMMV for other OSes.

TLDR: it works, mostly well.

Extensions I installed:

  • CodeLLDB for debugging
  • Run On Save for formatting
  • SwiftLint for linting
  • Maintained Swift Development Environment (MSDE) for syntax highlighting and hovering
  • Dash for offline documentation

Utilities I installed:

  • swiftformat
  • swiftlint
  • sourcekite (instructions at the MSDE plugin repo)

First off: I disabled format on save in VSCode, and autosave as well. I then added the following:

"emeraldwalk.runonsave": {
    "commands": [
        {
            "match": "\\.swift$",
            "isAsync": false,
            "cmd": "cd ${fileDirname} && swiftformat ${fileBasename}"
       }
    ]
}

This will autoformat all files ending in .swift whenever they're saved.

Next, I created a tasks.json as follows:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "swiftc with debug",
            "type": "shell",
            "command": "swiftc -g ${file}",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "panel": "dedicated"
            }
        }
    ]
}

This can be used by itself, but it's better with a launch.json:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=8303
87
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "preLaunchTask": "swiftc with debug",
            "name": "Debug",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "sourceLanguages": [
                "swift"
            ]
        }
    ]
}

With these two files, LLDB debugging works - you can set breakpoints, inspect variables, etc... all from within VSCode.

It'd be nice if we had a "one-stop shop" for turning VSCode into a Swift IDE, but until then, I hope this helps.

If there are VSCode experts out there who want to give suggestions as to how to make my environment even better, I'm all ears.

12 Likes

Thanks for sharing this, it’s really cool!

Thanks for sharing.

I am wondering if anyone managed to setup a good-enough Swift IDE using Atom instead of VSCode.

@gmosx I used Atom before VSCode, but its plugins were even more out-of-date than those for VSCode.

You can try using these as well, but you'll have to make the bindings for Atom:

  • langserver-swift: uses official Language Server Protocol from MS. Should be very easy to make work for Atom.
  • SKD: uses its own protocol, but includes an example biding so that you can make it work with an arbitrary editor.

None of them work outside of MacOS (yet), but there are ongoing efforts to finish the respective ports.

As a followup, I want to give a shoutout to CodeRunner, which is a great editor for OSX users and supports Swift (syntax highlighting, completion, and debugging). The author is pretty responsive as well.

2 Likes

:sob:

3 Likes

Don't worry, you're not that bad. At least you don't randomly break different UI guidelines willy-nilly every release. Although I still don't understand why you thought merging Project Builder and Interface Builder into one application was a good idea.

1 Like

This looks cool. However, this will only work for command line or server swift, right? This won't work for building iOS or macOS apps, will it?

On the MSDE plugin repo at Github, there appear to be two alternative macOS installation options for installing sourcekite. One is described as when using swiftenv or multiple Toolchains while the other is described as using Xcode's Toolchain.

Which one should I use? I suspect it's the latter option but I would like to be sure!

I decided to live life dangerously and go with the second option. I have run up against a problem but I think this is a different issue. I'm trying to build a command line swift app and I'm getting the error...

Error: Could not initialize debug target: unable to find executable for '/Users/carlca/code/swift/FileOrganiser/Sources/FileOrganiser/main'

Any ideas, anyone?

Hi all, these configs will work when debugging the currently opened, standalone Swift script without dependencies.

In case you have SwiftPM project with an executable the following configs will help you (examples taken from vknabel/vscode-swift-development-environment#debugging):

// .vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Run your Executable",
            "program": "${workspaceFolder}/.build/debug/your-executable",
            "args": [],
            "cwd": "${workspaceFolder}",
            "preLaunchTask": "swift-build"
        }
}
// .vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "swift-build",
            "type": "shell",
            "command": "swift build"
        }
}

I haven't tried out debugging Xcode projects using VS Code, but at least for macOS targets xcodebuild should help.

1 Like

THANK YOU VERY MUCH!

I tried to do this before but I know little about LLDB, you've made my day.

Anybody know how to use this to debug Swift Unit Tests?
Apparently no test executable is created by swift build so I don't know what to put in program.

@cgarciae

You would need to put a reference to the xctest bundle in program. e.g.

"program": "./.build/x86_64-unknown-linux/debug/PredicatePackageTests.xctest",

@olbo Thanks! I've been copying the test I wanted to debug to a main.swift. This is super useful!