11import Trace from 'demos/tom/trace.js' ;
2+ import wrapAST from 'demos/tom/wrapAST.js' ;
23
34export default function ( { types : t } ) {
45 function error ( path , message ) {
56 throw path . buildCodeFrameError ( message ) ;
67 }
78
89 const returnVisitor = {
9- ReturnStatement ( path ) {
10+ ReturnStatement ( path , state ) {
1011 if ( path . node . alreadyVisited ) {
1112 return ;
1213 }
1314 path . node . alreadyVisited = true ;
14- const log = callOnTrace ( 'return' ) ;
15+
1516 const returnValue = path . node . argument ? path . node . argument : t . identifier ( 'undefined' ) ;
16- path . node . argument = t . sequenceExpression ( [ log , returnValue ] )
17+ const returnNode = callOnTrace ( 'return' , [ location ( path . node , state ) , returnValue ] ) ;
18+ path . node . argument = returnNode ;
1719 }
1820 }
1921
2022 function callOnTrace ( methodName , args = [ ] ) {
2123 return t . callExpression ( t . memberExpression ( t . identifier ( Trace . traceIdenifierName ) , t . identifier ( methodName ) ) ,
2224 args ) ;
2325 }
26+
27+ function location ( astNode , state ) {
28+ const filename = state . file . opts . filename ;
29+
30+ const start = astNode . loc . start ;
31+ const end = astNode . loc . end ;
32+
33+ const locationObject = {
34+ filename,
35+ startLine : start . line ,
36+ startColumn : start . column ,
37+ endLine : end . line ,
38+ endColumn : end . column
39+ }
40+
41+ const id = Trace . register ( locationObject ) ;
42+
43+ return t . numericLiteral ( id ) ;
44+ }
2445
25- function modifyFunction ( name , path ) {
46+ function modifyFunction ( name , path , state ) {
2647 const body = path . get ( 'body' ) ;
27- body . unshiftContainer ( 'body' , t . expressionStatement ( callOnTrace ( 'enterFunction' , [ t . stringLiteral ( name ) ] ) ) ) ;
28- body . pushContainer ( 'body' , t . expressionStatement ( callOnTrace ( 'leave' ) ) ) ;
29- path . traverse ( returnVisitor ) ;
48+ body . unshiftContainer ( 'body' , t . expressionStatement ( callOnTrace ( 'enterFunction' , [ location ( path . node , state ) , t . stringLiteral ( name ) ] ) ) ) ;
49+ body . pushContainer ( 'body' , t . expressionStatement ( callOnTrace ( 'leave' , [ location ( path . node , state ) ] ) ) ) ;
50+ path . traverse ( returnVisitor , state ) ;
3051 }
3152
3253 function resolveName ( callee ) {
@@ -42,7 +63,6 @@ export default function({ types: t }) {
4263 function nameFromCallExpression ( path ) {
4364 const callee = path . node . callee ;
4465 if ( callee . type === 'MemberExpression' ) {
45-
4666 return resolveName ( callee )
4767 } else {
4868 return callee . name || 'anonymous function' ;
@@ -52,28 +72,73 @@ export default function({ types: t }) {
5272 return {
5373 name : 'tracer' ,
5474 visitor : {
75+ Program ( path ) {
76+ // wrapAST(path.node, {notify(){console.log(...arguments)}})
77+ } ,
5578 CallExpression ( path ) {
5679 if ( path . node . alreadyVisited || path . isGenerated ( ) ) {
5780 return ;
5881 }
59- debugger
6082 const name = nameFromCallExpression ( path ) ;
6183 path . node . alreadyVisited = true ;
62- const log = callOnTrace ( 'aboutToEnter' , [ t . stringLiteral ( name ) ] ) ;
63- const sequence = t . sequenceExpression ( [ log , path . node ] ) ;
64- path . replaceWith ( t . expressionStatement ( sequence ) ) ;
84+ const log = callOnTrace ( 'aboutToEnter' , [ location ( path . node , this ) , t . stringLiteral ( name ) ] ) ;
85+ path . insertBefore ( log )
6586 } ,
6687 ArrowFunctionExpression ( path ) {
6788
6889 } ,
6990 "ClassMethod|ObjectMethod" ( path ) {
7091 const name = path . node . key . name ;
71- modifyFunction ( name , path ) ;
92+ modifyFunction ( name , path , this ) ;
7293 } ,
7394 "FunctionDeclaration|FunctionExpression" ( path ) {
7495 const id = path . node . id ;
7596 const name = id ? id . name : 'anonymous function' ;
76- modifyFunction ( name , path ) ;
97+ modifyFunction ( name , path , this ) ;
98+ } ,
99+ Loop ( path ) {
100+ path . insertBefore ( callOnTrace ( 'beginLoop' , [ location ( path . node , this ) , t . stringLiteral ( path . type ) ] ) )
101+ path . insertAfter ( callOnTrace ( 'endLoop' , [ location ( path . node , this ) ] ) )
102+ } ,
103+ ForStatement ( path ) {
104+ path . get ( 'body' ) . unshiftContainer ( 'body' , callOnTrace ( 'nextLoopIteration' , [ location ( path . node , this ) , ...path . node . init . declarations . map ( declaration => declaration . id ) ] ) ) ;
105+ } ,
106+ ForOfStatement ( path ) {
107+
108+ } ,
109+ ForInStatement ( path ) {
110+
111+ } ,
112+ Conditional ( path ) {
113+ if ( path . node . alreadyVisited ) {
114+ return ;
115+ }
116+
117+ path . node . alreadyVisited = true ;
118+
119+ path . node . test = callOnTrace ( 'conditionTest' , [
120+ location ( path . node . test , this ) ,
121+ path . node . test
122+ ] ) ;
123+
124+ // do not log else ifs
125+ if ( path . parent . type !== 'IfStatement' ) {
126+ path . insertBefore ( callOnTrace ( 'beginCondition' , [
127+ location ( path . node , this ) ,
128+ t . stringLiteral ( path . type )
129+ ] ) ) ;
130+ path . insertAfter ( callOnTrace ( 'endCondition' , [ location ( path . node , this ) ] ) ) ;
131+ }
132+ } ,
133+
134+ AssignmentExpression ( path ) {
135+ if ( path . isGenerated ( ) ) {
136+ return ;
137+ }
138+ path . node . right = callOnTrace ( 'assignment' , [
139+ location ( path . node , this ) ,
140+ t . stringLiteral ( resolveName ( path . node . left ) ) , path . node . right
141+ ] ) ;
77142 }
78143 }
79144 }
0 commit comments