Hi Marcus, what is interesting is when you show the control flow graph overlaid over the AST, inter procedural analysis (i.e. follow the call graph) and thread or process-based decomposition if the code is run in parallel. This is some of the things I've done for a demo, and, yes, it doesn't take much time. Roassal is very cool for doing that :) Thierry 2015-07-24 8:57 GMT+02:00 Marcus Denker <marcus.denker@inria.fr>:
Hi,
Yesterday Alex and me played with using Roassal in combination with reflectivity.
Very quickly (within half an hour, even shorter) we had a view per class that shows coverage for ASTs as trees like this:
this is
| t | t := false. t ifTrue: [ self bar ] ifFalse: [ 'hello' ]. ^ 5
and you directly see that I have not yet added support for annotating optimized blocks⦠will come soon. (These views are nice for debugging reflectivityâ¦)
The code:
1) node-by-node coverage:
getCoverageOf: aPharoClass whileExecuting: aBlock " self new getCoverageOf: CoverageDemoTest whileExecuting: [ CoverageDemoTest new simpleAst ] "
| link | link := MetaLink new metaObject: #node; selector: #tagExecuted. aPharoClass methods do: [ :cm | cm ast nodesDo: [ :node | node link: link ] ]. aBlock value. ^ aPharoClass and the code for visalization:
renderCoverage | b | b := RTMondrian new.
b shape rectangle withTextAbove: #selector. b nodes: self methods forEach: [ :aMethod | b shape label text: [ :astNode | | aName | aName := astNode class name copyFrom: 3 to: astNode class name size. (aName endsWith: 'Node') ifTrue: [ aName copyFrom: 1 to: aName size - 'Node' size ] ifFalse: [ aName ] ] ; color: Color red; if: #hasBeenExecuted color: Color green. b nodes: aMethod ast allChildren. b edges connectFrom: #parent. b layout tree. ].
b layout flow. b build. ^ b view
A second example shows often executed nodes larger (shows another bug⦠the one largest should have the same size as the other large ones):
Code:
renderNodeExecutions | b | b := RTMondrian new.
b shape rectangle withTextAbove: #selector. b nodes: self methods forEach: [ :aMethod | b shape rectangle size: [ :astNode | astNode propertyAt: #nbExecutions ifAbsent: [ 0 ] ]. b nodes: aMethod ast allChildren. b edges connectFrom: #parent. b layout tree. ].
b layout flow. b build. ^ b view
getNodeExecution: aPharoClass whileExecuting: aBlock " self new getNodeExecution: CoverageDemoTest whileExecuting: [ 30 timesRepeat: [ CoverageDemoTest new simpleAst ] ] "
| link | link := MetaLink new metaObject: [ :node | | v | v := node propertyAt: #nbExecutions ifAbsentPut: [ 0 ]. node propertyAt: #nbExecutions put: v + 1 ]; selector: #value:; arguments: #(#node). aPharoClass methods do: [ :cm | cm ast nodesDo: [ :node | node link: link ] ]. aBlock value. ^ aPharoClass
These are just very quick and raw experiments⦠but they got us excited about the possibilities when this is all debugged and readyâ¦
Marcus