@@ -14,23 +14,161 @@ public import LanguageServerProtocol
14
14
15
15
/// The log message notification is sent from a server to a client to ask the client to log a particular message in its console.
16
16
///
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 .
18
18
public struct OnBuildLogMessageNotification : NotificationType {
19
19
public static let method : String = " build/logMessage "
20
20
21
21
/// The message type.
22
22
public var type : MessageType
23
23
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
+
24
32
/// The actual message.
25
33
public var message : String
26
34
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)***
29
38
public var structure : StructuredLogKind ?
30
39
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
+ ) {
32
47
self . type = type
48
+ self . task = task
49
+ self . originId = originId
33
50
self . message = message
34
51
self . structure = structure
35
52
}
36
53
}
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