Files
sourcekit-lsp/Sources/LanguageServerProtocol/Notifications/WorkDoneProgress.swift
2024-03-03 21:50:38 -08:00

225 lines
8.0 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
//
//===----------------------------------------------------------------------===//
public struct WorkDoneProgress: NotificationType, Hashable {
public static let method: String = "$/progress"
/// The progress token provided by the client or server.
public var token: ProgressToken
/// The progress data.
public var value: WorkDoneProgressKind
public init(token: ProgressToken, value: WorkDoneProgressKind) {
self.token = token
self.value = value
}
}
public enum WorkDoneProgressKind: Codable, Hashable, Sendable {
case begin(WorkDoneProgressBegin)
case report(WorkDoneProgressReport)
case end(WorkDoneProgressEnd)
public init(from decoder: Decoder) throws {
if let begin = try? WorkDoneProgressBegin(from: decoder) {
self = .begin(begin)
} else if let report = try? WorkDoneProgressReport(from: decoder) {
self = .report(report)
} else if let end = try? WorkDoneProgressEnd(from: decoder) {
self = .end(end)
} else {
let context = DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Expected WorkDoneProgressBegin, WorkDoneProgressReport, or WorkDoneProgressEnd"
)
throw DecodingError.dataCorrupted(context)
}
}
public func encode(to encoder: Encoder) throws {
switch self {
case .begin(let begin):
try begin.encode(to: encoder)
case .report(let report):
try report.encode(to: encoder)
case .end(let end):
try end.encode(to: encoder)
}
}
}
public struct WorkDoneProgressBegin: Codable, Hashable, Sendable {
/// Mandatory title of the progress operation. Used to briefly inform about
/// the kind of operation being performed.
///
/// Examples: "Indexing" or "Linking dependencies".
public var title: String
/// Controls if a cancel button should show to allow the user to cancel the
/// long running operation. Clients that don't support cancellation are
/// allowed to ignore the setting.
public var cancellable: Bool?
/// Optional, more detailed associated progress message. Contains
/// complementary information to the `title`.
///
/// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
/// If unset, the previous progress message (if any) is still valid.
public var message: String?
/// Optional progress percentage to display (value 100 is considered 100%).
/// If not provided infinite progress is assumed and clients are allowed
/// to ignore the `percentage` value in subsequent in report notifications.
///
/// The value should be steadily rising. Clients are free to ignore values
/// that are not following this rule. The value range is [0, 100]
public var percentage: Int?
public init(title: String, cancellable: Bool? = nil, message: String? = nil, percentage: Int? = nil) {
self.title = title
self.cancellable = cancellable
self.message = message
self.percentage = percentage
}
enum CodingKeys: CodingKey {
case kind
case title
case cancellable
case message
case percentage
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let kind = try container.decode(String.self, forKey: .kind)
guard kind == "begin" else {
throw DecodingError.dataCorruptedError(
forKey: .kind,
in: container,
debugDescription: "Kind of WorkDoneProgressBegin is not 'begin'"
)
}
self.title = try container.decode(String.self, forKey: .title)
self.cancellable = try container.decodeIfPresent(Bool.self, forKey: .cancellable)
self.message = try container.decodeIfPresent(String.self, forKey: .message)
self.percentage = try container.decodeIfPresent(Int.self, forKey: .percentage)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode("begin", forKey: .kind)
try container.encode(self.title, forKey: .title)
try container.encodeIfPresent(self.cancellable, forKey: .cancellable)
try container.encodeIfPresent(self.message, forKey: .message)
try container.encodeIfPresent(self.percentage, forKey: .percentage)
}
}
public struct WorkDoneProgressReport: Codable, Hashable, Sendable {
/// Controls enablement state of a cancel button. This property is only valid
/// if a cancel button got requested in the `WorkDoneProgressBegin` payload.
///
/// Clients that don't support cancellation or don't support control the
/// button's enablement state are allowed to ignore the setting.
public var cancellable: Bool?
/// Optional, more detailed associated progress message. Contains
/// complementary information to the `title`.
///
/// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
/// If unset, the previous progress message (if any) is still valid.
public var message: String?
/// Optional progress percentage to display (value 100 is considered 100%).
/// If not provided infinite progress is assumed and clients are allowed
/// to ignore the `percentage` value in subsequent in report notifications.
///
/// The value should be steadily rising. Clients are free to ignore values
/// that are not following this rule. The value range is [0, 100]
public var percentage: Int?
public init(cancellable: Bool? = nil, message: String? = nil, percentage: Int? = nil) {
self.cancellable = cancellable
self.message = message
self.percentage = percentage
}
enum CodingKeys: CodingKey {
case kind
case cancellable
case message
case percentage
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let kind = try container.decode(String.self, forKey: .kind)
guard kind == "report" else {
throw DecodingError.dataCorruptedError(
forKey: .kind,
in: container,
debugDescription: "Kind of WorkDoneProgressReport is not 'report'"
)
}
self.cancellable = try container.decodeIfPresent(Bool.self, forKey: .cancellable)
self.message = try container.decodeIfPresent(String.self, forKey: .message)
self.percentage = try container.decodeIfPresent(Int.self, forKey: .percentage)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode("report", forKey: .kind)
try container.encodeIfPresent(self.cancellable, forKey: .cancellable)
try container.encodeIfPresent(self.message, forKey: .message)
try container.encodeIfPresent(self.percentage, forKey: .percentage)
}
}
public struct WorkDoneProgressEnd: Codable, Hashable, Sendable {
/// Optional, a final message indicating to for example indicate the outcome
/// of the operation.
public var message: String?
public init(message: String? = nil) {
self.message = message
}
enum CodingKeys: CodingKey {
case kind
case message
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let kind = try container.decode(String.self, forKey: .kind)
guard kind == "end" else {
throw DecodingError.dataCorruptedError(
forKey: .kind,
in: container,
debugDescription: "Kind of WorkDoneProgressReport is not 'end'"
)
}
self.message = try container.decodeIfPresent(String.self, forKey: .message)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode("end", forKey: .kind)
try container.encodeIfPresent(self.message, forKey: .message)
}
}