# Design Overview

This document gives a general overview of the major design concepts in SourceKit-LSP and how components fit together. Detailed doc comments can usually be found on the individual types.

## Message handling

LSP Messages (ie. LSP requests or notifications) sent to SourceKit-LSP via stdin are handled using `JSONRPCConnection`, which decodes the JSON in the message to a type from `LanguageServerProtocol`. We need to guarantee that LSP messages are generally handled in-order. Re-ordering eg. `textDocument/didChange` notifications would be a major issue since it results in out-of-sync document contents. Since Swift concurrency does not make any ordering guarantees (Tasks and async calls can be executed in any order), the `Connection` types are serial and don’t use Swift Concurrency features.

After the message has been decoded, the `SourceKitLSPServer` handles it on its `messageHandlingQueue`. `SourceKitLSPServer` is capable of interpreting the semantic meaning of requests and is able to decide whether requests can be executed in parallel, modelled by `MessageHandlingDependencyTracker`. For example, edits to different documents don’t have any dependencies and can be handled concurrently or out-of-order. Similarly requests to the same document that aren’t modifying it can be handled concurrently.

## Language services

To provide language-specific functionality `SourceKitLSPServer` delegates to the types that implement `LanguageService`. This is either `SwiftLanguageService`, which implements language functionality for Swift files based on sourcekitd and swift-syntax, or `ClangLanguageService`, which launches a `clangd` process to provide functionality for C, C++, Objective-C and Objective-C++.

For requests that require knowledge about the project’s index, like call hierarchy or rename of global symbols, `SourceKitLSPServer` enriches the information returned from the language service with information from the [index](http://github.com/swiftlang/indexstore-db/).

### sourcekitd

[sourcekitd](https://github.com/apple/swift/tree/main/tools/SourceKit) is implemented in the Swift compiler’s repository and uses the Swift compiler’s understanding of Swift code to provide semantic functionality. On macOS, sourcekitd is run as an XPC service and all other platforms sourcekitd is run in the sourcekit-lsp process. This means that on macOS, a crash of sourcekitd can be recovered by re-launching sourcekitd, while on other platforms a crash inside sourcekitd crashes sourcekit-lsp.

## Build servers

Basically all semantic functionality requires knowledge about how a file is being built (like module search paths to be able to resolve `import` statements). SourceKit-LSP consults a *build server* to get this information. Build servers that are currently supported are:
- `SwiftPMBuildServer`: Reads a `Package.swift` at the project’s root
- `CompilationDatabaseBuildServer`: Reads a `compile_commands.json` file to provide build settings for files. `compile_commands.json` can eg. be generated by CMake.
- `ExternalBuildServerAdapter`: Launches an external BSP server process to provide build settings.

## Logging

SourceKit-LSP has fairly extensive logging to help diagnose issues. The way logging works depends on the platform that SourceKit-LSP is running on.

On macOS, SourceKit-LSP logs to the system log. [CONTRIBUTING.md](../CONTRIBUTING.md#logging) contains some information about how to read the system logs. Since [OSLog](https://developer.apple.com/documentation/os/logging) cannot be wrapped, the decision to log to macOS’s system log is done at build time and cannot be modified at runtime.

On other platforms, the `NonDarwinLogger` types are used to log messages. These types are API-compatible with OSLog. Log messages are written to stderr by default. When possible, `SourceKitLSP.run` will redirect the log messages to log files in `~/.sourcekit-lsp` on launch.
