Unreviewed, rolling out r152598.
[WebKit-https.git] / Source / WebInspectorUI / Tools / PrettyPrinting / FormatterContentBuilder.js
1 function FormatterContentBuilder(mapping, originalLineEndings, formattedLineEndings, originalOffset, formattedOffset, indentString)
2 {
3     this._originalContent = null;
4     this._formattedContent = [];
5     this._formattedContentLength = 0;
6
7     this._startOfLine = true;
8     this.lastTokenWasNewline = false;
9     this.lastTokenWasWhitespace = false;
10     this.lastNewlineAppendWasMultiple = false;
11
12     this._indent = 0;
13     this._indentString = indentString;
14     this._indentCache = ["", this._indentString];
15
16     this._mapping = mapping;
17     this._originalLineEndings = originalLineEndings || [];
18     this._formattedLineEndings = formattedLineEndings || [];
19     this._originalOffset = originalOffset || 0;
20     this._formattedOffset = formattedOffset || 0;
21
22     this._lastOriginalPosition = 0;
23     this._lastFormattedPosition = 0;
24 }
25
26 FormatterContentBuilder.prototype = {
27     constructor: FormatterContentBuilder,
28
29     // Public
30
31     get originalContent()
32     {
33         return this._originalContent;
34     },
35
36     get formattedContent()
37     {
38         var formatted = this._formattedContent.join("");
39         console.assert(formatted.length === this._formattedContentLength);
40         return formatted;
41     },
42
43     get mapping()
44     {
45         return this._mapping;
46     },
47
48     get originalLineEndings()
49     {
50         return this._originalLineEndings;
51     },
52
53     get formattedLineEndings()
54     {
55         return this._formattedLineEndings;
56     },
57
58     setOriginalContent: function(originalContent)
59     {
60         console.assert(!this._originalContent);
61         this._originalContent = originalContent;
62     },
63
64     appendToken: function(string, originalPosition)
65     {
66         if (this._startOfLine)
67             this._appendIndent();
68
69         this._addMappingIfNeeded(originalPosition);
70
71         this._append(string);
72         this._startOfLine = false;
73         this.lastTokenWasNewline = false;
74         this.lastTokenWasWhitespace = false;
75     },
76
77     appendSpace: function()
78     {
79         if (!this._startOfLine) {
80             this._append(" ");
81             this.lastTokenWasNewline = false;
82             this.lastTokenWasWhitespace = true;
83         }
84     },
85
86     appendNewline: function(force)
87     {
88         if ((!this.lastTokenWasNewline && !this._startOfLine) || force) {
89             this._append("\n");
90             this._addFormattedLineEnding();
91             this._startOfLine = true;
92             this.lastTokenWasNewline = true;
93             this.lastTokenWasWhitespace = false;
94             this.lastNewlineAppendWasMultiple = false;
95         }
96     },
97
98     appendMultipleNewlines: function(newlines)
99     {
100         console.assert(newlines > 0);
101
102         var wasMultiple = newlines > 1;
103
104         while (newlines-- > 0)
105             this.appendNewline(true);
106
107         if (wasMultiple)
108             this.lastNewlineAppendWasMultiple = true;
109     },
110
111     removeLastNewline: function()
112     {
113         console.assert(this.lastTokenWasNewline);
114         console.assert(this._formattedContent.lastValue === "\n");
115         if (this.lastTokenWasNewline) {
116             this._popNewLine();
117             this._startOfLine = false;
118             this.lastTokenWasNewline = false;
119             this.lastTokenWasWhitespace = false;
120         }
121     },
122
123     indent: function()
124     {
125         ++this._indent;
126     },
127
128     dedent: function()
129     {
130         --this._indent;
131
132         console.assert(this._indent >= 0);
133         if (this._indent < 0)
134             this._indent = 0;
135     },
136
137     addOriginalLineEnding: function(originalPosition)
138     {
139         this._originalLineEndings.push(originalPosition);
140     },
141
142     finish: function()
143     {
144         this.appendNewline();
145     },
146
147     // Private
148
149     _popNewLine: function()
150     {
151         var removed = this._formattedContent.pop();
152         this._formattedContentLength -= removed.length;
153         this._formattedLineEndings.pop();
154     },
155
156     _append: function(str)
157     {
158         this._formattedContent.push(str);
159         this._formattedContentLength += str.length;
160     },
161
162     _appendIndent: function()
163     {
164         // Indent is already in the cache.
165         if (this._indent < this._indentCache.length) {
166             this._append(this._indentCache[this._indent]);
167             return;
168         }
169
170         // Indent was not in the cache, fill up the cache up with what was needed.
171         const maxCacheIndent = 20;
172         var max = Math.min(this._indent, maxCacheIndent);
173         for (var i = this._indentCache.length; i <= max; ++i)
174             this._indentCache[i] = this._indentCache[i-1] + this._indentString;
175
176         // Append indents as needed.
177         var indent = this._indent;
178         do {
179             if (indent >= maxCacheIndent)
180                 this._append(this._indentCache[maxCacheIndent])
181             else
182                 this._append(this._indentCache[indent]);
183             indent -= maxCacheIndent;
184         } while (indent > 0);
185     },
186
187     _addMappingIfNeeded: function(originalPosition)
188     {
189         if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition)
190             return;
191
192         this._mapping.original.push(this._originalOffset + originalPosition);
193         this._mapping.formatted.push(this._formattedOffset + this._formattedContentLength);
194
195         this._lastOriginalPosition = originalPosition;
196         this._lastFormattedPosition = this._formattedContentLength;
197     },
198
199     _addFormattedLineEnding: function()
200     {
201         console.assert(this._formattedContent.lastValue === "\n");
202         this._formattedLineEndings.push(this._formattedContentLength - 1);
203     }
204 }