diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js b/Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js new file mode 100644 index 000000000..a60a27e32 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2015 Tobias Reiss <tobi+webkit@basecode.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +FormatterContentBuilder = class FormatterContentBuilder +{ + constructor(indentString) + { + this._originalContent = null; + this._formattedContent = []; + this._formattedContentLength = 0; + + this._startOfLine = true; + this.lastTokenWasNewline = false; + this.lastTokenWasWhitespace = false; + this.lastNewlineAppendWasMultiple = false; + + this._indent = 0; + this._indentString = indentString; + this._indentCache = ["", this._indentString]; + + this._mapping = {original: [0], formatted: [0]}; + this._originalLineEndings = []; + this._formattedLineEndings = []; + this._originalOffset = 0; + this._formattedOffset = 0; + + this._lastOriginalPosition = 0; + this._lastFormattedPosition = 0; + } + + // Public + + get originalContent() + { + return this._originalContent; + } + + get formattedContent() + { + let formatted = this._formattedContent.join(""); + console.assert(formatted.length === this._formattedContentLength); + return formatted; + } + + get sourceMapData() + { + return { + mapping: this._mapping, + originalLineEndings: this._originalLineEndings, + formattedLineEndings: this._formattedLineEndings, + }; + } + + setOriginalContent(originalContent) + { + console.assert(!this._originalContent); + this._originalContent = originalContent; + } + + setOriginalLineEndings(originalLineEndings) + { + console.assert(!this._originalLineEndings.length); + this._originalLineEndings = originalLineEndings; + } + + appendToken(string, originalPosition) + { + if (this._startOfLine) + this._appendIndent(); + + this._addMappingIfNeeded(originalPosition); + + this._append(string); + this._startOfLine = false; + this.lastTokenWasNewline = false; + this.lastTokenWasWhitespace = false; + } + + appendSpace() + { + if (!this._startOfLine) { + this._append(" "); + this.lastTokenWasNewline = false; + this.lastTokenWasWhitespace = true; + } + } + + appendNewline(force) + { + if ((!this.lastTokenWasNewline && !this._startOfLine) || force) { + if (this.lastTokenWasWhitespace) + this._popFormattedContent(); + this._append("\n"); + this._addFormattedLineEnding(); + this._startOfLine = true; + this.lastTokenWasNewline = true; + this.lastTokenWasWhitespace = false; + this.lastNewlineAppendWasMultiple = false; + } + } + + appendMultipleNewlines(newlines) + { + console.assert(newlines > 0); + + let wasMultiple = newlines > 1; + + while (newlines-- > 0) + this.appendNewline(true); + + if (wasMultiple) + this.lastNewlineAppendWasMultiple = true; + } + + removeLastNewline() + { + console.assert(this.lastTokenWasNewline); + console.assert(this._formattedContent.lastValue === "\n"); + if (this.lastTokenWasNewline) { + this._popFormattedContent(); + this._formattedLineEndings.pop(); + this._startOfLine = false; + this.lastTokenWasNewline = false; + this.lastTokenWasWhitespace = false; + } + } + + removeLastWhitespace() + { + console.assert(this.lastTokenWasWhitespace); + console.assert(this._formattedContent.lastValue === " "); + if (this.lastTokenWasWhitespace) { + this._popFormattedContent(); + // No need to worry about `_startOfLine` and `lastTokenWasNewline` + // because `appendSpace` takes care of not adding whitespace + // to the beginning of a line. + this.lastTokenWasWhitespace = false; + } + } + + indent() + { + ++this._indent; + } + + dedent() + { + --this._indent; + + console.assert(this._indent >= 0); + if (this._indent < 0) + this._indent = 0; + } + + addOriginalLineEnding(originalPosition) + { + this._originalLineEndings.push(originalPosition); + } + + finish() + { + this.appendNewline(); + } + + // Private + + _popFormattedContent() + { + let removed = this._formattedContent.pop(); + this._formattedContentLength -= removed.length; + } + + _append(str) + { + this._formattedContent.push(str); + this._formattedContentLength += str.length; + } + + _appendIndent() + { + // Indent is already in the cache. + if (this._indent < this._indentCache.length) { + this._append(this._indentCache[this._indent]); + return; + } + + // Indent was not in the cache, fill up the cache up with what was needed. + let maxCacheIndent = 20; + let max = Math.min(this._indent, maxCacheIndent); + for (let i = this._indentCache.length; i <= max; ++i) + this._indentCache[i] = this._indentCache[i - 1] + this._indentString; + + // Append indents as needed. + let indent = this._indent; + do { + if (indent >= maxCacheIndent) + this._append(this._indentCache[maxCacheIndent]); + else + this._append(this._indentCache[indent]); + indent -= maxCacheIndent; + } while (indent > 0); + } + + _addMappingIfNeeded(originalPosition) + { + if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition) + return; + + this._mapping.original.push(this._originalOffset + originalPosition); + this._mapping.formatted.push(this._formattedOffset + this._formattedContentLength); + + this._lastOriginalPosition = originalPosition; + this._lastFormattedPosition = this._formattedContentLength; + } + + _addFormattedLineEnding() + { + console.assert(this._formattedContent.lastValue === "\n"); + this._formattedLineEndings.push(this._formattedContentLength - 1); + } +}; |