Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / sources / ScriptFormatter.js
blob8e72d27cb8842f97a06e77ed5e158132f7ce51d2
1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /**
32 * @interface
34 WebInspector.Formatter = function()
38 /**
39 * @param {!WebInspector.ResourceType} contentType
40 * @param {string} mimeType
41 * @param {string} content
42 * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
44 WebInspector.Formatter.format = function(contentType, mimeType, content, callback)
46 if (contentType === WebInspector.resourceTypes.Script || contentType === WebInspector.resourceTypes.Document || contentType === WebInspector.resourceTypes.Stylesheet)
47 new WebInspector.ScriptFormatter(mimeType, content, callback);
48 else
49 new WebInspector.IdentityFormatter(mimeType, content, callback);
52 /**
53 * @param {!Array.<number>} lineEndings
54 * @param {number} lineNumber
55 * @param {number} columnNumber
56 * @return {number}
58 WebInspector.Formatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
60 var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
61 return position + columnNumber;
64 /**
65 * @param {!Array.<number>} lineEndings
66 * @param {number} position
67 * @return {!Array.<number>}
69 WebInspector.Formatter.positionToLocation = function(lineEndings, position)
71 var lineNumber = lineEndings.upperBound(position - 1);
72 if (!lineNumber)
73 var columnNumber = position;
74 else
75 var columnNumber = position - lineEndings[lineNumber - 1] - 1;
76 return [lineNumber, columnNumber];
79 /**
80 * @constructor
81 * @implements {WebInspector.Formatter}
82 * @param {string} mimeType
83 * @param {string} content
84 * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
86 WebInspector.ScriptFormatter = function(mimeType, content, callback)
88 content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '');
89 this._callback = callback;
90 this._originalContent = content;
92 this._worker = new WorkerRuntime.Worker("script_formatter_worker");
93 this._worker.onmessage = this._didFormatContent.bind(this);
95 var parameters = {
96 mimeType: mimeType,
97 content: content,
98 indentString: WebInspector.moduleSetting("textEditorIndent").get()
100 this._worker.postMessage({ method: "format", params: parameters });
103 WebInspector.ScriptFormatter.prototype = {
105 * @param {!MessageEvent} event
107 _didFormatContent: function(event)
109 this._worker.terminate();
110 var originalContent = this._originalContent;
111 var formattedContent = event.data.content;
112 var mapping = event.data["mapping"];
113 var sourceMapping = new WebInspector.FormatterSourceMappingImpl(originalContent.lineEndings(), formattedContent.lineEndings(), mapping);
114 this._callback(formattedContent, sourceMapping);
119 * @constructor
120 * @implements {WebInspector.Formatter}
121 * @param {string} mimeType
122 * @param {string} content
123 * @param {function(string, !WebInspector.FormatterSourceMapping)} callback
125 WebInspector.IdentityFormatter = function(mimeType, content, callback)
127 callback(content, new WebInspector.IdentityFormatterSourceMapping());
131 * @typedef {{original: !Array.<number>, formatted: !Array.<number>}}
133 WebInspector.FormatterMappingPayload;
136 * @interface
138 WebInspector.FormatterSourceMapping = function()
142 WebInspector.FormatterSourceMapping.prototype = {
144 * @param {number} lineNumber
145 * @param {number=} columnNumber
146 * @return {!Array.<number>}
148 originalToFormatted: function(lineNumber, columnNumber) { },
151 * @param {number} lineNumber
152 * @param {number=} columnNumber
153 * @return {!Array.<number>}
155 formattedToOriginal: function(lineNumber, columnNumber) { }
159 * @constructor
160 * @implements {WebInspector.FormatterSourceMapping}
162 WebInspector.IdentityFormatterSourceMapping = function()
166 WebInspector.IdentityFormatterSourceMapping.prototype = {
168 * @override
169 * @param {number} lineNumber
170 * @param {number=} columnNumber
171 * @return {!Array.<number>}
173 originalToFormatted: function(lineNumber, columnNumber)
175 return [lineNumber, columnNumber || 0];
179 * @override
180 * @param {number} lineNumber
181 * @param {number=} columnNumber
182 * @return {!Array.<number>}
184 formattedToOriginal: function(lineNumber, columnNumber)
186 return [lineNumber, columnNumber || 0];
191 * @constructor
192 * @implements {WebInspector.FormatterSourceMapping}
193 * @param {!Array.<number>} originalLineEndings
194 * @param {!Array.<number>} formattedLineEndings
195 * @param {!WebInspector.FormatterMappingPayload} mapping
197 WebInspector.FormatterSourceMappingImpl = function(originalLineEndings, formattedLineEndings, mapping)
199 this._originalLineEndings = originalLineEndings;
200 this._formattedLineEndings = formattedLineEndings;
201 this._mapping = mapping;
204 WebInspector.FormatterSourceMappingImpl.prototype = {
206 * @override
207 * @param {number} lineNumber
208 * @param {number=} columnNumber
209 * @return {!Array.<number>}
211 originalToFormatted: function(lineNumber, columnNumber)
213 var originalPosition = WebInspector.Formatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber || 0);
214 var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition || 0);
215 return WebInspector.Formatter.positionToLocation(this._formattedLineEndings, formattedPosition);
219 * @override
220 * @param {number} lineNumber
221 * @param {number=} columnNumber
222 * @return {!Array.<number>}
224 formattedToOriginal: function(lineNumber, columnNumber)
226 var formattedPosition = WebInspector.Formatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber || 0);
227 var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
228 return WebInspector.Formatter.positionToLocation(this._originalLineEndings, originalPosition || 0);
232 * @param {!Array.<number>} positions1
233 * @param {!Array.<number>} positions2
234 * @param {number} position
235 * @return {number}
237 _convertPosition: function(positions1, positions2, position)
239 var index = positions1.upperBound(position) - 1;
240 var convertedPosition = positions2[index] + position - positions1[index];
241 if (index < positions2.length - 1 && convertedPosition > positions2[index + 1])
242 convertedPosition = positions2[index + 1];
243 return convertedPosition;