1 | class SourceBuffer {
|
2 | constructor () {
|
3 | this.buffer = []
|
4 | this.locationMap = []
|
5 | this.line = 1
|
6 | this.column = 1
|
7 | this.indention = 0
|
8 | this.indentionSize = 2
|
9 | }
|
10 |
|
11 | write (str, defaultValue) {
|
12 | if (!str) {
|
13 | if (defaultValue) {
|
14 | this.write(defaultValue)
|
15 | }
|
16 |
|
17 | return this
|
18 | }
|
19 |
|
20 | if (typeof str === 'object') {
|
21 | str.compile(this)
|
22 | return this
|
23 | }
|
24 |
|
25 | const lastIndex = str.lastIndexOf('\n')
|
26 | if (lastIndex === -1) {
|
27 | this.column += str.length
|
28 | } else {
|
29 | this.column = str.length - lastIndex
|
30 | this.line += (str.split('\n').length - 1)
|
31 | }
|
32 |
|
33 | this.buffer.push(str)
|
34 | return this
|
35 | }
|
36 |
|
37 | writeItem (item) {
|
38 | if (item.leadingComments && item.leadingComments.length) {
|
39 | this.writeComments(item.leadingComments)
|
40 | this.indent()
|
41 | }
|
42 |
|
43 | item.compile(this)
|
44 |
|
45 | if (item.trailingComments && item.trailingComments.length) {
|
46 | this.indent()
|
47 | this.writeComments(item.trailingComments)
|
48 | }
|
49 | }
|
50 |
|
51 | writeComments (comments, joiner) {
|
52 | if (comments && comments.length > 0) {
|
53 | comments.forEach((comment, index) => {
|
54 | if (index) {
|
55 | joiner === undefined ? this.indent() : this.write(joiner)
|
56 | }
|
57 |
|
58 | this.write(comment)
|
59 | })
|
60 | }
|
61 | }
|
62 |
|
63 | nl (num = 1) {
|
64 | this.line += num
|
65 | this.column = 1
|
66 |
|
67 | this.buffer.push('\n'.repeat(num))
|
68 | return this
|
69 | }
|
70 |
|
71 | getLocation () {
|
72 | return [ this.line, this.column ]
|
73 | }
|
74 |
|
75 | getIndent () {
|
76 |
|
77 | return '\n' + ' '.repeat(this.indention * this.indentionSize)
|
78 | }
|
79 |
|
80 | indent (size, noWrite) {
|
81 | size = size || 0
|
82 | this.indention += size
|
83 |
|
84 | if (!noWrite) {
|
85 | this.write(this.getIndent())
|
86 | }
|
87 | }
|
88 |
|
89 | item (node) {
|
90 | node.compile(this)
|
91 | return this
|
92 | }
|
93 |
|
94 | loop (arr, joiner = this.getIndent(), fn) {
|
95 | if (arr) {
|
96 | arr.forEach((item, index) => {
|
97 | if (index > 0) {
|
98 | this.write(joiner)
|
99 | }
|
100 |
|
101 | this.writeItem(item)
|
102 | })
|
103 | }
|
104 |
|
105 | return this
|
106 | }
|
107 |
|
108 | registerItem (origLocation, name) {
|
109 | if (origLocation) {
|
110 | const map = [
|
111 | origLocation.line,
|
112 | origLocation.column,
|
113 | this.line,
|
114 | this.column
|
115 | ]
|
116 |
|
117 | if (typeof name === 'string') {
|
118 | map.push(name)
|
119 | }
|
120 |
|
121 | this.locationMap.push(map)
|
122 | }
|
123 |
|
124 | return this
|
125 | }
|
126 |
|
127 | toString () {
|
128 | return this.buffer.join('')
|
129 | }
|
130 |
|
131 | print () {
|
132 | console.log(this.buffer.slice(-5))
|
133 | }
|
134 |
|
135 | createLocationMap () {
|
136 | if (this.locationMap.length === 0) {
|
137 | return
|
138 | }
|
139 |
|
140 | this.write('module.exports.__fsLocationMap = [')
|
141 | this.write(this.locationMap.map((item) => {
|
142 | const args = item.slice(0, 4)
|
143 | if (item[4]) {
|
144 | args.push(`'${item[4].replace(/'/g, '\\\'')}'`)
|
145 | }
|
146 |
|
147 | return `[${args.join(', ')}]`
|
148 | }).join(', '))
|
149 |
|
150 | this.write('];')
|
151 | }
|
152 | }
|
153 |
|
154 | module.exports = SourceBuffer
|