Files
sourcekit-lsp/Sources/SourceKitLSP/Swift/OpenInterface.swift
Alex Hoppen d0fc00ce98 Format using swift-format
Add `.swift-format` to the repo and format the repo with `swift-format`.

This commit does not add any automation to enforce formatting of sourcekit-lsp in CI. The goal of this commit is to get the majority of source changes out of the way so that the diff of actually enforcing formatting will have fewer changes or conflicts.
2023-10-10 13:44:47 -07:00

119 lines
4.1 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 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 Foundation
import LSPLogging
import LanguageServerProtocol
import SKSupport
import SourceKitD
struct InterfaceInfo {
var contents: String
}
extension SwiftLanguageServer {
public func openInterface(_ request: OpenInterfaceRequest) async throws -> InterfaceDetails? {
let uri = request.textDocument.uri
let moduleName = request.moduleName
let name = request.name
let symbol = request.symbolUSR
let interfaceFilePath = self.generatedInterfacesPath.appendingPathComponent("\(name).swiftinterface")
let interfaceDocURI = DocumentURI(interfaceFilePath)
// has interface already been generated
if let snapshot = self.documentManager.latestSnapshot(interfaceDocURI) {
return await self.interfaceDetails(request: request, uri: interfaceDocURI, snapshot: snapshot, symbol: symbol)
} else {
// generate interface
let interfaceInfo = try await self.openInterface(
request: request,
uri: uri,
name: moduleName,
interfaceURI: interfaceDocURI
)
do {
// write to file
try interfaceInfo.contents.write(to: interfaceFilePath, atomically: true, encoding: String.Encoding.utf8)
// store snapshot
let snapshot = try self.documentManager.open(
interfaceDocURI,
language: .swift,
version: 0,
text: interfaceInfo.contents
)
return await self.interfaceDetails(request: request, uri: interfaceDocURI, snapshot: snapshot, symbol: symbol)
} catch {
throw ResponseError.unknown(error.localizedDescription)
}
}
}
/// Open the Swift interface for a module.
///
/// - Parameters:
/// - request: The OpenInterfaceRequest.
/// - uri: The document whose compiler arguments should be used to generate the interface.
/// - name: The name of the module whose interface should be generated.
/// - interfaceURI: The file where the generated interface should be written.
private func openInterface(
request: OpenInterfaceRequest,
uri: DocumentURI,
name: String,
interfaceURI: DocumentURI
) async throws -> InterfaceInfo {
let keys = self.keys
let skreq = SKDRequestDictionary(sourcekitd: sourcekitd)
skreq[keys.request] = requests.editor_open_interface
skreq[keys.modulename] = name
if request.groupNames.count > 0 {
skreq[keys.groupname] = request.groupNames
}
skreq[keys.name] = interfaceURI.pseudoPath
skreq[keys.synthesizedextensions] = 1
if let compileCommand = await self.buildSettings(for: uri) {
skreq[keys.compilerargs] = compileCommand.compilerArgs
}
let dict = try await self.sourcekitd.send(skreq)
return InterfaceInfo(contents: dict[keys.sourcetext] ?? "")
}
private func interfaceDetails(
request: OpenInterfaceRequest,
uri: DocumentURI,
snapshot: DocumentSnapshot,
symbol: String?
) async -> InterfaceDetails {
do {
guard let symbol = symbol else {
return InterfaceDetails(uri: uri, position: nil)
}
let keys = self.keys
let skreq = SKDRequestDictionary(sourcekitd: sourcekitd)
skreq[keys.request] = requests.find_usr
skreq[keys.sourcefile] = uri.pseudoPath
skreq[keys.usr] = symbol
let dict = try await self.sourcekitd.send(skreq)
if let offset: Int = dict[keys.offset],
let position = snapshot.positionOf(utf8Offset: offset)
{
return InterfaceDetails(uri: uri, position: position)
} else {
return InterfaceDetails(uri: uri, position: nil)
}
} catch {
return InterfaceDetails(uri: uri, position: nil)
}
}
}