diff --git a/front_end/script_formatter_worker/CSSFormatter.js b/front_end/script_formatter_worker/CSSFormatter.js index e7416965f2..04deab0e63 100644 --- a/front_end/script_formatter_worker/CSSFormatter.js +++ b/front_end/script_formatter_worker/CSSFormatter.js @@ -31,7 +31,7 @@ /** * @constructor * @param {string} content - * @param {!FormatterWorker.CSSFormattedContentBuilder} builder + * @param {!FormatterWorker.FormattedContentBuilder} builder */ FormatterWorker.CSSFormatter = function(content, builder) { @@ -52,7 +52,6 @@ FormatterWorker.CSSFormatter.prototype = { var line = lines[i]; tokenize(line, this._tokenCallback.bind(this, i)); } - this._builder.flushNewLines(true); }, /** @@ -71,7 +70,7 @@ FormatterWorker.CSSFormatter.prototype = { var isWhitespace = /^\s+$/.test(token); if (isWhitespace) { if (!this._state.eatWhitespace) - this._builder.addSpace(); + this._builder.addSoftSpace(); return; } this._state.eatWhitespace = false; @@ -80,10 +79,11 @@ FormatterWorker.CSSFormatter.prototype = { if (token !== "}") { if (this._state.afterClosingBrace) - this._builder.addNewLine(); + this._builder.addNewLine(true); this._state.afterClosingBrace = false; } var startPosition = (startLine ? this._lineEndings[startLine - 1] : 0) + startColumn; + var endLine = startLine + token.lineCount() - 1; if (token === "}") { if (this._state.inPropertyValue) this._builder.addNewLine(); @@ -91,21 +91,21 @@ FormatterWorker.CSSFormatter.prototype = { this._state.afterClosingBrace = true; this._state.inPropertyValue = false; } else if (token === ":" && !this._state.inPropertyValue && this._state.seenProperty) { - this._builder.addToken(token, startPosition, startLine, startColumn); - this._builder.addSpace(); + this._builder.addToken(token, startPosition, startLine, endLine); + this._builder.addSoftSpace(); this._state.eatWhitespace = true; this._state.inPropertyValue = true; this._state.seenProperty = false; return; } else if (token === "{") { - this._builder.addSpace(); - this._builder.addToken(token, startPosition, startLine, startColumn); + this._builder.addSoftSpace(); + this._builder.addToken(token, startPosition, startLine, endLine); this._builder.addNewLine(); this._builder.increaseNestingLevel(); return; } - this._builder.addToken(token, startPosition, startLine, startColumn); + this._builder.addToken(token, startPosition, startLine, endLine); if (type === "comment" && !this._state.inPropertyValue && !this._state.seenProperty) this._builder.addNewLine(); @@ -117,160 +117,3 @@ FormatterWorker.CSSFormatter.prototype = { } } } - -/** - * @constructor - * @param {string} content - * @param {!{original: !Array., formatted: !Array.}} mapping - * @param {number} originalOffset - * @param {number} formattedOffset - * @param {string} indentString - */ -FormatterWorker.CSSFormattedContentBuilder = function(content, mapping, originalOffset, formattedOffset, indentString) -{ - this._originalContent = content; - this._originalOffset = originalOffset; - this._lastOriginalPosition = 0; - - this._formattedContent = []; - this._formattedContentLength = 0; - this._formattedOffset = formattedOffset; - this._lastFormattedPosition = 0; - - this._mapping = mapping; - - this._lineNumber = 0; - this._nestingLevel = 0; - this._needNewLines = 0; - this._atLineStart = true; - this._indentString = indentString; - this._cachedIndents = {}; -} - -FormatterWorker.CSSFormattedContentBuilder.prototype = { - /** - * @param {string} token - * @param {number} startPosition - * @param {number} startLine - * @param {number} startColumn - */ - addToken: function(token, startPosition, startLine, startColumn) - { - if ((this._isWhitespaceRun || this._atLineStart) && /^\s+$/.test(token)) - return; - - if (this._isWhitespaceRun && this._lineNumber === startLine && !this._needNewLines) - this._addText(" "); - - this._isWhitespaceRun = false; - this._atLineStart = false; - - while (this._lineNumber < startLine) { - this._addText("\n"); - this._addIndent(); - this._needNewLines = 0; - this._lineNumber += 1; - this._atLineStart = true; - } - - if (this._needNewLines) { - this.flushNewLines(); - this._addIndent(); - this._atLineStart = true; - } - - this._addMappingIfNeeded(startPosition); - this._addText(token); - this._lineNumber = startLine; - }, - - addSpace: function() - { - if (this._isWhitespaceRun) - return; - this._isWhitespaceRun = true; - }, - - addNewLine: function() - { - ++this._needNewLines; - }, - - /** - * @param {boolean=} atLeastOne - */ - flushNewLines: function(atLeastOne) - { - var newLineCount = atLeastOne && !this._needNewLines ? 1 : this._needNewLines; - if (newLineCount) - this._isWhitespaceRun = false; - for (var i = 0; i < newLineCount; ++i) - this._addText("\n"); - this._needNewLines = 0; - }, - - increaseNestingLevel: function() - { - this._nestingLevel += 1; - }, - - /** - * @param {boolean=} addNewline - */ - decreaseNestingLevel: function(addNewline) - { - if (this._nestingLevel) - this._nestingLevel -= 1; - if (addNewline) - this.addNewLine(); - }, - - /** - * @return {string} - */ - content: function() - { - return this._formattedContent.join(""); - }, - - _addIndent: function() - { - if (this._cachedIndents[this._nestingLevel]) { - this._addText(this._cachedIndents[this._nestingLevel]); - return; - } - - var fullIndent = ""; - for (var i = 0; i < this._nestingLevel; ++i) - fullIndent += this._indentString; - this._addText(fullIndent); - - // Cache a maximum of 20 nesting level indents. - if (this._nestingLevel <= 20) - this._cachedIndents[this._nestingLevel] = fullIndent; - }, - - /** - * @param {string} text - */ - _addText: function(text) - { - if (!text) - return; - this._formattedContent.push(text); - this._formattedContentLength += text.length; - }, - - /** - * @param {number} originalPosition - */ - _addMappingIfNeeded: function(originalPosition) - { - if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition) - return; - this._mapping.original.push(this._originalOffset + originalPosition); - this._lastOriginalPosition = originalPosition; - this._mapping.formatted.push(this._formattedOffset + this._formattedContentLength); - this._lastFormattedPosition = this._formattedContentLength; - } -} diff --git a/front_end/script_formatter_worker/JavaScriptFormatter.js b/front_end/script_formatter_worker/JavaScriptFormatter.js index 15eab9e65f..f86c738440 100644 --- a/front_end/script_formatter_worker/JavaScriptFormatter.js +++ b/front_end/script_formatter_worker/JavaScriptFormatter.js @@ -31,7 +31,7 @@ /** * @constructor * @param {string} content - * @param {!FormatterWorker.JavaScriptFormattedContentBuilder} builder + * @param {!FormatterWorker.FormattedContentBuilder} builder */ FormatterWorker.JavaScriptFormatter = function(content, builder) { @@ -56,7 +56,9 @@ FormatterWorker.JavaScriptFormatter.prototype = { { for (var i = 0; i < format.length; ++i) { if (format[i] === "s") - this._builder.addSpace(); + this._builder.addSoftSpace(); + else if (format[i] === "S") + this._builder.addHardSpace(); else if (format[i] === "n") this._builder.addNewLine(); else if (format[i] === ">") @@ -182,7 +184,7 @@ FormatterWorker.JavaScriptFormatter.prototype = { var declarations = /** @type {!Array.} */(node.declarations); for (var i = 0; i < declarations.length; ++i) allVariablesInitialized = allVariablesInitialized && !!declarations[i].init; - return !this._inForLoopHeader(node) && allVariablesInitialized ? "nssts" : "ts"; + return !this._inForLoopHeader(node) && allVariablesInitialized ? "nSSts" : "ts"; } } else if (node.type === "BlockStatement") { if (AT.punctuator(token, "{")) @@ -297,15 +299,13 @@ FormatterWorker.JavaScriptFormatter.prototype = { /** * @constructor - * @param {string} content * @param {!{original: !Array., formatted: !Array.}} mapping * @param {number} originalOffset * @param {number} formattedOffset * @param {string} indentString */ -FormatterWorker.JavaScriptFormattedContentBuilder = function(content, mapping, originalOffset, formattedOffset, indentString) +FormatterWorker.FormattedContentBuilder = function(mapping, originalOffset, formattedOffset, indentString) { - this._originalContent = content; this._originalOffset = originalOffset; this._lastOriginalPosition = 0; @@ -319,10 +319,15 @@ FormatterWorker.JavaScriptFormattedContentBuilder = function(content, mapping, o this._lineNumber = 0; this._nestingLevel = 0; this._indentString = indentString; - this._cachedIndents = {}; + /** @type {!Map} */ + this._cachedIndents = new Map(); + + this._newLines = 0; + this._softSpace = false; + this._hardSpaces = 0; } -FormatterWorker.JavaScriptFormattedContentBuilder.prototype = { +FormatterWorker.FormattedContentBuilder.prototype = { /** * @param {string} token * @param {number} startPosition @@ -331,41 +336,42 @@ FormatterWorker.JavaScriptFormattedContentBuilder.prototype = { */ addToken: function(token, startPosition, startLine, endLine) { - while (this._lineNumber < startLine) { - this._addText("\n"); - this._addIndent(); - this._needNewLine = false; - this._lineNumber += 1; - } - - if (this._needNewLine) { - this._addText("\n"); - this._addIndent(); - this._needNewLine = false; - } + if (this._lineNumber < startLine) + this._newLines = Math.max(this._newLines, startLine - this._lineNumber); var last = this._formattedContent.peekLast(); if (last && /\w/.test(last[last.length - 1]) && /\w/.test(token)) - this.addSpace(); + this.addSoftSpace(); + + this._appendFormatting(); + // Insert token. this._addMappingIfNeeded(startPosition); this._addText(token); this._lineNumber = endLine; }, - addSpace: function() + addSoftSpace: function() { - if (this._needNewLine) { - this._addText("\n"); - this._addIndent(); - this._needNewLine = false; - } - this._addText(" "); + if (!this._hardSpaces) + this._softSpace = true; }, - addNewLine: function() + addHardSpace: function() + { + this._softSpace = false; + ++this._hardSpaces; + }, + + /** + * @param {boolean=} noSquash + */ + addNewLine: function(noSquash) { - this._needNewLine = true; + if (noSquash) + ++this._newLines; + else + this._newLines = this._newLines || 1; }, increaseNestingLevel: function() @@ -375,7 +381,26 @@ FormatterWorker.JavaScriptFormattedContentBuilder.prototype = { decreaseNestingLevel: function() { - this._nestingLevel -= 1; + if (this._nestingLevel > 0) + this._nestingLevel -= 1; + }, + + _appendFormatting: function() + { + if (this._newLines) { + for (var i = 0; i < this._newLines; ++i) + this._addText("\n"); + this._addText(this._indent()); + } else if (this._softSpace) { + this._addText(" "); + } + if (this._hardSpaces) { + for (var i = 0; i < this._hardSpaces; ++i) + this._addText(" "); + } + this._newLines = 0; + this._softSpace = false; + this._hardSpaces = 0; }, /** @@ -383,24 +408,26 @@ FormatterWorker.JavaScriptFormattedContentBuilder.prototype = { */ content: function() { - return this._formattedContent.join("") + (this._needNewLine ? "\n" : ""); + return this._formattedContent.join("") + (this._newLines ? "\n" : ""); }, - _addIndent: function() + /** + * @return {string} + */ + _indent: function() { - if (this._cachedIndents[this._nestingLevel]) { - this._addText(this._cachedIndents[this._nestingLevel]); - return; - } + var cachedValue = this._cachedIndents.get(this._nestingLevel) + if (cachedValue) + return cachedValue; var fullIndent = ""; for (var i = 0; i < this._nestingLevel; ++i) fullIndent += this._indentString; - this._addText(fullIndent); // Cache a maximum of 20 nesting level indents. if (this._nestingLevel <= 20) - this._cachedIndents[this._nestingLevel] = fullIndent; + this._cachedIndents.set(this._nestingLevel, fullIndent); + return fullIndent; }, /** diff --git a/front_end/script_formatter_worker/ScriptFormatterWorker.js b/front_end/script_formatter_worker/ScriptFormatterWorker.js index eeb4649747..9b2afc85f5 100644 --- a/front_end/script_formatter_worker/ScriptFormatterWorker.js +++ b/front_end/script_formatter_worker/ScriptFormatterWorker.js @@ -363,7 +363,7 @@ FormatterWorker._formatScript = function(content, mapping, offset, formattedOffs { var formattedContent; try { - var builder = new FormatterWorker.JavaScriptFormattedContentBuilder(content, mapping, offset, formattedOffset, indentString); + var builder = new FormatterWorker.FormattedContentBuilder(mapping, offset, formattedOffset, indentString); var formatter = new FormatterWorker.JavaScriptFormatter(content, builder); formatter.format(); formattedContent = builder.content(); @@ -386,7 +386,7 @@ FormatterWorker._formatCSS = function(content, mapping, offset, formattedOffset, { var formattedContent; try { - var builder = new FormatterWorker.CSSFormattedContentBuilder(content, mapping, offset, formattedOffset, indentString); + var builder = new FormatterWorker.FormattedContentBuilder(mapping, offset, formattedOffset, indentString); var formatter = new FormatterWorker.CSSFormatter(content, builder); formatter.format(); formattedContent = builder.content();