├── .gitignore ├── .swift-version ├── Package.swift ├── README.md ├── Sources └── DebugAdapterProtocol │ ├── Adapter │ ├── DebugAdapter.swift │ └── ProtocolMessageHandler.swift │ ├── Logger │ └── Logger.swift │ ├── Protocol │ ├── Errors.swift │ ├── Messages │ │ ├── Events.swift │ │ ├── ProtocolMessage.swift │ │ ├── Requests.swift │ │ └── Responses.swift │ └── Types.swift │ └── Utils │ ├── CodableExtensions.swift │ └── MirroredEnum.swift └── Tests ├── DebugAdapterProtocolTests ├── DebugAdapterProtocolTests.swift └── XCTestManifests.swift └── LinuxMain.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | /.idea 6 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0.2 2 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "DebugAdapterProtocol", 6 | products: [ 7 | .library( 8 | name: "DebugAdapterProtocol", 9 | targets: ["DebugAdapterProtocol"]), 10 | ], 11 | dependencies: [ 12 | ], 13 | targets: [ 14 | .target( 15 | name: "DebugAdapterProtocol", 16 | dependencies: []), 17 | .testTarget( 18 | name: "DebugAdapterProtocolTests", 19 | dependencies: ["DebugAdapterProtocol"]), 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftDAP 2 | 3 | Swift SDK for Microsoft's [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol) 4 | 5 | **Note:** Still in alpha development - features are incomplete! 6 | 7 | ## User Guide 8 | 9 | This is the most basic way to use the provided `DebugAdapter`. 10 | `.start()` tells the adapter to start listening to incoming DAP messages from the `input` passed into the `DebugAdapter`'s constructor. 11 | 12 | ```swift 13 | import DebugAdapterProtocol 14 | 15 | let input = FileHandle.standardInput 16 | let output = FileHandle.standardOutput 17 | 18 | DebugAdapter(input, output).start() 19 | ``` 20 | 21 | At this point, the only thing it'll do is listen to DAP messages and parse them, but it does not do anything about them. 22 | So, you'll have to implement a `ProtocolMessageHandler` to handle these messages. 23 | 24 | ```swift 25 | class ExampleHandler: ProtocolMessageHandler { 26 | func handle(message: ProtocolMessage) { 27 | // do something about the incoming message 28 | } 29 | } 30 | ``` 31 | 32 | You can pass a factory method to create your message handler into the `DebugAdapter` as such: 33 | 34 | ```swift 35 | DebugAdapter(input, output) 36 | .withMessageHandler { sender in ExampleHandler(...) } 37 | .start() 38 | ``` 39 | 40 | The `sender` argument in the factory method is a `ProtocolMessageSender`, which is basically a function that takes in a 41 | `ProtocolMessage` and sends it via the `DebugAdapter`. You'll probably need this in your `ProtocolMessageHandler` if you 42 | want to respond to requests. 43 | 44 | ### Full Example 45 | 46 | ```swift 47 | import DebugAdapterProtocol 48 | 49 | class MessageHandler: ProtocolMessageHandler { 50 | let send: ProtocolMessageSender 51 | 52 | init(_ send: ProtocolMessageSender) { 53 | self.send = send 54 | } 55 | 56 | func handle(message: ProtocolMessage) { 57 | switch message { 58 | case .request(seq: let seq, request: let request): 59 | send(.response(seq: seq, response: /* ... */)) 60 | default: 61 | break 62 | } 63 | } 64 | } 65 | 66 | main() { 67 | DebugAdapter(input, output) 68 | .withMessageHandler { sender in MessageHandler(sender) } 69 | .start() 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Adapter/DebugAdapter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias ProtocolMessageSender = (ProtocolMessage) -> Void 4 | 5 | public class DebugAdapter { 6 | private let logger: Logger? 7 | private let input: FileHandle 8 | private let output: FileHandle 9 | private var buffer: Data 10 | private var contentLength: Int 11 | private var messageHandler: ProtocolMessageHandler? 12 | 13 | public init(_ input: FileHandle = FileHandle.standardInput, 14 | _ output: FileHandle = FileHandle.standardOutput, 15 | _ logger: Logger? = nil) { 16 | self.logger = logger 17 | self.input = input 18 | self.output = output 19 | self.buffer = Data() 20 | self.contentLength = -1 21 | } 22 | 23 | public func withMessageHandler(_ messageHandlerFactory: (@escaping ProtocolMessageSender) -> ProtocolMessageHandler) 24 | -> DebugAdapter { 25 | self.messageHandler = messageHandlerFactory(self.send) 26 | return self 27 | } 28 | 29 | private func send(_ message: ProtocolMessage) { 30 | let encoder = JSONEncoder() 31 | let data = try! encoder.encode(message) 32 | let header = "Content-Length: \(data.count)\r\n\r\n".data(using: .utf8)! 33 | self.output.write(header + data) 34 | log("Sent: \(String(data: data, encoding: .utf8)!)") 35 | } 36 | 37 | private func handleData(_ data: Data) { 38 | log("Received: \(data)", level: .debug) 39 | self.buffer.append(data) 40 | while true { 41 | if self.contentLength >= 0 { 42 | log("Reading \(contentLength) bytes of data", level: .debug) 43 | if self.buffer.count >= self.contentLength { 44 | guard let message = String(data: buffer.subdata(in: 0.. 0 { 51 | log("Decoding message", level: .debug) 52 | do { 53 | let decoder = JSONDecoder() 54 | let messageData = try decoder.decode(ProtocolMessage.self, from: message.data(using: .utf8)!) 55 | log("Decode successful", level: .debug) 56 | self.messageHandler?.handle(message: messageData) 57 | } catch let error { 58 | log("Decoding message failed: \(error)", level: .error) 59 | let err = ResponseMessage.error(RequestResult(requestSeq: 0, success: false, message: "\(error)")) 60 | self.send(.response(seq: 0, response: err)) 61 | } 62 | } 63 | continue 64 | } 65 | } else { 66 | if let newline = self.buffer.range(of: "\r\n".data(using: .utf8)!) { 67 | let range: Range = 0.. Int { 9 | switch self { 10 | case .error: 11 | return 3 12 | case .warning: 13 | return 2 14 | case .info: 15 | return 1 16 | case .debug: 17 | return 0 18 | } 19 | } 20 | 21 | public static func < (lhs: LoggingLevel, rhs: LoggingLevel) -> Bool { 22 | return lhs.asInteger() < rhs.asInteger() 23 | } 24 | } 25 | 26 | public protocol Logger { 27 | func log(_ message: CustomStringConvertible) 28 | func log(_ message: CustomStringConvertible, level: LoggingLevel) 29 | } 30 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Errors.swift: -------------------------------------------------------------------------------- 1 | public enum DAPError: Error, Equatable, CustomStringConvertible { 2 | case unsupportedRequest(command: String) 3 | case unsupportedResponse(command: String) 4 | case unsupportedEvent(event: String) 5 | 6 | public var description: String { 7 | switch self { 8 | case .unsupportedRequest(let command): 9 | return "Request \"\(command)\" is not supported" 10 | case .unsupportedResponse(let command): 11 | return "Response \"\(command)\" is not supported" 12 | case .unsupportedEvent(let event): 13 | return "Event \"\(event)\" is not supported" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Messages/Events.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum EventMessage: MirroredEnum, Codable { 4 | private enum CodingKeys: String, CodingKey { 5 | case event 6 | case body 7 | } 8 | 9 | case breakpoint(BreakpointEvent?) 10 | case initialized 11 | case continued(ContinuedEvent) 12 | case exited(ExitedEvent) 13 | case stopped(StoppedEvent) 14 | case terminated(TerminatedEvent?) 15 | 16 | public init(from decoder: Decoder) throws { 17 | let container = try decoder.container(keyedBy: CodingKeys.self) 18 | let event = try container.decode(String.self, forKey: .event) 19 | switch event { 20 | case "breakpoint": self = .breakpoint(try container.decode(BreakpointEvent.self, forKey: .body)) 21 | case "initialized": self = .initialized 22 | case "continued": self = .continued(try container.decode(ContinuedEvent.self, forKey: .body)) 23 | case "exited": self = .exited(try container.decode(ExitedEvent.self, forKey: .body)) 24 | case "stopped": self = .stopped(try container.decode(StoppedEvent.self, forKey: .body)) 25 | case "terminated": self = .terminated(try container.decode(TerminatedEvent.self, forKey: .body)) 26 | default: throw DAPError.unsupportedEvent(event: event) 27 | } 28 | } 29 | 30 | public func encode(to encoder: Encoder) throws { 31 | var container = encoder.container(keyedBy: CodingKeys.self) 32 | try container.encode(self.label, forKey: .event) 33 | switch self { 34 | case .breakpoint(let event): 35 | try container.encode(event, forKey: .body) 36 | case .continued(let event): 37 | try container.encode(event, forKey: .body) 38 | case .exited(let event): 39 | try container.encode(event, forKey: .body) 40 | case .stopped(let event): 41 | try container.encode(event, forKey: .body) 42 | case .terminated(let event): 43 | try container.encode(event, forKey: .body) 44 | case .initialized: 45 | break 46 | } 47 | } 48 | } 49 | 50 | public enum BreakpointReason: String, Codable { 51 | case changed, new, removed 52 | } 53 | 54 | public struct BreakpointEvent: Codable { 55 | public var reason: BreakpointReason 56 | 57 | public init(reason: BreakpointReason) { 58 | self.reason = reason 59 | } 60 | } 61 | 62 | public enum StopReason: String, Codable { 63 | case step 64 | case breakpoint 65 | case exception 66 | case pause 67 | case entry 68 | case goto 69 | case functionBreakpoint = "function breakpoint" 70 | case dataBreakpoint = "data breakpoint" 71 | } 72 | 73 | public struct StoppedEvent: Codable { 74 | public var reason: StopReason 75 | public var description: String? 76 | public var threadId: Int? 77 | public var preserveFocusHint: Bool? 78 | public var text: String? 79 | public var allThreadsStopped: Bool? 80 | 81 | public init(reason: StopReason, 82 | description: String? = nil, 83 | threadId: Int? = nil, 84 | preserveFocusHint: Bool? = nil, 85 | text: String? = nil, 86 | allThreadsStopped: Bool? = nil) { 87 | self.reason = reason 88 | self.description = description 89 | self.threadId = threadId 90 | self.preserveFocusHint = preserveFocusHint 91 | self.text = text 92 | self.allThreadsStopped = allThreadsStopped 93 | } 94 | } 95 | 96 | public struct ContinuedEvent: Codable { 97 | public var threadId: Int 98 | public var allThreadsContinued: Bool? 99 | 100 | public init(threadId: Int, allThreadsContinued: Bool? = nil) { 101 | self.threadId = threadId 102 | self.allThreadsContinued = allThreadsContinued 103 | } 104 | } 105 | 106 | public struct ExitedEvent: Codable { 107 | public var exitCode: Int 108 | 109 | public init(exitCode: Int) { 110 | self.exitCode = exitCode 111 | } 112 | } 113 | 114 | public struct TerminatedEvent: Codable { 115 | // public var restart: Any 116 | public init() { 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Messages/ProtocolMessage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ProtocolMessage: MirroredEnum, Codable { 4 | private enum CodingKeys: String, CodingKey { 5 | case seq 6 | case type 7 | } 8 | 9 | case request(seq: Int, request: RequestMessage) 10 | case response(seq: Int, response: ResponseMessage) 11 | case event(seq: Int, event: EventMessage) 12 | 13 | public init(from decoder: Decoder) throws { 14 | let container = try decoder.container(keyedBy: CodingKeys.self) 15 | let seq = try container.decode(Int.self, forKey: .seq) 16 | let type = try container.decode(String.self, forKey: .type) 17 | switch type { 18 | case "request": self = .request(seq: seq, request: try RequestMessage.init(from: decoder)) 19 | case "response": self = .response(seq: seq, response: try ResponseMessage.init(from: decoder)) 20 | case "event": self = .event(seq: seq, event: try EventMessage.init(from: decoder)) 21 | default: fatalError("Message type \"\(type)\" not supported") 22 | } 23 | } 24 | 25 | public func encode(to encoder: Encoder) throws { 26 | var container = encoder.container(keyedBy: CodingKeys.self) 27 | try container.encode(self.label, forKey: .type) 28 | switch self { 29 | case .request(let seq, let message as Encodable), 30 | .response(let seq, let message as Encodable), 31 | .event(let seq, let message as Encodable): 32 | try container.encode(seq, forKey: .seq) 33 | try message.encode(to: encoder) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Messages/Requests.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum RequestMessage: MirroredEnum, Codable { 4 | private enum CodingKeys: String, CodingKey { 5 | case command 6 | case arguments 7 | } 8 | 9 | case goto(GotoArguments?) 10 | case next(NextArguments?) 11 | case stepIn(StepInArguments) 12 | case stepOut(StepOutArguments) 13 | case stepBack(StepBackArguments) 14 | case `continue`(ContinueArguments) 15 | case reverseContinue(ReverseContinueArguments) 16 | case initialize(InitializeArguments) 17 | case launch(_ args: LaunchArguments) 18 | case setBreakpoints(SetBreakpointsArguments) 19 | case setFunctionBreakpoints(SetFunctionBreakpointsArguments) 20 | case setExceptionBreakpoints(SetExceptionBreakpointsArguments) 21 | case setDataBreakpoints(SetDataBreakpointsArguments) 22 | case configurationDone 23 | case threads 24 | case scopes(ScopesArguments) 25 | case variables(VariablesArguments) 26 | case stackTrace(StackTraceArguments) 27 | case disconnect(DisconnectArguments?) 28 | 29 | public init(from decoder: Decoder) throws { 30 | let container = try decoder.container(keyedBy: CodingKeys.self) 31 | let command = try container.decode(String.self, forKey: .command) 32 | switch command { 33 | case "goto": self = .goto(try container.decodeIfPresent(GotoArguments.self, forKey: .arguments)) 34 | case "next": self = .next(try container.decodeIfPresent(NextArguments.self, forKey: .arguments)) 35 | case "stepIn": self = .stepIn(try container.decode(StepInArguments.self, forKey: .arguments)) 36 | case "stepBack": self = .stepBack(try container.decode(StepBackArguments.self, forKey: .arguments)) 37 | case "stepOut": self = .stepOut(try container.decode(StepOutArguments.self, forKey: .arguments)) 38 | case "continue": self = .continue(try container.decode(ContinueArguments.self, forKey: .arguments)) 39 | case "reverseContinue": 40 | self = .reverseContinue(try container.decode(ReverseContinueArguments.self, forKey: .arguments)) 41 | case "initialize": self = .initialize(try container.decode(InitializeArguments.self, forKey: .arguments)) 42 | case "launch": self = .launch(try container.decode(LaunchArguments.self, forKey: .arguments)) 43 | case "setBreakpoints": 44 | self = .setBreakpoints(try container.decode(SetBreakpointsArguments.self, forKey: .arguments)) 45 | case "setFunctionBreakpoints": 46 | self = .setFunctionBreakpoints(try container.decode(SetFunctionBreakpointsArguments.self, forKey: .arguments)) 47 | case "setExceptionBreakpoints": 48 | self = .setExceptionBreakpoints(try container.decode(SetExceptionBreakpointsArguments.self, forKey: .arguments)) 49 | case "setDataBreakpoints": 50 | self = .setDataBreakpoints(try container.decode(SetDataBreakpointsArguments.self, forKey: .arguments)) 51 | case "stackTrace": self = .stackTrace(try container.decode(StackTraceArguments.self, forKey: .arguments)) 52 | case "configurationDone": self = .configurationDone 53 | case "threads": self = .threads 54 | case "scopes": self = .scopes(try container.decode(ScopesArguments.self, forKey: .arguments)) 55 | case "variables": self = .variables(try container.decode(VariablesArguments.self, forKey: .arguments)) 56 | case "disconnect": self = .disconnect(try container.decodeIfPresent(DisconnectArguments.self, forKey: .arguments)) 57 | default: throw DAPError.unsupportedRequest(command: command) 58 | } 59 | } 60 | 61 | public func encode(to encoder: Encoder) throws { 62 | var container = encoder.container(keyedBy: CodingKeys.self) 63 | try container.encode(self.label, forKey: .command) 64 | switch self { 65 | case .goto(let args): 66 | try container.encode(args, forKey: .arguments) 67 | case .next(let args): 68 | try container.encode(args, forKey: .arguments) 69 | case .stepIn(let args): 70 | try container.encode(args, forKey: .arguments) 71 | case .stepBack(let args): 72 | try container.encode(args, forKey: .arguments) 73 | case .stepOut(let args): 74 | try container.encode(args, forKey: .arguments) 75 | case .continue(let args): 76 | try container.encode(args, forKey: .arguments) 77 | case .reverseContinue(let args): 78 | try container.encode(args, forKey: .arguments) 79 | case .initialize(let args): 80 | try container.encode(args, forKey: .arguments) 81 | case .launch(let args): 82 | try container.encode(args, forKey: .arguments) 83 | case .setBreakpoints(let args): 84 | try container.encode(args, forKey: .arguments) 85 | case .setFunctionBreakpoints(let args): 86 | try container.encode(args, forKey: .arguments) 87 | case .setExceptionBreakpoints(let args): 88 | try container.encode(args, forKey: .arguments) 89 | case .setDataBreakpoints(let args): 90 | try container.encode(args, forKey: .arguments) 91 | case .stackTrace(let args): 92 | try container.encode(args, forKey: .arguments) 93 | case .scopes(let args): 94 | try container.encode(args, forKey: .arguments) 95 | case .variables(let args): 96 | try container.encode(args, forKey: .arguments) 97 | case .disconnect(let args): 98 | try container.encode(args, forKey: .arguments) 99 | case .configurationDone, 100 | .threads: 101 | break 102 | } 103 | } 104 | } 105 | 106 | public struct GotoArguments: Codable { 107 | public var threadId: Int 108 | public var targetId: Int 109 | 110 | public init(threadId: Int, targetId: Int) { 111 | self.threadId = threadId 112 | self.targetId = targetId 113 | } 114 | } 115 | 116 | public struct NextArguments: Codable { 117 | public var threadId: Int 118 | public var granularity: SteppingGranularity? 119 | 120 | public init(threadId: Int, granularity: SteppingGranularity? = nil) { 121 | self.threadId = threadId 122 | self.granularity = granularity 123 | } 124 | } 125 | 126 | public struct LaunchArguments: Codable { 127 | enum CodingKeys: String, CodingKey { 128 | case noDebug, __restart 129 | } 130 | 131 | public var noDebug: Bool? 132 | public var __restart: String? 133 | public var extraArgs: [String: Any] 134 | 135 | public init(noDebug: Bool? = nil, __restart: String? = nil, extraArgs: [String: Any] = [:]) { 136 | self.noDebug = noDebug 137 | self.__restart = __restart 138 | self.extraArgs = extraArgs 139 | } 140 | 141 | public init(from decoder: Decoder) throws { 142 | let container = try decoder.container(keyedBy: CodingKeys.self) 143 | self.noDebug = try container.decodeIfPresent(Bool.self, forKey: .noDebug) 144 | self.__restart = try container.decodeIfPresent(String.self, forKey: .__restart) 145 | let extrasContainer = try decoder.container(keyedBy: GenericCodingKeys.self) 146 | self.extraArgs = try extrasContainer.decode([String: Any].self) 147 | } 148 | 149 | public func encode(to encoder: Encoder) throws { 150 | var container = encoder.container(keyedBy: CodingKeys.self) 151 | try container.encode(self.noDebug, forKey: .noDebug) 152 | try container.encode(self.__restart, forKey: .__restart) 153 | var extraContainer = encoder.container(keyedBy: GenericCodingKeys.self) 154 | try extraContainer.encode(self.extraArgs) 155 | } 156 | } 157 | 158 | public struct SetBreakpointsArguments: Codable { 159 | public var source: Source 160 | public var breakpoints: [SourceBreakpoint]? 161 | public var lines: [Int]? 162 | public var sourceModified: Bool? 163 | 164 | public init(source: Source, 165 | breakpoints: [SourceBreakpoint]? = nil, 166 | lines: [Int]? = nil, 167 | sourceModified: Bool? = nil) { 168 | self.source = source 169 | self.breakpoints = breakpoints 170 | self.lines = lines 171 | self.sourceModified = sourceModified 172 | } 173 | } 174 | 175 | public struct SetFunctionBreakpointsArguments: Codable { 176 | public var breakpoints: [FunctionBreakpoint]? 177 | 178 | public init(breakpoints: [FunctionBreakpoint]? = nil) { 179 | self.breakpoints = breakpoints 180 | } 181 | } 182 | 183 | public struct SetExceptionBreakpointsArguments: Codable { 184 | public var filters: [String] 185 | public var exceptionOptions: [ExceptionOptions]? 186 | 187 | public init(filters: [String], exceptionOptions: [ExceptionOptions]? = nil) { 188 | self.filters = filters 189 | self.exceptionOptions = exceptionOptions 190 | } 191 | } 192 | 193 | public struct SetDataBreakpointsArguments: Codable { 194 | public var breakpoints: [DataBreakpoint] 195 | 196 | public init(breakpoints: [DataBreakpoint]) { 197 | self.breakpoints = breakpoints 198 | } 199 | } 200 | 201 | public struct InitializeArguments: Codable { 202 | public var clientID: String? 203 | public var clientName: String? 204 | public var adapterID: String 205 | public var locale: String? 206 | public var linesStartAt1: Bool? 207 | public var columnsStartAt1: Bool? 208 | public var pathFormat: String? 209 | public var supportsVariableType: Bool? 210 | public var supportsVariablePaging: Bool? 211 | public var supportsRunInTerminalRequest: Bool? 212 | public var supportsMemoryReferences: Bool? 213 | public var supportsProgressReporting: Bool? 214 | 215 | public init(clientID: String? = nil, 216 | clientName: String? = nil, 217 | adapterID: String, 218 | locale: String? = nil, 219 | linesStartAt1: Bool? = nil, 220 | columnsStartAt1: Bool? = nil, 221 | pathFormat: String? = nil, 222 | supportsVariableType: Bool? = nil, 223 | supportsVariablePaging: Bool? = nil, 224 | supportsRunInTerminalRequest: Bool? = nil, 225 | supportsMemoryReferences: Bool? = nil, 226 | supportsProgressReporting: Bool? = nil) { 227 | self.clientID = clientID 228 | self.clientName = clientName 229 | self.adapterID = adapterID 230 | self.locale = locale 231 | self.linesStartAt1 = linesStartAt1 232 | self.columnsStartAt1 = columnsStartAt1 233 | self.pathFormat = pathFormat 234 | self.supportsVariableType = supportsVariableType 235 | self.supportsVariablePaging = supportsVariablePaging 236 | self.supportsRunInTerminalRequest = supportsRunInTerminalRequest 237 | self.supportsMemoryReferences = supportsMemoryReferences 238 | self.supportsProgressReporting = supportsProgressReporting 239 | } 240 | } 241 | 242 | public struct StackTraceArguments: Codable { 243 | public var threadId: Int 244 | public var startFrame: Int? 245 | public var levels: Int? 246 | public var format: StackFrameFormat? 247 | 248 | public init(threadId: Int, 249 | startFrame: Int? = nil, 250 | levels: Int? = nil, 251 | format: StackFrameFormat? = nil) { 252 | self.threadId = threadId 253 | self.startFrame = startFrame 254 | self.levels = levels 255 | self.format = format 256 | } 257 | } 258 | 259 | public struct ScopesArguments: Codable { 260 | public var frameId: Int 261 | 262 | public init(frameId: Int) { 263 | self.frameId = frameId 264 | } 265 | } 266 | 267 | public enum VariableFilter: String, Codable { 268 | case indexed, named 269 | } 270 | 271 | public struct VariablesArguments: Codable { 272 | public var variablesReference: Int 273 | public var filter: VariableFilter? 274 | public var start: Int? 275 | public var count: Int? 276 | public var format: ValueFormat? 277 | 278 | public init(variablesReference: Int, 279 | filter: VariableFilter? = nil, 280 | start: Int? = nil, 281 | count: Int? = nil, 282 | format: ValueFormat? = nil) { 283 | self.variablesReference = variablesReference 284 | self.filter = filter 285 | self.start = start 286 | self.count = count 287 | self.format = format 288 | } 289 | } 290 | 291 | public struct DisconnectArguments: Codable { 292 | public var restart: Bool? 293 | public var terminateDebuggee: Bool? 294 | 295 | public init(restart: Bool? = nil, terminateDebuggee: Bool? = nil) { 296 | self.restart = restart 297 | self.terminateDebuggee = terminateDebuggee 298 | } 299 | } 300 | 301 | public struct ContinueArguments: Codable { 302 | public var threadId: Int 303 | 304 | public init(threadId: Int) { 305 | self.threadId = threadId 306 | } 307 | } 308 | 309 | public struct ReverseContinueArguments: Codable { 310 | public var threadId: Int 311 | 312 | public init(threadId: Int) { 313 | self.threadId = threadId 314 | } 315 | } 316 | 317 | public struct StepInArguments: Codable { 318 | public var threadId: Int 319 | public var targetId: Int? 320 | public var granularity: SteppingGranularity? 321 | 322 | public init(threadId: Int, targetId: Int? = nil, granularity: SteppingGranularity? = nil) { 323 | self.threadId = threadId 324 | self.targetId = targetId 325 | self.granularity = granularity 326 | } 327 | } 328 | 329 | public struct StepOutArguments: Codable { 330 | public var threadId: Int 331 | public var granularity: SteppingGranularity? 332 | 333 | public init(threadId: Int, granularity: SteppingGranularity? = nil) { 334 | self.threadId = threadId 335 | self.granularity = granularity 336 | } 337 | } 338 | 339 | public struct StepBackArguments: Codable { 340 | public var threadId: Int 341 | public var granularity: SteppingGranularity? 342 | 343 | public init(threadId: Int, granularity: SteppingGranularity? = nil) { 344 | self.threadId = threadId 345 | self.granularity = granularity 346 | } 347 | } -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Messages/Responses.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ResponseMessage: MirroredEnum, Codable { 4 | private enum CodingKeys: String, CodingKey { 5 | case command 6 | case body 7 | } 8 | 9 | case goto(RequestResult) 10 | case next(RequestResult) 11 | case stepIn(RequestResult) 12 | case stepOut(RequestResult) 13 | case stepBack(RequestResult) 14 | case `continue`(RequestResult, ContinueResponse) 15 | case reverseContinue(RequestResult) 16 | case error(RequestResult) 17 | case initialize(RequestResult, Capabilities) 18 | case launch(RequestResult) 19 | case setBreakpoints(RequestResult, SetBreakpointsResponse) 20 | case setFunctionBreakpoints(RequestResult, SetFunctionBreakpointsResponse) 21 | case setExceptionBreakpoints(RequestResult) 22 | case setDataBreakpoints(RequestResult, SetDataBreakpointsResponse) 23 | case configurationDone(RequestResult) 24 | case threads(RequestResult, ThreadsResponse) 25 | case scopes(RequestResult, ScopesResponse) 26 | case variables(RequestResult, VariablesResponse) 27 | case stackTrace(RequestResult, StackTraceResponse) 28 | case disconnect(RequestResult) 29 | 30 | public init(from decoder: Decoder) throws { 31 | let container = try decoder.container(keyedBy: CodingKeys.self) 32 | let command = try container.decode(String.self, forKey: .command) 33 | let result = try RequestResult.init(from: decoder) 34 | switch command { 35 | case "goto": self = .goto(result) 36 | case "next": self = .next(result) 37 | case "stepIn": self = .stepIn(result) 38 | case "stepOut": self = .stepOut(result) 39 | case "stepBack": self = .stepIn(result) 40 | case "error": self = .error(result) 41 | case "continue": self = .continue(result, try container.decode(ContinueResponse.self, forKey: .body)) 42 | case "reverseContinue": self = .reverseContinue(result) 43 | case "initialize": self = .initialize(result, try container.decode(Capabilities.self, forKey: .body)) 44 | case "launch": self = .launch(result) 45 | case "setBreakpoints": 46 | self = .setBreakpoints(result, try container.decode(SetBreakpointsResponse.self, forKey: .body)) 47 | case "setFunctionBreakpoints": 48 | self = .setFunctionBreakpoints(result, try container.decode(SetFunctionBreakpointsResponse.self, forKey: .body)) 49 | case "setDataBreakpoints": 50 | self = .setDataBreakpoints(result, try container.decode(SetDataBreakpointsResponse.self, forKey: .body)) 51 | case "setExceptionBreakpoints": 52 | self = .setExceptionBreakpoints(result) 53 | case "configurationDone": 54 | self = .configurationDone(result) 55 | case "threads": 56 | self = .threads(result, try container.decode(ThreadsResponse.self, forKey: .body)) 57 | case "stackTrace": 58 | self = .stackTrace(result, try container.decode(StackTraceResponse.self, forKey: .body)) 59 | case "scopes": 60 | self = .scopes(result, try container.decode(ScopesResponse.self, forKey: .body)) 61 | case "variables": 62 | self = .variables(result, try container.decode(VariablesResponse.self, forKey: .body)) 63 | case "disconnect": 64 | self = .disconnect(result) 65 | default: throw DAPError.unsupportedResponse(command: command) 66 | } 67 | } 68 | 69 | public func encode(to encoder: Encoder) throws { 70 | var container = encoder.container(keyedBy: CodingKeys.self) 71 | try container.encode(self.label, forKey: .command) 72 | switch self { 73 | case .continue(let result, let body): 74 | try result.encode(to: encoder) 75 | try container.encode(body, forKey: .body) 76 | 77 | case .initialize(let result, let body): 78 | try result.encode(to: encoder) 79 | try container.encode(body, forKey: .body) 80 | 81 | case .setBreakpoints(let result, let body): 82 | try result.encode(to: encoder) 83 | try container.encode(body, forKey: .body) 84 | 85 | case .setFunctionBreakpoints(let result, let body): 86 | try result.encode(to: encoder) 87 | try container.encode(body, forKey: .body) 88 | 89 | case .setDataBreakpoints(let result, let body): 90 | try result.encode(to: encoder) 91 | try container.encode(body, forKey: .body) 92 | 93 | case .threads(let result, let body): 94 | try result.encode(to: encoder) 95 | try container.encode(body, forKey: .body) 96 | 97 | case .scopes(let result, let body): 98 | try result.encode(to: encoder) 99 | try container.encode(body, forKey: .body) 100 | 101 | case .stackTrace(let result, let body): 102 | try result.encode(to: encoder) 103 | try container.encode(body, forKey: .body) 104 | 105 | case .variables(let result, let body): 106 | try result.encode(to: encoder) 107 | try container.encode(body, forKey: .body) 108 | 109 | case .setExceptionBreakpoints(let result), 110 | .configurationDone(let result), 111 | .goto(let result), 112 | .next(let result), 113 | .stepIn(let result), 114 | .stepOut(let result), 115 | .stepBack(let result), 116 | .reverseContinue(let result), 117 | .error(let result), 118 | .launch(let result), 119 | .disconnect(let result): 120 | try result.encode(to: encoder) 121 | } 122 | } 123 | } 124 | 125 | public struct RequestResult: Codable { 126 | public var requestSeq: Int 127 | public var success: Bool 128 | public var message: String? 129 | 130 | private enum CodingKeys: String, CodingKey { 131 | case requestSeq = "request_seq" 132 | case success 133 | case message 134 | } 135 | 136 | public init(requestSeq: Int, success: Bool, message: String? = nil) { 137 | self.requestSeq = requestSeq 138 | self.success = success 139 | self.message = message 140 | } 141 | } 142 | 143 | public struct Capabilities: Codable { 144 | public var supportsConfigurationDoneRequest: Bool? 145 | public var supportsFunctionBreakpoints: Bool? 146 | public var supportsConditionalBreakpoints: Bool? 147 | public var supportsHitConditionalBreakpoints: Bool? 148 | public var supportsEvaluateForHovers: Bool? 149 | public var exceptionBreakpointFilters: [ExceptionBreakpointsFilter]? 150 | public var supportsStepBack: Bool? 151 | public var supportsSetVariable: Bool? 152 | public var supportsRestartFrame: Bool? 153 | public var supportsGotoTargetsRequest: Bool? 154 | public var supportsStepInTargetsRequest: Bool? 155 | public var supportsCompletionsRequest: Bool? 156 | public var completionTriggerCharacters: [String]? 157 | public var supportsModulesRequest: Bool? 158 | public var additionalModuleColumns: [ColumnDescriptor]? 159 | public var supportedChecksumAlgorithms: [ChecksumAlgorithm]? 160 | public var supportsRestartRequest: Bool? 161 | public var supportsExceptionOptions: Bool? 162 | public var supportsValueFormattingOptions: Bool? 163 | public var supportsExceptionInfoRequest: Bool? 164 | public var supportTerminateDebuggee: Bool? 165 | public var supportsDelayedStackTraceLoading: Bool? 166 | public var supportsLoadedSourcesRequest: Bool? 167 | public var supportsLogPoints: Bool? 168 | public var supportsTerminateThreadsRequest: Bool? 169 | public var supportsSetExpression: Bool? 170 | public var supportsTerminateRequest: Bool? 171 | public var supportsDataBreakpoints: Bool? 172 | public var supportsReadMemoryRequest: Bool? 173 | public var supportsDisassembleRequest: Bool? 174 | public var supportsCancelRequest: Bool? 175 | public var supportsBreakpointLocationsRequest: Bool? 176 | public var supportsClipboardContext: Bool? 177 | public var supportsSteppingGranularity: Bool? 178 | 179 | public init(supportsConfigurationDoneRequest: Bool? = nil, 180 | supportsFunctionBreakpoints: Bool? = nil, 181 | supportsConditionalBreakpoints: Bool? = nil, 182 | supportsHitConditionalBreakpoints: Bool? = nil, 183 | supportsEvaluateForHovers: Bool? = nil, 184 | exceptionBreakpointFilters: [ExceptionBreakpointsFilter]? = nil, 185 | supportsStepBack: Bool? = nil, 186 | supportsSetVariable: Bool? = nil, 187 | supportsRestartFrame: Bool? = nil, 188 | supportsGotoTargetsRequest: Bool? = nil, 189 | supportsStepInTargetsRequest: Bool? = nil, 190 | supportsCompletionsRequest: Bool? = nil, 191 | completionTriggerCharacters: [String]? = nil, 192 | supportsModulesRequest: Bool? = nil, 193 | additionalModuleColumns: [ColumnDescriptor]? = nil, 194 | supportedChecksumAlgorithms: [ChecksumAlgorithm]? = nil, 195 | supportsRestartRequest: Bool? = nil, 196 | supportsExceptionOptions: Bool? = nil, 197 | supportsValueFormattingOptions: Bool? = nil, 198 | supportsExceptionInfoRequest: Bool? = nil, 199 | supportTerminateDebuggee: Bool? = nil, 200 | supportsDelayedStackTraceLoading: Bool? = nil, 201 | supportsLoadedSourcesRequest: Bool? = nil, 202 | supportsLogPoints: Bool? = nil, 203 | supportsTerminateThreadsRequest: Bool? = nil, 204 | supportsSetExpression: Bool? = nil, 205 | supportsTerminateRequest: Bool? = nil, 206 | supportsDataBreakpoints: Bool? = nil, 207 | supportsReadMemoryRequest: Bool? = nil, 208 | supportsDisassembleRequest: Bool? = nil, 209 | supportsCancelRequest: Bool? = nil, 210 | supportsBreakpointLocationsRequest: Bool? = nil, 211 | supportsClipboardContext: Bool? = nil, 212 | supportsSteppingGranularity: Bool? = nil) { 213 | self.supportsConfigurationDoneRequest = supportsConfigurationDoneRequest 214 | self.supportsFunctionBreakpoints = supportsFunctionBreakpoints 215 | self.supportsConditionalBreakpoints = supportsConditionalBreakpoints 216 | self.supportsHitConditionalBreakpoints = supportsHitConditionalBreakpoints 217 | self.supportsEvaluateForHovers = supportsEvaluateForHovers 218 | self.exceptionBreakpointFilters = exceptionBreakpointFilters 219 | self.supportsStepBack = supportsStepBack 220 | self.supportsSetVariable = supportsSetVariable 221 | self.supportsRestartFrame = supportsRestartFrame 222 | self.supportsGotoTargetsRequest = supportsGotoTargetsRequest 223 | self.supportsStepInTargetsRequest = supportsStepInTargetsRequest 224 | self.supportsCompletionsRequest = supportsCompletionsRequest 225 | self.completionTriggerCharacters = completionTriggerCharacters 226 | self.supportsModulesRequest = supportsModulesRequest 227 | self.additionalModuleColumns = additionalModuleColumns 228 | self.supportedChecksumAlgorithms = supportedChecksumAlgorithms 229 | self.supportsRestartRequest = supportsRestartRequest 230 | self.supportsExceptionOptions = supportsExceptionOptions 231 | self.supportsValueFormattingOptions = supportsValueFormattingOptions 232 | self.supportsExceptionInfoRequest = supportsExceptionInfoRequest 233 | self.supportTerminateDebuggee = supportTerminateDebuggee 234 | self.supportsDelayedStackTraceLoading = supportsDelayedStackTraceLoading 235 | self.supportsLoadedSourcesRequest = supportsLoadedSourcesRequest 236 | self.supportsLogPoints = supportsLogPoints 237 | self.supportsTerminateThreadsRequest = supportsTerminateThreadsRequest 238 | self.supportsSetExpression = supportsSetExpression 239 | self.supportsTerminateRequest = supportsTerminateRequest 240 | self.supportsDataBreakpoints = supportsDataBreakpoints 241 | self.supportsReadMemoryRequest = supportsReadMemoryRequest 242 | self.supportsDisassembleRequest = supportsDisassembleRequest 243 | self.supportsCancelRequest = supportsCancelRequest 244 | self.supportsBreakpointLocationsRequest = supportsBreakpointLocationsRequest 245 | self.supportsClipboardContext = supportsClipboardContext 246 | self.supportsSteppingGranularity = supportsSteppingGranularity 247 | } 248 | } 249 | 250 | public typealias SetFunctionBreakpointsResponse = SetBreakpointsResponse 251 | public typealias SetDataBreakpointsResponse = SetBreakpointsResponse 252 | 253 | public struct SetBreakpointsResponse: Codable { 254 | public var breakpoints: [Breakpoint] 255 | 256 | public init(breakpoints: [Breakpoint]) { 257 | self.breakpoints = breakpoints 258 | } 259 | } 260 | 261 | public struct ThreadsResponse: Codable { 262 | public var threads: [Thread] 263 | 264 | public init(threads: [Thread]) { 265 | self.threads = threads 266 | } 267 | } 268 | 269 | public struct StackTraceResponse: Codable { 270 | public var stackFrames: [StackFrame] 271 | public var totalFrames: Int? 272 | 273 | public init(stackFrames: [StackFrame], totalFrames: Int? = nil) { 274 | self.stackFrames = stackFrames 275 | self.totalFrames = totalFrames 276 | } 277 | } 278 | 279 | public struct ScopesResponse: Codable { 280 | public var scopes: [Scope] 281 | 282 | public init(scopes: [Scope]) { 283 | self.scopes = scopes 284 | } 285 | } 286 | 287 | public struct VariablesResponse: Codable { 288 | public var variables: [Variable] 289 | 290 | public init(variables: [Variable]) { 291 | self.variables = variables 292 | } 293 | } 294 | 295 | public struct ContinueResponse: Codable { 296 | public var allThreadsContinued: Bool? 297 | 298 | public init(allThreadsContinued: Bool?) { 299 | self.allThreadsContinued = allThreadsContinued 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Protocol/Types.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum PresentationHint: String, Codable { 4 | case normal, emphasize, deemphasize 5 | } 6 | 7 | public enum ChecksumAlgorithm: String, Codable { 8 | case md5 = "MD5" 9 | case sha1 = "SHA1" 10 | case sha256 = "SHA256" 11 | case timestamp = "timestamp" 12 | } 13 | 14 | public struct ExceptionBreakpointsFilter: Codable { 15 | public var filter: String 16 | public var label: String 17 | public var `default`: Bool? 18 | 19 | public init(filter: String, label: String, `default`: Bool? = nil) { 20 | self.filter = filter 21 | self.label = label 22 | self.default = `default` 23 | } 24 | } 25 | 26 | public enum ColumnDescriptorType: String, Codable { 27 | case string, number, boolean, unixTimestampUTC 28 | } 29 | 30 | public struct ColumnDescriptor: Codable { 31 | public var attributeName: String 32 | public var label: String 33 | public var format: String? 34 | public var type: ColumnDescriptorType? 35 | public var width: Int? 36 | 37 | public init(attributeName: String, 38 | label: String, 39 | format: String? = nil, 40 | type: ColumnDescriptorType? = nil, 41 | width: Int? = nil) { 42 | self.attributeName = attributeName 43 | self.label = label 44 | self.format = format 45 | self.type = type 46 | self.width = width 47 | } 48 | } 49 | 50 | public struct Source: Codable { 51 | public var name: String? 52 | public var path: String? 53 | public var sourceReference: Int? 54 | public var presentationHint: PresentationHint? 55 | public var origin: Int? 56 | public var sources: Int? 57 | public var adapterData: String? 58 | public var checksums: [Checksum]? 59 | 60 | public init(name: String? = nil, 61 | path: String? = nil, 62 | sourceReference: Int? = nil, 63 | presentationHint: PresentationHint? = nil, 64 | origin: Int? = nil, 65 | sources: Int? = nil, 66 | adapterData: String? = nil, 67 | checksums: [Checksum]? = nil) { 68 | self.name = name 69 | self.path = path 70 | self.sourceReference = sourceReference 71 | self.presentationHint = presentationHint 72 | self.origin = origin 73 | self.sources = sources 74 | self.adapterData = adapterData 75 | self.checksums = checksums 76 | } 77 | } 78 | 79 | public struct Checksum: Codable { 80 | public var algorithm: ChecksumAlgorithm 81 | public var checksum: String 82 | 83 | public init(algorithm: ChecksumAlgorithm, checksum: String) { 84 | self.algorithm = algorithm 85 | self.checksum = checksum 86 | } 87 | } 88 | 89 | public struct SourceBreakpoint: Codable { 90 | public var line: Int 91 | public var column: Int? 92 | public var condition: String? 93 | public var hitCondition: String? 94 | public var logMessage: String? 95 | 96 | public init(line: Int, 97 | column: Int? = nil, 98 | condition: String? = nil, 99 | hitCondition: String? = nil, 100 | logMessage: String? = nil) { 101 | self.line = line 102 | self.column = column 103 | self.condition = condition 104 | self.hitCondition = hitCondition 105 | self.logMessage = logMessage 106 | } 107 | } 108 | 109 | public struct FunctionBreakpoint: Codable { 110 | public var name: String 111 | public var condition: String? 112 | public var hitCondition: String? 113 | 114 | public init(name: String, condition: String? = nil, hitCondition: String? = nil) { 115 | self.name = name 116 | self.condition = condition 117 | self.hitCondition = hitCondition 118 | } 119 | } 120 | 121 | public struct Breakpoint: Codable { 122 | public var id: Int? 123 | public var verified: Bool 124 | public var message: String? 125 | public var source: Source? 126 | public var line: Int? 127 | public var column: Int? 128 | public var endLine: Int? 129 | public var endColumn: Int? 130 | 131 | public init(id: Int? = nil, 132 | verified: Bool, 133 | message: String? = nil, 134 | source: Source? = nil, 135 | line: Int? = nil, 136 | column: Int? = nil, 137 | endLine: Int? = nil, 138 | endColumn: Int? = nil) { 139 | self.id = id 140 | self.verified = verified 141 | self.message = message 142 | self.source = source 143 | self.line = line 144 | self.column = column 145 | self.endLine = endLine 146 | self.endColumn = endColumn 147 | } 148 | } 149 | 150 | public struct DataBreakpoint: Codable { 151 | public var dataId: String 152 | public var accessType: DataBreakpointAccessType? 153 | public var condition: String? 154 | public var hitCondition: String? 155 | 156 | public init(dataId: String, 157 | accessType: DataBreakpointAccessType? = nil, 158 | condition: String? = nil, 159 | hitCondition: String? = nil) { 160 | self.dataId = dataId 161 | self.accessType = accessType 162 | self.condition = condition 163 | self.hitCondition = hitCondition 164 | } 165 | } 166 | 167 | public enum DataBreakpointAccessType: String, Codable { 168 | case read, write, readWrite 169 | } 170 | 171 | public struct ExceptionOptions: Codable { 172 | public var path: [ExceptionPathSegment]? 173 | public var breakMode: ExceptionBreakMode 174 | 175 | public init(path: [ExceptionPathSegment]? = nil, breakMode: ExceptionBreakMode) { 176 | self.path = path 177 | self.breakMode = breakMode 178 | } 179 | } 180 | 181 | public enum ExceptionBreakMode: String, Codable { 182 | case never, always, unhandled, userUnhandled 183 | } 184 | 185 | public struct ExceptionPathSegment: Codable { 186 | public var negate: Bool? 187 | public var names: [String] 188 | 189 | public init(negate: Bool? = nil, names: [String]) { 190 | self.negate = negate 191 | self.names = names 192 | } 193 | } 194 | 195 | public struct Thread: Codable { 196 | public var id: Int 197 | public var name: String 198 | 199 | public init(id: Int, name: String) { 200 | self.id = id 201 | self.name = name 202 | } 203 | } 204 | 205 | public struct StackFrame: Codable { 206 | public var id: Int 207 | public var name: String 208 | public var source: Source? 209 | public var line: Int 210 | public var column: Int 211 | public var endLine: Int? 212 | public var endColumn: Int? 213 | public var instructionPointerReference: String? 214 | // public var moduleId: String | Int 215 | public var presentationHint: PresentationHint? 216 | 217 | public init(id: Int, 218 | name: String, 219 | source: Source? = nil, 220 | line: Int, 221 | column: Int, 222 | endLine: Int? = nil, 223 | endColumn: Int? = nil, 224 | instructionPointerReference: String? = nil, 225 | presentationHint: PresentationHint? = nil) { 226 | self.id = id 227 | self.name = name 228 | self.source = source 229 | self.line = line 230 | self.column = column 231 | self.endLine = endLine 232 | self.endColumn = endColumn 233 | self.instructionPointerReference = instructionPointerReference 234 | self.presentationHint = presentationHint 235 | } 236 | } 237 | 238 | public struct ValueFormat: Codable { 239 | public var hex: Bool? 240 | 241 | public init(hex: Bool? = nil) { 242 | self.hex = hex 243 | } 244 | } 245 | 246 | public struct StackFrameFormat: Codable { 247 | public var hex: Bool? 248 | public var parameters: Bool? 249 | public var parameterTypes: Bool? 250 | public var parameterNames: Bool? 251 | public var parameterValues: Bool? 252 | public var line: Bool? 253 | public var module: Bool? 254 | public var includeAll: Bool? 255 | 256 | public init(hex: Bool? = nil, 257 | parameters: Bool? = nil, 258 | parameterTypes: Bool? = nil, 259 | parameterNames: Bool? = nil, 260 | parameterValues: Bool? = nil, 261 | line: Bool? = nil, 262 | module: Bool? = nil, 263 | includeAll: Bool? = nil) { 264 | self.hex = hex 265 | self.parameters = parameters 266 | self.parameterTypes = parameterTypes 267 | self.parameterNames = parameterNames 268 | self.parameterValues = parameterValues 269 | self.line = line 270 | self.module = module 271 | self.includeAll = includeAll 272 | } 273 | } 274 | 275 | public struct Scope: Codable { 276 | public var name: String 277 | public var presentationHint: PresentationHint? 278 | public var variablesReference: Int 279 | public var namedVariables: Int? 280 | public var indexedVariables: Int? 281 | public var expensive: Bool 282 | public var source: Source? 283 | public var line: Int? 284 | public var column: Int? 285 | public var endLine: Int? 286 | public var endColumn: Int? 287 | 288 | public init(name: String, 289 | presentationHint: PresentationHint? = nil, 290 | variablesReference: Int, 291 | namedVariables: Int? = nil, 292 | indexedVariables: Int? = nil, 293 | expensive: Bool, 294 | source: Source? = nil, 295 | line: Int? = nil, 296 | column: Int? = nil, 297 | endLine: Int? = nil, 298 | endColumn: Int? = nil) { 299 | self.name = name 300 | self.presentationHint = presentationHint 301 | self.variablesReference = variablesReference 302 | self.namedVariables = namedVariables 303 | self.indexedVariables = indexedVariables 304 | self.expensive = expensive 305 | self.source = source 306 | self.line = line 307 | self.column = column 308 | self.endLine = endLine 309 | self.endColumn = endColumn 310 | } 311 | } 312 | 313 | public struct Variable: Codable { 314 | public var name: String 315 | public var value: String 316 | public var type: String? 317 | public var presentationHint: VariablePresentationHint? 318 | public var evaluateName: String? 319 | public var variablesReference: Int 320 | public var namedVariables: Int? 321 | public var indexedVariables: Int? 322 | public var memoryReference: Int? 323 | 324 | public init(name: String, 325 | value: String, 326 | type: String? = nil, 327 | presentationHint: VariablePresentationHint? = nil, 328 | evaluateName: String? = nil, 329 | variablesReference: Int, 330 | namedVariables: Int? = nil, 331 | indexedVariables: Int? = nil, 332 | memoryReference: Int? = nil) { 333 | self.name = name 334 | self.value = value 335 | self.type = type 336 | self.presentationHint = presentationHint 337 | self.evaluateName = evaluateName 338 | self.variablesReference = variablesReference 339 | self.namedVariables = namedVariables 340 | self.indexedVariables = indexedVariables 341 | self.memoryReference = memoryReference 342 | } 343 | } 344 | 345 | public enum VariablePresentationHintKind: String, Codable { 346 | case property, method, `class`, data, event, baseClass, innerClass, interface, mostDerivedClass, virtual, 347 | dataBreakpoints 348 | } 349 | 350 | public enum VariablePresentationHintAttribute: String, Codable { 351 | case `static`, constant, readOnly, rawString, hasObjectId, canHaveObjectId, hasSideEffects 352 | } 353 | 354 | public struct VariablePresentationHint: Codable { 355 | public var kind: VariablePresentationHintKind 356 | public var attributes: [VariablePresentationHintAttribute]? 357 | public var visibility: String? 358 | 359 | public init(kind: VariablePresentationHintKind, 360 | attributes: [VariablePresentationHintAttribute]? = nil, 361 | visibility: String? = nil) { 362 | self.kind = kind 363 | self.attributes = attributes 364 | self.visibility = visibility 365 | } 366 | } 367 | 368 | public enum SteppingGranularity: String, Codable { 369 | case statement, line, instruction 370 | } -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Utils/CodableExtensions.swift: -------------------------------------------------------------------------------- 1 | // https://gist.github.com/sukov/d3834c0e7b72e4f7575f753b352f6ddd 2 | 3 | struct GenericCodingKeys: CodingKey { 4 | var stringValue: String 5 | 6 | init(stringValue: String) { 7 | self.stringValue = stringValue 8 | } 9 | 10 | var intValue: Int? 11 | 12 | init?(intValue: Int) { 13 | self.init(stringValue: "\(intValue)") 14 | self.intValue = intValue 15 | } 16 | } 17 | 18 | extension KeyedDecodingContainer { 19 | func decode(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any] { 20 | let container = try nestedContainer(keyedBy: GenericCodingKeys.self, forKey: key) 21 | return try container.decode(type) 22 | } 23 | 24 | func decode(_ type: [Any].Type, forKey key: K) throws -> [Any] { 25 | var container = try nestedUnkeyedContainer(forKey: key) 26 | return try container.decode(type) 27 | } 28 | 29 | func decode(_ type: [String: Any].Type) throws -> [String: Any] { 30 | var dictionary = [String: Any]() 31 | 32 | for key in allKeys { 33 | if let boolValue = try? decode(Bool.self, forKey: key) { 34 | dictionary[key.stringValue] = boolValue 35 | } else if let intValue = try? decode(Int.self, forKey: key) { 36 | dictionary[key.stringValue] = intValue 37 | } else if let stringValue = try? decode(String.self, forKey: key) { 38 | dictionary[key.stringValue] = stringValue 39 | } else if let doubleValue = try? decode(Double.self, forKey: key) { 40 | dictionary[key.stringValue] = doubleValue 41 | } else if let nestedDictionary = try? decode([String: Any].self, forKey: key) { 42 | dictionary[key.stringValue] = nestedDictionary 43 | } else if let nestedArray = try? decode([Any].self, forKey: key) { 44 | dictionary[key.stringValue] = nestedArray 45 | } else if let isValueNil = try? decodeNil(forKey: key), isValueNil == true { 46 | dictionary[key.stringValue] = nil 47 | } else { 48 | throw DecodingError.dataCorrupted( 49 | DecodingError.Context(codingPath: codingPath + [key], debugDescription: "Unable to decode value")) 50 | } 51 | } 52 | return dictionary 53 | } 54 | } 55 | 56 | extension UnkeyedDecodingContainer { 57 | mutating func decode(_ type: [Any].Type) throws -> [Any] { 58 | var array: [Any] = [] 59 | 60 | while isAtEnd == false { 61 | if let value = try? decode(Bool.self) { 62 | array.append(value) 63 | } else if let value = try? decode(Int.self) { 64 | array.append(value) 65 | } else if let value = try? decode(String.self) { 66 | array.append(value) 67 | } else if let value = try? decode(Double.self) { 68 | array.append(value) 69 | } else if let nestedDictionary = try? decode([String: Any].self) { 70 | array.append(nestedDictionary) 71 | } else if let nestedArray = try? decodeNestedArray([Any].self) { 72 | array.append(nestedArray) 73 | } else if let isValueNil = try? decodeNil(), isValueNil == true { 74 | array.append(Any?.none as Any) 75 | } else { 76 | throw DecodingError.dataCorrupted( 77 | DecodingError.Context(codingPath: codingPath, debugDescription: "Unable to decode value")) 78 | } 79 | } 80 | return array 81 | } 82 | 83 | mutating func decode(_ type: [String: Any].Type) throws -> [String: Any] { 84 | let container = try nestedContainer(keyedBy: GenericCodingKeys.self) 85 | return try container.decode(type) 86 | } 87 | 88 | mutating func decodeNestedArray(_ type: [Any].Type) throws -> [Any] { 89 | var container = try nestedUnkeyedContainer() 90 | return try container.decode(type) 91 | } 92 | } 93 | 94 | extension KeyedEncodingContainerProtocol where Key == GenericCodingKeys { 95 | mutating func encode(_ value: [String: Any]) throws { 96 | for (key, value) in value { 97 | let key = GenericCodingKeys(stringValue: key) 98 | switch value { 99 | case let value as Bool: 100 | try encode(value, forKey: key) 101 | case let value as Int: 102 | try encode(value, forKey: key) 103 | case let value as String: 104 | try encode(value, forKey: key) 105 | case let value as Double: 106 | try encode(value, forKey: key) 107 | case let value as [String: Any]: 108 | try encode(value, forKey: key) 109 | case let value as [Any]: 110 | try encode(value, forKey: key) 111 | case Optional.none: 112 | try encodeNil(forKey: key) 113 | default: 114 | throw EncodingError.invalidValue( 115 | value, 116 | EncodingError.Context(codingPath: codingPath + [key], debugDescription: "Invalid JSON value")) 117 | } 118 | } 119 | } 120 | } 121 | 122 | extension KeyedEncodingContainerProtocol { 123 | mutating func encode(_ value: [String: Any]?, forKey key: Key) throws { 124 | guard let value = value else { return } 125 | 126 | var container = nestedContainer(keyedBy: GenericCodingKeys.self, forKey: key) 127 | try container.encode(value) 128 | } 129 | 130 | mutating func encode(_ value: [Any]?, forKey key: Key) throws { 131 | guard let value = value else { return } 132 | 133 | var container = nestedUnkeyedContainer(forKey: key) 134 | try container.encode(value) 135 | } 136 | } 137 | 138 | extension UnkeyedEncodingContainer { 139 | mutating func encode(_ value: [Any]) throws { 140 | for (index, value) in value.enumerated() { 141 | switch value { 142 | case let value as Bool: 143 | try encode(value) 144 | case let value as Int: 145 | try encode(value) 146 | case let value as String: 147 | try encode(value) 148 | case let value as Double: 149 | try encode(value) 150 | case let value as [String: Any]: 151 | try encode(value) 152 | case let value as [Any]: 153 | try encodeNestedArray(value) 154 | case Optional.none: 155 | try encodeNil() 156 | default: 157 | let keys = GenericCodingKeys(intValue: index).map({ [ $0 ] }) ?? [] 158 | throw EncodingError.invalidValue( 159 | value, 160 | EncodingError.Context(codingPath: codingPath + keys, debugDescription: "Invalid JSON value")) 161 | } 162 | } 163 | } 164 | 165 | mutating func encode(_ value: [String: Any]) throws { 166 | var container = nestedContainer(keyedBy: GenericCodingKeys.self) 167 | try container.encode(value) 168 | } 169 | 170 | mutating func encodeNestedArray(_ value: [Any]) throws { 171 | var container = nestedUnkeyedContainer() 172 | try container.encode(value) 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /Sources/DebugAdapterProtocol/Utils/MirroredEnum.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol MirroredEnum { 4 | } 5 | 6 | public extension MirroredEnum { 7 | var label: String { 8 | let reflection = Mirror(reflecting: self) 9 | guard reflection.displayStyle == .enum, let associated = reflection.children.first else { 10 | return "\(self)" 11 | } 12 | return associated.label! 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Tests/DebugAdapterProtocolTests/DebugAdapterProtocolTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import DebugAdapterProtocol 3 | 4 | final class DebugAdapterProtocolTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | } 10 | 11 | static var allTests = [ 12 | ("testExample", testExample), 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /Tests/DebugAdapterProtocolTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !os(macOS) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(DebugAdapterProtocolTests.allTests), 7 | ] 8 | } 9 | #endif -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import DebugAdapterProtocolTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += DebugAdapterProtocolTests.allTests() 7 | XCTMain(tests) --------------------------------------------------------------------------------