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