@@ -14,23 +14,161 @@ public import LanguageServerProtocol
1414
1515/// The log message notification is sent from a server to a client to ask the client to log a particular message in its console.
1616///
17- /// A `build/logMessage`` notification is similar to LSP's `window/logMessage``.
17+ /// A `build/logMessage`` notification is similar to LSP's `window/logMessage``, except for a few additions like id and originId .
1818public struct OnBuildLogMessageNotification : NotificationType {
1919 public static let method : String = " build/logMessage "
2020
2121 /// The message type.
2222 public var type : MessageType
2323
24+ /// The task id if any.
25+ public var task : TaskId ?
26+
27+ /// The request id that originated this notification.
28+ /// The originId field helps clients know which request originated a notification in case several requests are handled by the
29+ /// client at the same time. It will only be populated if the client defined it in the request that triggered this notification.
30+ public var originId : OriginId ?
31+
2432 /// The actual message.
2533 public var message : String
2634
27- /// If specified, allows grouping log messages that belong to the same originating task together instead of logging
28- /// them in chronological order in which they were produced.
35+ /// Extends BSPs log message grouping by explicitly starting and ending the log for a specific task ID.
36+ ///
37+ /// **(BSP Extension)***
2938 public var structure : StructuredLogKind ?
3039
31- public init ( type: MessageType , message: String , structure: StructuredLogKind ? ) {
40+ public init (
41+ type: MessageType ,
42+ task: TaskId ? = nil ,
43+ originId: OriginId ? = nil ,
44+ message: String ,
45+ structure: StructuredLogKind ? = nil
46+ ) {
3247 self . type = type
48+ self . task = task
49+ self . originId = originId
3350 self . message = message
3451 self . structure = structure
3552 }
3653}
54+
55+ public enum StructuredLogKind : Codable , Hashable , Sendable {
56+ case begin( StructuredLogBegin )
57+ case report( StructuredLogReport )
58+ case end( StructuredLogEnd )
59+
60+ public init ( from decoder: Decoder ) throws {
61+ if let begin = try ? StructuredLogBegin ( from: decoder) {
62+ self = . begin( begin)
63+ } else if let report = try ? StructuredLogReport ( from: decoder) {
64+ self = . report( report)
65+ } else if let end = try ? StructuredLogEnd ( from: decoder) {
66+ self = . end( end)
67+ } else {
68+ let context = DecodingError . Context (
69+ codingPath: decoder. codingPath,
70+ debugDescription: " Expected StructuredLogBegin, StructuredLogReport, or StructuredLogEnd "
71+ )
72+ throw DecodingError . dataCorrupted ( context)
73+ }
74+ }
75+
76+ public func encode( to encoder: Encoder ) throws {
77+ switch self {
78+ case . begin( let begin) :
79+ try begin. encode ( to: encoder)
80+ case . report( let report) :
81+ try report. encode ( to: encoder)
82+ case . end( let end) :
83+ try end. encode ( to: encoder)
84+ }
85+ }
86+ }
87+
88+ /// Indicates the beginning of a new task that may receive updates with `StructuredLogReport` or `StructuredLogEnd`
89+ /// payloads.
90+ public struct StructuredLogBegin : Codable , Hashable , Sendable {
91+ /// A succinct title that can be used to describe the task that started this structured.
92+ public var title : String
93+
94+ private enum CodingKeys : CodingKey {
95+ case kind
96+ case title
97+ }
98+
99+ public init ( title: String ) {
100+ self . title = title
101+ }
102+
103+ public init ( from decoder: any Decoder ) throws {
104+ let container = try decoder. container ( keyedBy: CodingKeys . self)
105+ guard try container. decode ( String . self, forKey: . kind) == " begin " else {
106+ throw DecodingError . dataCorruptedError (
107+ forKey: . kind,
108+ in: container,
109+ debugDescription: " Kind of StructuredLogBegin is not 'begin' "
110+ )
111+ }
112+
113+ self . title = try container. decode ( String . self, forKey: . title)
114+
115+ }
116+
117+ public func encode( to encoder: any Encoder ) throws {
118+ var container = encoder. container ( keyedBy: CodingKeys . self)
119+ try container. encode ( " begin " , forKey: . kind)
120+ try container. encode ( self . title, forKey: . title)
121+ }
122+ }
123+
124+ /// Adds a new log message to a structured log without ending it.
125+ public struct StructuredLogReport : Codable , Hashable , Sendable {
126+ private enum CodingKeys : CodingKey {
127+ case kind
128+ }
129+
130+ public init ( ) { }
131+
132+ public init ( from decoder: any Decoder ) throws {
133+ let container = try decoder. container ( keyedBy: CodingKeys . self)
134+ guard try container. decode ( String . self, forKey: . kind) == " report " else {
135+ throw DecodingError . dataCorruptedError (
136+ forKey: . kind,
137+ in: container,
138+ debugDescription: " Kind of StructuredLogReport is not 'report' "
139+ )
140+ }
141+ }
142+
143+ public func encode( to encoder: any Encoder ) throws {
144+ var container = encoder. container ( keyedBy: CodingKeys . self)
145+ try container. encode ( " report " , forKey: . kind)
146+ }
147+ }
148+
149+ /// Ends a structured log. No more `StructuredLogReport` updates should be sent for this task ID.
150+ ///
151+ /// The task ID may be re-used for new structured logs by beginning a new structured log for that task.
152+ public struct StructuredLogEnd : Codable , Hashable , Sendable {
153+ private enum CodingKeys : CodingKey {
154+ case kind
155+ }
156+
157+ public init ( ) { }
158+
159+ public init ( from decoder: any Decoder ) throws {
160+ let container = try decoder. container ( keyedBy: CodingKeys . self)
161+ guard try container. decode ( String . self, forKey: . kind) == " end " else {
162+ throw DecodingError . dataCorruptedError (
163+ forKey: . kind,
164+ in: container,
165+ debugDescription: " Kind of StructuredLogEnd is not 'end' "
166+ )
167+ }
168+ }
169+
170+ public func encode( to encoder: any Encoder ) throws {
171+ var container = encoder. container ( keyedBy: CodingKeys . self)
172+ try container. encode ( " end " , forKey: . kind)
173+ }
174+ }
0 commit comments