Helios-Debugger.st 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. Smalltalk createPackage: 'Helios-Debugger'!
  2. Object subclass: #HLContextInspectorDecorator
  3. instanceVariableNames: 'context'
  4. package: 'Helios-Debugger'!
  5. !HLContextInspectorDecorator methodsFor: 'accessing'!
  6. context
  7. ^ context
  8. ! !
  9. !HLContextInspectorDecorator methodsFor: 'initialization'!
  10. initializeFromContext: aContext
  11. context := aContext
  12. ! !
  13. !HLContextInspectorDecorator methodsFor: 'inspecting'!
  14. inspectOn: anInspector
  15. | variables inspectedContext |
  16. variables := Dictionary new.
  17. inspectedContext := self context.
  18. variables addAll: inspectedContext locals.
  19. [ inspectedContext notNil and: [ inspectedContext isBlockContext ] ] whileTrue: [
  20. inspectedContext := inspectedContext outerContext.
  21. inspectedContext ifNotNil: [
  22. variables addAll: inspectedContext locals ] ].
  23. anInspector
  24. setLabel: 'Context';
  25. setVariables: variables
  26. ! !
  27. !HLContextInspectorDecorator class methodsFor: 'instance creation'!
  28. on: aContext
  29. ^ self new
  30. initializeFromContext: aContext;
  31. yourself
  32. ! !
  33. HLFocusableWidget subclass: #HLDebugger
  34. instanceVariableNames: 'model stackListWidget codeWidget inspectorWidget'
  35. package: 'Helios-Debugger'!
  36. !HLDebugger commentStamp!
  37. I am the main widget for the Helios debugger.!
  38. !HLDebugger methodsFor: 'accessing'!
  39. codeWidget
  40. ^ codeWidget ifNil: [ codeWidget := HLDebuggerCodeWidget new
  41. browserModel: self model;
  42. yourself ]
  43. !
  44. initializeFromMethodContext: aMethodContext
  45. model := HLDebuggerModel on: aMethodContext.
  46. self observeModel
  47. !
  48. inspectorWidget
  49. ^ inspectorWidget ifNil: [
  50. inspectorWidget := HLInspectorWidget new ]
  51. !
  52. model
  53. ^ model ifNil: [ model := HLDebuggerModel new ]
  54. !
  55. stackListWidget
  56. ^ stackListWidget ifNil: [
  57. stackListWidget := (HLStackListWidget on: self model)
  58. next: self codeWidget;
  59. yourself ]
  60. ! !
  61. !HLDebugger methodsFor: 'actions'!
  62. focus
  63. self stackListWidget focus
  64. !
  65. observeModel
  66. self model announcer
  67. on: HLDebuggerContextSelected
  68. send: #onContextSelected:
  69. to: self.
  70. self model announcer
  71. on: HLDebuggerStepped
  72. send: #onContextSelected:
  73. to: self
  74. !
  75. unregister
  76. super unregister.
  77. self inspectorWidget unregister
  78. ! !
  79. !HLDebugger methodsFor: 'keybindings'!
  80. registerBindingsOn: aBindingGroup
  81. HLToolCommand
  82. registerConcreteClassesOn: aBindingGroup
  83. for: self model
  84. ! !
  85. !HLDebugger methodsFor: 'reactions'!
  86. onContextSelected: anAnnouncement
  87. self inspectorWidget inspect: (HLContextInspectorDecorator on: anAnnouncement context)
  88. ! !
  89. !HLDebugger methodsFor: 'rendering'!
  90. renderContentOn: html
  91. html with: (HLContainer with: (HLHorizontalSplitter
  92. with: self stackListWidget
  93. with: (HLVerticalSplitter
  94. with: self codeWidget
  95. with: self inspectorWidget)))
  96. ! !
  97. !HLDebugger class methodsFor: 'accessing'!
  98. tabClass
  99. ^ 'debugger'
  100. !
  101. tabLabel
  102. ^ 'Debugger'
  103. ! !
  104. !HLDebugger class methodsFor: 'instance creation'!
  105. on: aMethodContext
  106. ^ self new
  107. initializeFromMethodContext: aMethodContext;
  108. yourself
  109. ! !
  110. HLBrowserCodeWidget subclass: #HLDebuggerCodeWidget
  111. instanceVariableNames: ''
  112. package: 'Helios-Debugger'!
  113. !HLDebuggerCodeWidget methodsFor: 'accessing'!
  114. contents: aString
  115. self clearHighlight.
  116. super contents: aString
  117. !
  118. editorOptions
  119. ^ super editorOptions
  120. at: 'gutters' put: #('CodeMirror-linenumbers' 'stops');
  121. yourself
  122. ! !
  123. !HLDebuggerCodeWidget methodsFor: 'actions'!
  124. addStopAt: anInteger
  125. editor
  126. setGutterMarker: anInteger
  127. gutter: 'stops'
  128. value: '<div class="stop"></stop>' asJQuery toArray first
  129. !
  130. clearHighlight
  131. self editor clearGutter: 'stops'
  132. !
  133. highlight
  134. self highlightNode: self browserModel nextNode
  135. !
  136. highlightNode: aNode
  137. | token |
  138. aNode ifNotNil: [
  139. self
  140. clearHighlight;
  141. addStopAt: aNode positionStart x - 1.
  142. self editor
  143. setSelection: #{ 'line' -> (aNode positionStart x - 1). 'ch' -> (aNode positionStart y - 1) }
  144. to: #{ 'line' -> (aNode positionEnd x - 1). 'ch' -> (aNode positionEnd y) } ]
  145. !
  146. observeBrowserModel
  147. super observeBrowserModel.
  148. self browserModel announcer
  149. on: HLDebuggerContextSelected
  150. send: #onContextSelected
  151. to: self.
  152. self browserModel announcer
  153. on: HLDebuggerStepped
  154. send: #onContextSelected
  155. to: self.
  156. self browserModel announcer
  157. on: HLDebuggerWhere
  158. send: #onContextSelected
  159. to: self
  160. ! !
  161. !HLDebuggerCodeWidget methodsFor: 'reactions'!
  162. onContextSelected
  163. self highlight
  164. ! !
  165. HLToolModel subclass: #HLDebuggerModel
  166. instanceVariableNames: 'rootContext currentContext contexts'
  167. package: 'Helios-Debugger'!
  168. !HLDebuggerModel commentStamp!
  169. I am a model for Helios debugging.
  170. My instances hold a reference to an `AIContext` instance, built from a `MethodContext`. The context should be the root of the context stack.!
  171. !HLDebuggerModel methodsFor: 'accessing'!
  172. contexts
  173. ^ contexts
  174. !
  175. currentContext
  176. currentContext ifNil: [ self currentContext: self rootContext ].
  177. ^ currentContext
  178. !
  179. currentContext: aContext
  180. self withChangesDo: [
  181. self selectedMethod: aContext method.
  182. currentContext := aContext.
  183. self announcer announce: (HLDebuggerContextSelected new
  184. context: aContext;
  185. yourself) ]
  186. !
  187. interpreter
  188. ^ self currentContext interpreter
  189. !
  190. nextNode
  191. ^ self interpreter node
  192. !
  193. rootContext
  194. ^ rootContext
  195. ! !
  196. !HLDebuggerModel methodsFor: 'actions'!
  197. restart
  198. self interpreter restart.
  199. self announcer announce: (HLDebuggerStepped new
  200. context: self currentContext;
  201. yourself)
  202. !
  203. skip
  204. self interpreter skip.
  205. self announcer announce: (HLDebuggerStepped new
  206. context: self currentContext;
  207. yourself)
  208. !
  209. stepOver
  210. self interpreter stepOver.
  211. self announcer announce: (HLDebuggerStepped new
  212. context: self currentContext;
  213. yourself)
  214. !
  215. where
  216. self announcer announce: HLDebuggerWhere new
  217. ! !
  218. !HLDebuggerModel methodsFor: 'initialization'!
  219. initializeContexts
  220. "Flatten the context stack into an OrderedCollection"
  221. | context |
  222. contexts := OrderedCollection new.
  223. context := self rootContext.
  224. [ context notNil ] whileTrue: [
  225. contexts add: context.
  226. context := context outerContext ]
  227. !
  228. initializeFromContext: aMethodContext
  229. rootContext := AIContext fromMethodContext: aMethodContext.
  230. self initializeContexts
  231. ! !
  232. !HLDebuggerModel class methodsFor: 'instance creation'!
  233. on: aMethodContext
  234. ^ self new
  235. initializeFromContext: aMethodContext;
  236. yourself
  237. ! !
  238. Object subclass: #HLErrorHandler
  239. instanceVariableNames: ''
  240. package: 'Helios-Debugger'!
  241. !HLErrorHandler methodsFor: 'error handling'!
  242. handleError: anError
  243. self onErrorHandled.
  244. [
  245. (HLDebugger on: anError context) openAsTab
  246. ]
  247. on: Error
  248. do: [ :error | ErrorHandler new handleError: error ]
  249. !
  250. onErrorHandled
  251. "when an error is handled, we need to make sure that
  252. any progress bar widget gets removed. Because HLProgressBarWidget is asynchronous,
  253. it has to be done here."
  254. HLProgressWidget default
  255. flush;
  256. remove
  257. ! !
  258. HLToolListWidget subclass: #HLStackListWidget
  259. instanceVariableNames: ''
  260. package: 'Helios-Debugger'!
  261. !HLStackListWidget methodsFor: 'accessing'!
  262. items
  263. ^ items ifNil: [ items := self model contexts ]
  264. !
  265. label
  266. ^ 'Call stack'
  267. ! !
  268. !HLStackListWidget methodsFor: 'actions'!
  269. restart
  270. self model restart
  271. !
  272. selectItem: aContext
  273. self model currentContext: aContext
  274. !
  275. skip
  276. self model skip
  277. !
  278. stepOver
  279. self model stepOver
  280. !
  281. where
  282. self model where
  283. ! !
  284. !HLStackListWidget methodsFor: 'rendering'!
  285. renderButtonsOn: html
  286. html div
  287. class: 'debugger_bar';
  288. with: [
  289. html button
  290. class: 'btn restart';
  291. with: 'Restart';
  292. onClick: [ self restart ].
  293. html button
  294. class: 'btn where';
  295. with: 'Where';
  296. onClick: [ self where ].
  297. html button
  298. class: 'btn stepOver';
  299. with: 'Step over';
  300. onClick: [ self stepOver ].
  301. html button
  302. class: 'btn skip';
  303. with: 'Skip';
  304. onClick: [ self skip ] ]
  305. ! !