ecalDebugAdapter.ts 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**
  2. * Debug Adapter for VS Code to support the ECAL debugger.
  3. *
  4. * See the debugger extension guide:
  5. * https://code.visualstudio.com/api/extension-guides/debugger-extension
  6. */
  7. import { logger, Logger, LoggingDebugSession, InitializedEvent, Thread } from 'vscode-debugadapter'
  8. import { DebugProtocol } from 'vscode-debugprotocol'
  9. import { WaitGroup } from '@jpwilliams/waitgroup'
  10. /**
  11. * ECALDebugArguments are the arguments which VSCode can pass to the debug adapter.
  12. * This defines the parameter which a VSCode instance using the ECAL extention can pass to the
  13. * debug adapter from a lauch configuration ('.vscode/launch.json') in a project folder.
  14. */
  15. interface ECALDebugArguments extends DebugProtocol.LaunchRequestArguments {
  16. dir: string; // Root directory for ECAL interpreter
  17. serverURL: string // URL of the ECAL debug server
  18. executeOnEntry?: boolean; // Flag if the debugged script should be executed when the debug session is started
  19. trace?: boolean; // Flag to enable verbose logging of the adapter protocol
  20. }
  21. /**
  22. * Debug adapter implementation.
  23. *
  24. * Uses: https://github.com/microsoft/vscode-debugadapter-node
  25. *
  26. * See the Debug Adapter Protocol (DAP) documentation:
  27. * https://microsoft.github.io/debug-adapter-protocol/overview#How_it_works
  28. */
  29. export class ECALDebugSession extends LoggingDebugSession {
  30. /**
  31. * WaitGroup to wait the finish of the configuration sequence
  32. */
  33. private wgConfig = new WaitGroup();
  34. /**
  35. * Create a new debug adapter which is used for one debug session.
  36. */
  37. public constructor () {
  38. super('mock-debug.txt')
  39. console.error('##### constructor')
  40. // Lines and columns start at 1
  41. this.setDebuggerLinesStartAt1(true)
  42. this.setDebuggerColumnsStartAt1(true)
  43. // Increment the config WaitGroup counter for configurationDoneRequest()
  44. this.wgConfig.add(1)
  45. }
  46. /**
  47. * Called as the first step in the DAP. The client (e.g. VSCode)
  48. * interrogates the debug adapter on the features which it provides.
  49. */
  50. protected initializeRequest (response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
  51. console.log('##### initializeRequest:', args)
  52. response.body = response.body || {}
  53. // The adapter implements the configurationDoneRequest.
  54. response.body.supportsConfigurationDoneRequest = true
  55. this.sendResponse(response)
  56. this.sendEvent(new InitializedEvent())
  57. }
  58. /**
  59. * Called as part of the "configuration Done" step in the DAP. The client (e.g. VSCode) has
  60. * finished the initialization of the debug adapter.
  61. */
  62. protected configurationDoneRequest (response: DebugProtocol.ConfigurationDoneResponse, args: DebugProtocol.ConfigurationDoneArguments): void {
  63. console.error('##### configurationDoneRequest')
  64. super.configurationDoneRequest(response, args)
  65. this.wgConfig.done()
  66. }
  67. /**
  68. * The client (e.g. VSCode) asks the debug adapter to start the debuggee communication.
  69. */
  70. protected async launchRequest (response: DebugProtocol.LaunchResponse, args: ECALDebugArguments) {
  71. console.error('##### launchRequest:', args)
  72. // Setup logging either verbose or just on errors
  73. logger.setup(args.trace ? Logger.LogLevel.Verbose : Logger.LogLevel.Error, false)
  74. await this.wgConfig.wait() // Wait for configuration sequence to finish
  75. this.sendResponse(response)
  76. }
  77. protected async setBreakPointsRequest (response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): Promise<void> {
  78. console.error('##### setBreakPointsRequest:', args)
  79. response.body = {
  80. breakpoints: []
  81. }
  82. this.sendResponse(response)
  83. }
  84. protected threadsRequest (response: DebugProtocol.ThreadsResponse): void {
  85. console.error('##### threadsRequest')
  86. // runtime supports no threads so just return a default thread.
  87. response.body = {
  88. threads: [
  89. new Thread(1, 'thread 1')
  90. ]
  91. }
  92. this.sendResponse(response)
  93. }
  94. protected stackTraceRequest (response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void {
  95. console.error('##### stackTraceRequest:', args)
  96. response.body = {
  97. stackFrames: []
  98. }
  99. this.sendResponse(response)
  100. }
  101. protected scopesRequest (response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
  102. console.error('##### scopesRequest:', args)
  103. response.body = {
  104. scopes: []
  105. }
  106. this.sendResponse(response)
  107. }
  108. protected async variablesRequest (response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments, request?: DebugProtocol.Request) {
  109. console.error('##### variablesRequest', args, request)
  110. response.body = {
  111. variables: []
  112. }
  113. this.sendResponse(response)
  114. }
  115. protected continueRequest (response: DebugProtocol.ContinueResponse, args: DebugProtocol.ContinueArguments): void {
  116. console.error('##### continueRequest', args)
  117. this.sendResponse(response)
  118. }
  119. protected reverseContinueRequest (response: DebugProtocol.ReverseContinueResponse, args: DebugProtocol.ReverseContinueArguments): void {
  120. console.error('##### reverseContinueRequest', args)
  121. this.sendResponse(response)
  122. }
  123. protected nextRequest (response: DebugProtocol.NextResponse, args: DebugProtocol.NextArguments): void {
  124. console.error('##### nextRequest', args)
  125. this.sendResponse(response)
  126. }
  127. protected stepBackRequest (response: DebugProtocol.StepBackResponse, args: DebugProtocol.StepBackArguments): void {
  128. console.error('##### stepBackRequest', args)
  129. this.sendResponse(response)
  130. }
  131. protected stepInTargetsRequest (response: DebugProtocol.StepInTargetsResponse, args: DebugProtocol.StepInTargetsArguments) {
  132. console.error('##### stepInTargetsRequest', args)
  133. response.body = {
  134. targets: []
  135. }
  136. this.sendResponse(response)
  137. }
  138. protected stepInRequest (response: DebugProtocol.StepInResponse, args: DebugProtocol.StepInArguments): void {
  139. console.error('##### stepInRequest', args)
  140. this.sendResponse(response)
  141. }
  142. protected stepOutRequest (response: DebugProtocol.StepOutResponse, args: DebugProtocol.StepOutArguments): void {
  143. console.error('##### stepOutRequest', args)
  144. this.sendResponse(response)
  145. }
  146. protected async evaluateRequest (response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): Promise<void> {
  147. console.error('##### evaluateRequest', args)
  148. response.body = {
  149. result: 'evaluate',
  150. variablesReference: 0
  151. }
  152. this.sendResponse(response)
  153. }
  154. protected dataBreakpointInfoRequest (response: DebugProtocol.DataBreakpointInfoResponse, args: DebugProtocol.DataBreakpointInfoArguments): void {
  155. console.error('##### dataBreakpointInfoRequest', args)
  156. response.body = {
  157. dataId: null,
  158. description: 'cannot break on data access',
  159. accessTypes: undefined,
  160. canPersist: false
  161. }
  162. this.sendResponse(response)
  163. }
  164. protected setDataBreakpointsRequest (response: DebugProtocol.SetDataBreakpointsResponse, args: DebugProtocol.SetDataBreakpointsArguments): void {
  165. console.error('##### setDataBreakpointsRequest', args)
  166. response.body = {
  167. breakpoints: []
  168. }
  169. this.sendResponse(response)
  170. }
  171. protected completionsRequest (response: DebugProtocol.CompletionsResponse, args: DebugProtocol.CompletionsArguments): void {
  172. console.error('##### completionsRequest', args)
  173. response.body = {
  174. targets: [
  175. {
  176. label: 'item 10',
  177. sortText: '10'
  178. },
  179. {
  180. label: 'item 1',
  181. sortText: '01'
  182. },
  183. {
  184. label: 'item 2',
  185. sortText: '02'
  186. },
  187. {
  188. label: 'array[]',
  189. selectionStart: 6,
  190. sortText: '03'
  191. },
  192. {
  193. label: 'func(arg)',
  194. selectionStart: 5,
  195. selectionLength: 3,
  196. sortText: '04'
  197. }
  198. ]
  199. }
  200. this.sendResponse(response)
  201. }
  202. protected cancelRequest (response: DebugProtocol.CancelResponse, args: DebugProtocol.CancelArguments) {
  203. console.error('##### cancelRequest', args)
  204. this.sendResponse(response)
  205. }
  206. protected customRequest (command: string, response: DebugProtocol.Response, args: any) {
  207. console.error('##### customRequest', args)
  208. if (command === 'toggleFormatting') {
  209. this.sendResponse(response)
  210. } else {
  211. super.customRequest(command, response, args)
  212. }
  213. }
  214. }