mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
We are tied to using a SwiftPM that matches the toolchain, so upgrade
from 0.3.0 to .branch("master") and add a pins file to manage updating
that dependency.
This was driven by changes that broke loading packages being developed
with newer version of SwiftPM when using the 0.3.0 tag of libSwiftPM.
However, the changes seem to work when going in the other direction, so
using the newer libSwiftPM hasn't caused any known regressions for using
older toolchain versions (not guarantteed and not tested extensively
though).
This fixes using the latest (November 13) toolchain snapshot on macOS.
On Linux there are other issues not specific to LSP.
79 lines
2.8 KiB
Swift
79 lines
2.8 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 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 LanguageServerProtocol
|
|
import SKSupport
|
|
|
|
struct MessageHeader: Hashable {
|
|
static let contentLengthKey: [UInt8] = [UInt8]("Content-Length".utf8)
|
|
static let separator: [UInt8] = [UInt8]("\r\n".utf8)
|
|
static let colon: UInt8 = ":".utf8.spm_only!
|
|
static let invalidKeyBytes: [UInt8] = [colon] + separator
|
|
|
|
var contentLength: Int? = nil
|
|
}
|
|
|
|
extension RandomAccessCollection where Element == UInt8 {
|
|
|
|
/// Returns the first message range and header in `self`, or nil.
|
|
func splitMessage() throws -> ((SubSequence, header: MessageHeader), SubSequence)? {
|
|
guard let (header, rest) = try parseHeader() else { return nil }
|
|
guard let contentLength = header.contentLength else {
|
|
throw MessageDecodingError.parseError("missing Content-Length header")
|
|
}
|
|
if contentLength > rest.count { return nil }
|
|
return ((rest.prefix(contentLength), header: header), rest.dropFirst(contentLength))
|
|
}
|
|
|
|
func parseHeader() throws -> (MessageHeader, SubSequence)? {
|
|
var header = MessageHeader()
|
|
var slice = self[...]
|
|
while let (kv, rest) = try slice.parseHeaderField() {
|
|
guard let (key, value) = kv else {
|
|
return (header, rest)
|
|
}
|
|
slice = rest
|
|
|
|
if key.elementsEqual(MessageHeader.contentLengthKey) {
|
|
guard let count = Int(ascii: value) else {
|
|
throw MessageDecodingError.parseError("expected integer value in \(String(bytes: value, encoding: .utf8) ?? "<invalid>")")
|
|
}
|
|
header.contentLength = count
|
|
}
|
|
|
|
// Unknown field, continue.
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseHeaderField() throws -> ((key: SubSequence, value: SubSequence)?, SubSequence)? {
|
|
if starts(with: MessageHeader.separator) {
|
|
return (nil, dropFirst(MessageHeader.separator.count))
|
|
} else if first == MessageHeader.separator.first {
|
|
return nil
|
|
}
|
|
|
|
guard let keyEnd = firstIndex(where: { MessageHeader.invalidKeyBytes.contains($0) }) else {
|
|
return nil
|
|
}
|
|
if self[keyEnd] != MessageHeader.colon {
|
|
throw MessageDecodingError.parseError("expected ':' in message header")
|
|
}
|
|
let valueStart = index(after:keyEnd)
|
|
guard let valueEnd = self[valueStart...].firstIndex(of: MessageHeader.separator) else {
|
|
return nil
|
|
}
|
|
|
|
return ((key: self[..<keyEnd], value: self[valueStart..<valueEnd]), self[index(valueEnd, offsetBy: 2)...])
|
|
}
|
|
}
|