blob: fb031f6904324a1bc3b4bb9eabb6e0905c8f4be8 [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
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.
17 *
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.
29 */
Tim van der Lippefe5c3f72020-01-09 16:15:0230
Tim van der Lippe6f088c02020-01-23 18:09:1531import * as Common from '../common/common.js'; // eslint-disable-line no-unused-vars
Jack Franklin42895522020-02-28 11:40:5632import * as Platform from '../platform/platform.js';
Tim van der Lippe6f088c02020-01-23 18:09:1533
Tim van der Lippe1cf8e422020-03-12 16:09:2134import {FormatMapping, FormatResult, formatterWorkerPool} from './FormatterWorkerPool.js'; // eslint-disable-line no-unused-vars
Tim van der Lippefe5c3f72020-01-09 16:15:0235
Blink Reformat4c46d092018-04-07 15:32:3736/**
37 * @interface
38 */
Tim van der Lippe5368fbc2019-11-09 23:34:4639export class FormatterInterface {}
Blink Reformat4c46d092018-04-07 15:32:3740
41/**
Tim van der Lippe6f088c02020-01-23 18:09:1542 * @param {!Common.ResourceType.ResourceType} contentType
Blink Reformat4c46d092018-04-07 15:32:3743 * @param {string} mimeType
44 * @param {string} content
Tim van der Lippe5368fbc2019-11-09 23:34:4645 * @param {function(string, !FormatterSourceMapping)} callback
Blink Reformat4c46d092018-04-07 15:32:3746 */
Tim van der Lippe5368fbc2019-11-09 23:34:4647FormatterInterface.format = function(contentType, mimeType, content, callback) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3448 if (contentType.isDocumentOrScriptOrStyleSheet()) {
Tim van der Lippe5368fbc2019-11-09 23:34:4649 new ScriptFormatter(mimeType, content, callback);
Tim van der Lippe1d6e57a2019-09-30 11:55:3450 } else {
Tim van der Lippe5368fbc2019-11-09 23:34:4651 new ScriptIdentityFormatter(mimeType, content, callback);
Tim van der Lippe1d6e57a2019-09-30 11:55:3452 }
Blink Reformat4c46d092018-04-07 15:32:3753};
54
55/**
56 * @param {!Array<number>} lineEndings
57 * @param {number} lineNumber
58 * @param {number} columnNumber
59 * @return {number}
60 */
Tim van der Lippe5368fbc2019-11-09 23:34:4661FormatterInterface.locationToPosition = function(lineEndings, lineNumber, columnNumber) {
Blink Reformat4c46d092018-04-07 15:32:3762 const position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
63 return position + columnNumber;
64};
Blink Reformat4c46d092018-04-07 15:32:3765/**
66 * @param {!Array<number>} lineEndings
67 * @param {number} position
68 * @return {!Array<number>}
69 */
Tim van der Lippe5368fbc2019-11-09 23:34:4670FormatterInterface.positionToLocation = function(lineEndings, position) {
Blink Reformat4c46d092018-04-07 15:32:3771 const lineNumber = lineEndings.upperBound(position - 1);
72 let columnNumber;
Tim van der Lippe1d6e57a2019-09-30 11:55:3473 if (!lineNumber) {
Blink Reformat4c46d092018-04-07 15:32:3774 columnNumber = position;
Tim van der Lippe1d6e57a2019-09-30 11:55:3475 } else {
Blink Reformat4c46d092018-04-07 15:32:3776 columnNumber = position - lineEndings[lineNumber - 1] - 1;
Tim van der Lippe1d6e57a2019-09-30 11:55:3477 }
Blink Reformat4c46d092018-04-07 15:32:3778 return [lineNumber, columnNumber];
79};
80
81/**
Tim van der Lippe5368fbc2019-11-09 23:34:4682 * @implements {FormatterInterface}
Blink Reformat4c46d092018-04-07 15:32:3783 * @unrestricted
84 */
Tim van der Lippe5368fbc2019-11-09 23:34:4685export class ScriptFormatter {
Blink Reformat4c46d092018-04-07 15:32:3786 /**
87 * @param {string} mimeType
88 * @param {string} content
Tim van der Lippe5368fbc2019-11-09 23:34:4689 * @param {function(string, !FormatterSourceMapping)} callback
Blink Reformat4c46d092018-04-07 15:32:3790 */
91 constructor(mimeType, content, callback) {
92 content = content.replace(/\r\n?|[\n\u2028\u2029]/g, '\n').replace(/^\uFEFF/, '');
93 this._callback = callback;
94 this._originalContent = content;
95
Tim van der Lippefe5c3f72020-01-09 16:15:0296 formatterWorkerPool()
Paul Lewis4b64b3f2020-01-23 11:41:2097 .format(mimeType, content, self.Common.settings.moduleSetting('textEditorIndent').get())
Blink Reformat4c46d092018-04-07 15:32:3798 .then(this._didFormatContent.bind(this));
99 }
100
101 /**
Tim van der Lippefe5c3f72020-01-09 16:15:02102 * @param {!FormatResult} formatResult
Blink Reformat4c46d092018-04-07 15:32:37103 */
104 _didFormatContent(formatResult) {
Jack Franklin42895522020-02-28 11:40:56105 const originalContentLineEndings = Platform.StringUtilities.findLineEndingIndexes(this._originalContent);
106 const formattedContentLineEndings = Platform.StringUtilities.findLineEndingIndexes(formatResult.content);
107
108 const sourceMapping =
109 new FormatterSourceMappingImpl(originalContentLineEndings, formattedContentLineEndings, formatResult.mapping);
Blink Reformat4c46d092018-04-07 15:32:37110 this._callback(formatResult.content, sourceMapping);
111 }
Tim van der Lippe5368fbc2019-11-09 23:34:46112}
Blink Reformat4c46d092018-04-07 15:32:37113
114/**
Tim van der Lippe5368fbc2019-11-09 23:34:46115 * @implements {FormatterInterface}
Blink Reformat4c46d092018-04-07 15:32:37116 * @unrestricted
117 */
Tim van der Lippec96ccd92019-11-29 16:23:54118class ScriptIdentityFormatter {
Blink Reformat4c46d092018-04-07 15:32:37119 /**
120 * @param {string} mimeType
121 * @param {string} content
Tim van der Lippe5368fbc2019-11-09 23:34:46122 * @param {function(string, !FormatterSourceMapping)} callback
Blink Reformat4c46d092018-04-07 15:32:37123 */
124 constructor(mimeType, content, callback) {
Tim van der Lippe5368fbc2019-11-09 23:34:46125 callback(content, new IdentityFormatterSourceMapping());
Blink Reformat4c46d092018-04-07 15:32:37126 }
Tim van der Lippe5368fbc2019-11-09 23:34:46127}
Blink Reformat4c46d092018-04-07 15:32:37128
129/**
130 * @interface
131 */
Tim van der Lippe5368fbc2019-11-09 23:34:46132export class FormatterSourceMapping {
Blink Reformat4c46d092018-04-07 15:32:37133 /**
134 * @param {number} lineNumber
135 * @param {number=} columnNumber
136 * @return {!Array.<number>}
137 */
Tim van der Lippe5368fbc2019-11-09 23:34:46138 originalToFormatted(lineNumber, columnNumber) {
139 }
Blink Reformat4c46d092018-04-07 15:32:37140
141 /**
142 * @param {number} lineNumber
143 * @param {number=} columnNumber
144 * @return {!Array.<number>}
145 */
Sigurd Schneider718eebb2019-10-10 10:14:57146 formattedToOriginal(lineNumber, columnNumber) {}
Tim van der Lippe5368fbc2019-11-09 23:34:46147}
Blink Reformat4c46d092018-04-07 15:32:37148
149/**
Tim van der Lippe5368fbc2019-11-09 23:34:46150 * @implements {FormatterSourceMapping}
Blink Reformat4c46d092018-04-07 15:32:37151 * @unrestricted
152 */
Tim van der Lippec96ccd92019-11-29 16:23:54153class IdentityFormatterSourceMapping {
Blink Reformat4c46d092018-04-07 15:32:37154 /**
155 * @override
156 * @param {number} lineNumber
157 * @param {number=} columnNumber
158 * @return {!Array.<number>}
159 */
160 originalToFormatted(lineNumber, columnNumber) {
161 return [lineNumber, columnNumber || 0];
162 }
163
164 /**
165 * @override
166 * @param {number} lineNumber
167 * @param {number=} columnNumber
168 * @return {!Array.<number>}
169 */
Sigurd Schneider718eebb2019-10-10 10:14:57170 formattedToOriginal(lineNumber, columnNumber) {
Blink Reformat4c46d092018-04-07 15:32:37171 return [lineNumber, columnNumber || 0];
172 }
Tim van der Lippe5368fbc2019-11-09 23:34:46173}
Blink Reformat4c46d092018-04-07 15:32:37174
175/**
Tim van der Lippe5368fbc2019-11-09 23:34:46176 * @implements {FormatterSourceMapping}
Blink Reformat4c46d092018-04-07 15:32:37177 * @unrestricted
178 */
Tim van der Lippec96ccd92019-11-29 16:23:54179class FormatterSourceMappingImpl {
Blink Reformat4c46d092018-04-07 15:32:37180 /**
181 * @param {!Array.<number>} originalLineEndings
182 * @param {!Array.<number>} formattedLineEndings
Tim van der Lippe1cf8e422020-03-12 16:09:21183 * @param {!FormatMapping} mapping
Blink Reformat4c46d092018-04-07 15:32:37184 */
185 constructor(originalLineEndings, formattedLineEndings, mapping) {
186 this._originalLineEndings = originalLineEndings;
187 this._formattedLineEndings = formattedLineEndings;
188 this._mapping = mapping;
189 }
190
191 /**
192 * @override
193 * @param {number} lineNumber
194 * @param {number=} columnNumber
195 * @return {!Array.<number>}
196 */
197 originalToFormatted(lineNumber, columnNumber) {
198 const originalPosition =
Tim van der Lippe5368fbc2019-11-09 23:34:46199 FormatterInterface.locationToPosition(this._originalLineEndings, lineNumber, columnNumber || 0);
Blink Reformat4c46d092018-04-07 15:32:37200 const formattedPosition =
201 this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition || 0);
Tim van der Lippe5368fbc2019-11-09 23:34:46202 return FormatterInterface.positionToLocation(this._formattedLineEndings, formattedPosition);
Blink Reformat4c46d092018-04-07 15:32:37203 }
204
205 /**
206 * @override
207 * @param {number} lineNumber
208 * @param {number=} columnNumber
209 * @return {!Array.<number>}
210 */
Sigurd Schneider718eebb2019-10-10 10:14:57211 formattedToOriginal(lineNumber, columnNumber) {
Blink Reformat4c46d092018-04-07 15:32:37212 const formattedPosition =
Tim van der Lippe5368fbc2019-11-09 23:34:46213 FormatterInterface.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber || 0);
Blink Reformat4c46d092018-04-07 15:32:37214 const originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
Tim van der Lippe5368fbc2019-11-09 23:34:46215 return FormatterInterface.positionToLocation(this._originalLineEndings, originalPosition || 0);
Blink Reformat4c46d092018-04-07 15:32:37216 }
217
218 /**
219 * @param {!Array.<number>} positions1
220 * @param {!Array.<number>} positions2
221 * @param {number} position
222 * @return {number}
223 */
224 _convertPosition(positions1, positions2, position) {
225 const index = positions1.upperBound(position) - 1;
226 let convertedPosition = positions2[index] + position - positions1[index];
Tim van der Lippe1d6e57a2019-09-30 11:55:34227 if (index < positions2.length - 1 && convertedPosition > positions2[index + 1]) {
Blink Reformat4c46d092018-04-07 15:32:37228 convertedPosition = positions2[index + 1];
Tim van der Lippe1d6e57a2019-09-30 11:55:34229 }
Blink Reformat4c46d092018-04-07 15:32:37230 return convertedPosition;
231 }
Tim van der Lippe5368fbc2019-11-09 23:34:46232}