Helios-Debugger.st 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. Smalltalk current 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: 'highlightedNode'
  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. highlightedNode
  124. ^ highlightedNode
  125. !
  126. highlightedNode: aNode
  127. highlightedNode := aNode
  128. ! !
  129. !HLDebuggerCodeWidget methodsFor: 'actions'!
  130. addStopAt: anInteger
  131. editor
  132. setGutterMarker: anInteger
  133. gutter: 'stops'
  134. value: '<div class="stop"></stop>' asJQuery toArray first
  135. !
  136. clearHighlight
  137. editor clearGutter: 'stops'.
  138. self highlightedNode ifNotNil: [ :node |
  139. editor
  140. removeLineClass: node position x - 1
  141. where: 'background'
  142. class: 'highlighted' ]
  143. !
  144. highlight
  145. | anchor head selection |
  146. head := #{
  147. 'line' -> (self highlightedNode position x - 1).
  148. 'ch' -> (self highlightedNode position y - 1)
  149. }.
  150. anchor := #{
  151. 'line' -> (self highlightedNode extent x - 1).
  152. 'ch' -> (self highlightedNode extent y - 1)
  153. }.
  154. editor setSelection: head to: anchor
  155. !
  156. highlightLine: anInteger
  157. editor
  158. addLineClass: anInteger
  159. where: 'background'
  160. class: 'highlighted'
  161. !
  162. highlightNode: aNode
  163. | line |
  164. aNode ifNotNil: [
  165. line := aNode position x - 1.
  166. self
  167. clearHighlight;
  168. addStopAt: line;
  169. highlightLine: line;
  170. highlightedNode: aNode
  171. ]
  172. !
  173. observeBrowserModel
  174. super observeBrowserModel.
  175. self browserModel announcer
  176. on: HLDebuggerContextSelected
  177. send: #onContextSelected
  178. to: self.
  179. self browserModel announcer
  180. on: HLDebuggerStepped
  181. send: #onContextSelected
  182. to: self
  183. ! !
  184. !HLDebuggerCodeWidget methodsFor: 'reactions'!
  185. onContextSelected
  186. self highlightNode: self browserModel nextNode
  187. ! !
  188. HLToolModel subclass: #HLDebuggerModel
  189. instanceVariableNames: 'rootContext currentContext contexts'
  190. package: 'Helios-Debugger'!
  191. !HLDebuggerModel commentStamp!
  192. I am a model for Helios debugging.
  193. My instances hold a reference to an `AIContext` instance, built from a `MethodContext`. The context should be the root of the context stack.!
  194. !HLDebuggerModel methodsFor: 'accessing'!
  195. contexts
  196. ^ contexts
  197. !
  198. currentContext
  199. currentContext ifNil: [ self currentContext: self rootContext ].
  200. ^ currentContext
  201. !
  202. currentContext: aContext
  203. self withChangesDo: [
  204. self selectedMethod: aContext method.
  205. currentContext := aContext.
  206. interpreter := ASTDebugger context: aContext.
  207. self announcer announce: (HLDebuggerContextSelected new
  208. context: aContext;
  209. yourself) ]
  210. !
  211. interpreter
  212. ^ self currentContext interpreter
  213. !
  214. nextNode
  215. ^ self interpreter node
  216. !
  217. rootContext
  218. ^ rootContext
  219. ! !
  220. !HLDebuggerModel methodsFor: 'actions'!
  221. restart
  222. self interpreter restart.
  223. self announcer announce: (HLDebuggerStepped new
  224. context: self currentContext;
  225. yourself)
  226. !
  227. stepOver
  228. self interpreter stepOver.
  229. self announcer announce: (HLDebuggerStepped new
  230. context: self currentContext;
  231. yourself)
  232. ! !
  233. !HLDebuggerModel methodsFor: 'initialization'!
  234. initializeContexts
  235. "Flatten the context stack into an OrderedCollection"
  236. | context |
  237. contexts := OrderedCollection new.
  238. context := self rootContext.
  239. [ context notNil ] whileTrue: [
  240. contexts add: context.
  241. context := context outerContext ]
  242. !
  243. initializeFromContext: aMethodContext
  244. rootContext := aMethodContext aiContext.
  245. self initializeContexts
  246. ! !
  247. !HLDebuggerModel class methodsFor: 'instance creation'!
  248. on: aMethodContext
  249. ^ self new
  250. initializeFromContext: aMethodContext;
  251. yourself
  252. ! !
  253. ErrorHandler subclass: #HLErrorHandler
  254. instanceVariableNames: ''
  255. package: 'Helios-Debugger'!
  256. !HLErrorHandler methodsFor: 'error handling'!
  257. handleError: anError
  258. self onErrorHandled.
  259. [
  260. (HLDebugger on: anError context) openAsTab
  261. ]
  262. on: Error
  263. do: [ :error | ErrorHandler new handleError: error ]
  264. !
  265. onErrorHandled
  266. "when an error is handled, we need to make sure that
  267. any progress bar widget gets removed. Because HLProgressBarWidget is asynchronous,
  268. it has to be done here."
  269. HLProgressWidget default
  270. flush;
  271. remove
  272. ! !
  273. !HLErrorHandler class methodsFor: 'error handling'!
  274. handleError: anError
  275. ^ self new handleError: anError
  276. ! !
  277. HLToolListWidget subclass: #HLStackListWidget
  278. instanceVariableNames: ''
  279. package: 'Helios-Debugger'!
  280. !HLStackListWidget methodsFor: 'accessing'!
  281. items
  282. ^ items ifNil: [ items := self model contexts ]
  283. !
  284. label
  285. ^ 'Call stack'
  286. ! !
  287. !HLStackListWidget methodsFor: 'actions'!
  288. restart
  289. self model restart
  290. !
  291. selectItem: aContext
  292. self model currentContext: aContext
  293. !
  294. stepOver
  295. self model stepOver
  296. ! !
  297. !HLStackListWidget methodsFor: 'rendering'!
  298. renderButtonsOn: html
  299. html div
  300. class: 'debugger_bar';
  301. with: [
  302. html button
  303. class: 'btn restart';
  304. with: 'Restart';
  305. onClick: [ self restart ].
  306. html button
  307. class: 'btn stepOver';
  308. with: 'Step over';
  309. onClick: [ self stepOver ] ]
  310. ! !