1 | const falafel = require('falafel')
|
2 | const debug = require('debug')('comment-value')
|
3 |
|
4 | function instrumentSource (source, filename) {
|
5 |
|
6 |
|
7 | const __instrumenter = global.__instrumenter || {
|
8 | comments: []
|
9 | }
|
10 |
|
11 | const endsBeforeInstrumentedComment = node =>
|
12 | __instrumenter.comments.some(c => c.start === node.end + 1)
|
13 | const findComment = node =>
|
14 | __instrumenter.comments.find(c => c.start === node.end + 1)
|
15 |
|
16 | function instrument (node) {
|
17 |
|
18 | if (node.type === 'ExpressionStatement' ||
|
19 | node.type === 'Identifier') {
|
20 |
|
21 | if (endsBeforeInstrumentedComment(node)) {
|
22 |
|
23 | const comment = findComment(node)
|
24 |
|
25 | const reference = 'global.__instrumenter.comments[' + comment.index + '].value'
|
26 | const store = reference + ' = ' + node.source()
|
27 | const storeAndReturn = ';(function () {' + store + '; return ' + reference + '}())'
|
28 | node.update(storeAndReturn)
|
29 | }
|
30 | }
|
31 | }
|
32 |
|
33 | const isInstrumentComment = s => s.startsWith('>')
|
34 |
|
35 | const parserOptions = {
|
36 | locations: true,
|
37 | onComment (block, text, start, end, from, to) {
|
38 | if (block) {
|
39 | return
|
40 | }
|
41 | if (!isInstrumentComment(text)) {
|
42 | return
|
43 | }
|
44 |
|
45 | const index = __instrumenter.comments.length
|
46 | __instrumenter.comments.push({
|
47 | value: undefined,
|
48 | start: start,
|
49 | text: text,
|
50 | index: index,
|
51 | from: from,
|
52 | to: to,
|
53 | filename: filename
|
54 | })
|
55 | }
|
56 | }
|
57 | const output = falafel(source, parserOptions, instrument)
|
58 | debug('instrumented for %d comments', __instrumenter.comments.length)
|
59 |
|
60 | const preamble = 'if (!global.__instrumenter) {global.__instrumenter=' +
|
61 | JSON.stringify(__instrumenter, null, 2) + '}\n'
|
62 |
|
63 |
|
64 |
|
65 | const sep = ';\n'
|
66 | const instrumented = preamble + sep + output
|
67 | return instrumented
|
68 | }
|
69 |
|
70 | module.exports = instrumentSource
|