123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.concat = exports.fromString = exports.countSpaces = exports.Lines = void 0;
- var tslib_1 = require("tslib");
- var assert_1 = tslib_1.__importDefault(require("assert"));
- var source_map_1 = tslib_1.__importDefault(require("source-map"));
- var options_1 = require("./options");
- var util_1 = require("./util");
- var mapping_1 = tslib_1.__importDefault(require("./mapping"));
- var Lines = /** @class */ (function () {
- function Lines(infos, sourceFileName) {
- if (sourceFileName === void 0) { sourceFileName = null; }
- this.infos = infos;
- this.mappings = [];
- this.cachedSourceMap = null;
- this.cachedTabWidth = void 0;
- assert_1.default.ok(infos.length > 0);
- this.length = infos.length;
- this.name = sourceFileName || null;
- if (this.name) {
- this.mappings.push(new mapping_1.default(this, {
- start: this.firstPos(),
- end: this.lastPos(),
- }));
- }
- }
- Lines.prototype.toString = function (options) {
- return this.sliceString(this.firstPos(), this.lastPos(), options);
- };
- Lines.prototype.getSourceMap = function (sourceMapName, sourceRoot) {
- if (!sourceMapName) {
- // Although we could make up a name or generate an anonymous
- // source map, instead we assume that any consumer who does not
- // provide a name does not actually want a source map.
- return null;
- }
- var targetLines = this;
- function updateJSON(json) {
- json = json || {};
- json.file = sourceMapName;
- if (sourceRoot) {
- json.sourceRoot = sourceRoot;
- }
- return json;
- }
- if (targetLines.cachedSourceMap) {
- // Since Lines objects are immutable, we can reuse any source map
- // that was previously generated. Nevertheless, we return a new
- // JSON object here to protect the cached source map from outside
- // modification.
- return updateJSON(targetLines.cachedSourceMap.toJSON());
- }
- var smg = new source_map_1.default.SourceMapGenerator(updateJSON());
- var sourcesToContents = {};
- targetLines.mappings.forEach(function (mapping) {
- var sourceCursor = mapping.sourceLines.skipSpaces(mapping.sourceLoc.start) ||
- mapping.sourceLines.lastPos();
- var targetCursor = targetLines.skipSpaces(mapping.targetLoc.start) ||
- targetLines.lastPos();
- while ((0, util_1.comparePos)(sourceCursor, mapping.sourceLoc.end) < 0 &&
- (0, util_1.comparePos)(targetCursor, mapping.targetLoc.end) < 0) {
- var sourceChar = mapping.sourceLines.charAt(sourceCursor);
- var targetChar = targetLines.charAt(targetCursor);
- assert_1.default.strictEqual(sourceChar, targetChar);
- var sourceName = mapping.sourceLines.name;
- // Add mappings one character at a time for maximum resolution.
- smg.addMapping({
- source: sourceName,
- original: { line: sourceCursor.line, column: sourceCursor.column },
- generated: { line: targetCursor.line, column: targetCursor.column },
- });
- if (!hasOwn.call(sourcesToContents, sourceName)) {
- var sourceContent = mapping.sourceLines.toString();
- smg.setSourceContent(sourceName, sourceContent);
- sourcesToContents[sourceName] = sourceContent;
- }
- targetLines.nextPos(targetCursor, true);
- mapping.sourceLines.nextPos(sourceCursor, true);
- }
- });
- targetLines.cachedSourceMap = smg;
- return smg.toJSON();
- };
- Lines.prototype.bootstrapCharAt = function (pos) {
- assert_1.default.strictEqual(typeof pos, "object");
- assert_1.default.strictEqual(typeof pos.line, "number");
- assert_1.default.strictEqual(typeof pos.column, "number");
- var line = pos.line, column = pos.column, strings = this.toString().split(lineTerminatorSeqExp), string = strings[line - 1];
- if (typeof string === "undefined")
- return "";
- if (column === string.length && line < strings.length)
- return "\n";
- if (column >= string.length)
- return "";
- return string.charAt(column);
- };
- Lines.prototype.charAt = function (pos) {
- assert_1.default.strictEqual(typeof pos, "object");
- assert_1.default.strictEqual(typeof pos.line, "number");
- assert_1.default.strictEqual(typeof pos.column, "number");
- var line = pos.line, column = pos.column, secret = this, infos = secret.infos, info = infos[line - 1], c = column;
- if (typeof info === "undefined" || c < 0)
- return "";
- var indent = this.getIndentAt(line);
- if (c < indent)
- return " ";
- c += info.sliceStart - indent;
- if (c === info.sliceEnd && line < this.length)
- return "\n";
- if (c >= info.sliceEnd)
- return "";
- return info.line.charAt(c);
- };
- Lines.prototype.stripMargin = function (width, skipFirstLine) {
- if (width === 0)
- return this;
- assert_1.default.ok(width > 0, "negative margin: " + width);
- if (skipFirstLine && this.length === 1)
- return this;
- var lines = new Lines(this.infos.map(function (info, i) {
- if (info.line && (i > 0 || !skipFirstLine)) {
- info = tslib_1.__assign(tslib_1.__assign({}, info), { indent: Math.max(0, info.indent - width) });
- }
- return info;
- }));
- if (this.mappings.length > 0) {
- var newMappings_1 = lines.mappings;
- assert_1.default.strictEqual(newMappings_1.length, 0);
- this.mappings.forEach(function (mapping) {
- newMappings_1.push(mapping.indent(width, skipFirstLine, true));
- });
- }
- return lines;
- };
- Lines.prototype.indent = function (by) {
- if (by === 0) {
- return this;
- }
- var lines = new Lines(this.infos.map(function (info) {
- if (info.line && !info.locked) {
- info = tslib_1.__assign(tslib_1.__assign({}, info), { indent: info.indent + by });
- }
- return info;
- }));
- if (this.mappings.length > 0) {
- var newMappings_2 = lines.mappings;
- assert_1.default.strictEqual(newMappings_2.length, 0);
- this.mappings.forEach(function (mapping) {
- newMappings_2.push(mapping.indent(by));
- });
- }
- return lines;
- };
- Lines.prototype.indentTail = function (by) {
- if (by === 0) {
- return this;
- }
- if (this.length < 2) {
- return this;
- }
- var lines = new Lines(this.infos.map(function (info, i) {
- if (i > 0 && info.line && !info.locked) {
- info = tslib_1.__assign(tslib_1.__assign({}, info), { indent: info.indent + by });
- }
- return info;
- }));
- if (this.mappings.length > 0) {
- var newMappings_3 = lines.mappings;
- assert_1.default.strictEqual(newMappings_3.length, 0);
- this.mappings.forEach(function (mapping) {
- newMappings_3.push(mapping.indent(by, true));
- });
- }
- return lines;
- };
- Lines.prototype.lockIndentTail = function () {
- if (this.length < 2) {
- return this;
- }
- return new Lines(this.infos.map(function (info, i) { return (tslib_1.__assign(tslib_1.__assign({}, info), { locked: i > 0 })); }));
- };
- Lines.prototype.getIndentAt = function (line) {
- assert_1.default.ok(line >= 1, "no line " + line + " (line numbers start from 1)");
- return Math.max(this.infos[line - 1].indent, 0);
- };
- Lines.prototype.guessTabWidth = function () {
- if (typeof this.cachedTabWidth === "number") {
- return this.cachedTabWidth;
- }
- var counts = []; // Sparse array.
- var lastIndent = 0;
- for (var line = 1, last = this.length; line <= last; ++line) {
- var info = this.infos[line - 1];
- var sliced = info.line.slice(info.sliceStart, info.sliceEnd);
- // Whitespace-only lines don't tell us much about the likely tab
- // width of this code.
- if (isOnlyWhitespace(sliced)) {
- continue;
- }
- var diff = Math.abs(info.indent - lastIndent);
- counts[diff] = ~~counts[diff] + 1;
- lastIndent = info.indent;
- }
- var maxCount = -1;
- var result = 2;
- for (var tabWidth = 1; tabWidth < counts.length; tabWidth += 1) {
- if (hasOwn.call(counts, tabWidth) && counts[tabWidth] > maxCount) {
- maxCount = counts[tabWidth];
- result = tabWidth;
- }
- }
- return (this.cachedTabWidth = result);
- };
- // Determine if the list of lines has a first line that starts with a //
- // or /* comment. If this is the case, the code may need to be wrapped in
- // parens to avoid ASI issues.
- Lines.prototype.startsWithComment = function () {
- if (this.infos.length === 0) {
- return false;
- }
- var firstLineInfo = this.infos[0], sliceStart = firstLineInfo.sliceStart, sliceEnd = firstLineInfo.sliceEnd, firstLine = firstLineInfo.line.slice(sliceStart, sliceEnd).trim();
- return (firstLine.length === 0 ||
- firstLine.slice(0, 2) === "//" ||
- firstLine.slice(0, 2) === "/*");
- };
- Lines.prototype.isOnlyWhitespace = function () {
- return isOnlyWhitespace(this.toString());
- };
- Lines.prototype.isPrecededOnlyByWhitespace = function (pos) {
- var info = this.infos[pos.line - 1];
- var indent = Math.max(info.indent, 0);
- var diff = pos.column - indent;
- if (diff <= 0) {
- // If pos.column does not exceed the indentation amount, then
- // there must be only whitespace before it.
- return true;
- }
- var start = info.sliceStart;
- var end = Math.min(start + diff, info.sliceEnd);
- var prefix = info.line.slice(start, end);
- return isOnlyWhitespace(prefix);
- };
- Lines.prototype.getLineLength = function (line) {
- var info = this.infos[line - 1];
- return this.getIndentAt(line) + info.sliceEnd - info.sliceStart;
- };
- Lines.prototype.nextPos = function (pos, skipSpaces) {
- if (skipSpaces === void 0) { skipSpaces = false; }
- var l = Math.max(pos.line, 0), c = Math.max(pos.column, 0);
- if (c < this.getLineLength(l)) {
- pos.column += 1;
- return skipSpaces ? !!this.skipSpaces(pos, false, true) : true;
- }
- if (l < this.length) {
- pos.line += 1;
- pos.column = 0;
- return skipSpaces ? !!this.skipSpaces(pos, false, true) : true;
- }
- return false;
- };
- Lines.prototype.prevPos = function (pos, skipSpaces) {
- if (skipSpaces === void 0) { skipSpaces = false; }
- var l = pos.line, c = pos.column;
- if (c < 1) {
- l -= 1;
- if (l < 1)
- return false;
- c = this.getLineLength(l);
- }
- else {
- c = Math.min(c - 1, this.getLineLength(l));
- }
- pos.line = l;
- pos.column = c;
- return skipSpaces ? !!this.skipSpaces(pos, true, true) : true;
- };
- Lines.prototype.firstPos = function () {
- // Trivial, but provided for completeness.
- return { line: 1, column: 0 };
- };
- Lines.prototype.lastPos = function () {
- return {
- line: this.length,
- column: this.getLineLength(this.length),
- };
- };
- Lines.prototype.skipSpaces = function (pos, backward, modifyInPlace) {
- if (backward === void 0) { backward = false; }
- if (modifyInPlace === void 0) { modifyInPlace = false; }
- if (pos) {
- pos = modifyInPlace
- ? pos
- : {
- line: pos.line,
- column: pos.column,
- };
- }
- else if (backward) {
- pos = this.lastPos();
- }
- else {
- pos = this.firstPos();
- }
- if (backward) {
- while (this.prevPos(pos)) {
- if (!isOnlyWhitespace(this.charAt(pos)) && this.nextPos(pos)) {
- return pos;
- }
- }
- return null;
- }
- else {
- while (isOnlyWhitespace(this.charAt(pos))) {
- if (!this.nextPos(pos)) {
- return null;
- }
- }
- return pos;
- }
- };
- Lines.prototype.trimLeft = function () {
- var pos = this.skipSpaces(this.firstPos(), false, true);
- return pos ? this.slice(pos) : emptyLines;
- };
- Lines.prototype.trimRight = function () {
- var pos = this.skipSpaces(this.lastPos(), true, true);
- return pos ? this.slice(this.firstPos(), pos) : emptyLines;
- };
- Lines.prototype.trim = function () {
- var start = this.skipSpaces(this.firstPos(), false, true);
- if (start === null) {
- return emptyLines;
- }
- var end = this.skipSpaces(this.lastPos(), true, true);
- if (end === null) {
- return emptyLines;
- }
- return this.slice(start, end);
- };
- Lines.prototype.eachPos = function (callback, startPos, skipSpaces) {
- if (startPos === void 0) { startPos = this.firstPos(); }
- if (skipSpaces === void 0) { skipSpaces = false; }
- var pos = this.firstPos();
- if (startPos) {
- (pos.line = startPos.line), (pos.column = startPos.column);
- }
- if (skipSpaces && !this.skipSpaces(pos, false, true)) {
- return; // Encountered nothing but spaces.
- }
- do
- callback.call(this, pos);
- while (this.nextPos(pos, skipSpaces));
- };
- Lines.prototype.bootstrapSlice = function (start, end) {
- var strings = this.toString()
- .split(lineTerminatorSeqExp)
- .slice(start.line - 1, end.line);
- if (strings.length > 0) {
- strings.push(strings.pop().slice(0, end.column));
- strings[0] = strings[0].slice(start.column);
- }
- return fromString(strings.join("\n"));
- };
- Lines.prototype.slice = function (start, end) {
- if (!end) {
- if (!start) {
- // The client seems to want a copy of this Lines object, but
- // Lines objects are immutable, so it's perfectly adequate to
- // return the same object.
- return this;
- }
- // Slice to the end if no end position was provided.
- end = this.lastPos();
- }
- if (!start) {
- throw new Error("cannot slice with end but not start");
- }
- var sliced = this.infos.slice(start.line - 1, end.line);
- if (start.line === end.line) {
- sliced[0] = sliceInfo(sliced[0], start.column, end.column);
- }
- else {
- assert_1.default.ok(start.line < end.line);
- sliced[0] = sliceInfo(sliced[0], start.column);
- sliced.push(sliceInfo(sliced.pop(), 0, end.column));
- }
- var lines = new Lines(sliced);
- if (this.mappings.length > 0) {
- var newMappings_4 = lines.mappings;
- assert_1.default.strictEqual(newMappings_4.length, 0);
- this.mappings.forEach(function (mapping) {
- var sliced = mapping.slice(this, start, end);
- if (sliced) {
- newMappings_4.push(sliced);
- }
- }, this);
- }
- return lines;
- };
- Lines.prototype.bootstrapSliceString = function (start, end, options) {
- return this.slice(start, end).toString(options);
- };
- Lines.prototype.sliceString = function (start, end, options) {
- if (start === void 0) { start = this.firstPos(); }
- if (end === void 0) { end = this.lastPos(); }
- var _a = (0, options_1.normalize)(options), tabWidth = _a.tabWidth, useTabs = _a.useTabs, reuseWhitespace = _a.reuseWhitespace, lineTerminator = _a.lineTerminator;
- var parts = [];
- for (var line = start.line; line <= end.line; ++line) {
- var info = this.infos[line - 1];
- if (line === start.line) {
- if (line === end.line) {
- info = sliceInfo(info, start.column, end.column);
- }
- else {
- info = sliceInfo(info, start.column);
- }
- }
- else if (line === end.line) {
- info = sliceInfo(info, 0, end.column);
- }
- var indent = Math.max(info.indent, 0);
- var before_1 = info.line.slice(0, info.sliceStart);
- if (reuseWhitespace &&
- isOnlyWhitespace(before_1) &&
- countSpaces(before_1, tabWidth) === indent) {
- // Reuse original spaces if the indentation is correct.
- parts.push(info.line.slice(0, info.sliceEnd));
- continue;
- }
- var tabs = 0;
- var spaces = indent;
- if (useTabs) {
- tabs = Math.floor(indent / tabWidth);
- spaces -= tabs * tabWidth;
- }
- var result = "";
- if (tabs > 0) {
- result += new Array(tabs + 1).join("\t");
- }
- if (spaces > 0) {
- result += new Array(spaces + 1).join(" ");
- }
- result += info.line.slice(info.sliceStart, info.sliceEnd);
- parts.push(result);
- }
- return parts.join(lineTerminator);
- };
- Lines.prototype.isEmpty = function () {
- return this.length < 2 && this.getLineLength(1) < 1;
- };
- Lines.prototype.join = function (elements) {
- var separator = this;
- var infos = [];
- var mappings = [];
- var prevInfo;
- function appendLines(linesOrNull) {
- if (linesOrNull === null) {
- return;
- }
- if (prevInfo) {
- var info = linesOrNull.infos[0];
- var indent = new Array(info.indent + 1).join(" ");
- var prevLine_1 = infos.length;
- var prevColumn_1 = Math.max(prevInfo.indent, 0) +
- prevInfo.sliceEnd -
- prevInfo.sliceStart;
- prevInfo.line =
- prevInfo.line.slice(0, prevInfo.sliceEnd) +
- indent +
- info.line.slice(info.sliceStart, info.sliceEnd);
- // If any part of a line is indentation-locked, the whole line
- // will be indentation-locked.
- prevInfo.locked = prevInfo.locked || info.locked;
- prevInfo.sliceEnd = prevInfo.line.length;
- if (linesOrNull.mappings.length > 0) {
- linesOrNull.mappings.forEach(function (mapping) {
- mappings.push(mapping.add(prevLine_1, prevColumn_1));
- });
- }
- }
- else if (linesOrNull.mappings.length > 0) {
- mappings.push.apply(mappings, linesOrNull.mappings);
- }
- linesOrNull.infos.forEach(function (info, i) {
- if (!prevInfo || i > 0) {
- prevInfo = tslib_1.__assign({}, info);
- infos.push(prevInfo);
- }
- });
- }
- function appendWithSeparator(linesOrNull, i) {
- if (i > 0)
- appendLines(separator);
- appendLines(linesOrNull);
- }
- elements
- .map(function (elem) {
- var lines = fromString(elem);
- if (lines.isEmpty())
- return null;
- return lines;
- })
- .forEach(function (linesOrNull, i) {
- if (separator.isEmpty()) {
- appendLines(linesOrNull);
- }
- else {
- appendWithSeparator(linesOrNull, i);
- }
- });
- if (infos.length < 1)
- return emptyLines;
- var lines = new Lines(infos);
- lines.mappings = mappings;
- return lines;
- };
- Lines.prototype.concat = function () {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- var list = [this];
- list.push.apply(list, args);
- assert_1.default.strictEqual(list.length, args.length + 1);
- return emptyLines.join(list);
- };
- return Lines;
- }());
- exports.Lines = Lines;
- var fromStringCache = {};
- var hasOwn = fromStringCache.hasOwnProperty;
- var maxCacheKeyLen = 10;
- function countSpaces(spaces, tabWidth) {
- var count = 0;
- var len = spaces.length;
- for (var i = 0; i < len; ++i) {
- switch (spaces.charCodeAt(i)) {
- case 9: {
- // '\t'
- assert_1.default.strictEqual(typeof tabWidth, "number");
- assert_1.default.ok(tabWidth > 0);
- var next = Math.ceil(count / tabWidth) * tabWidth;
- if (next === count) {
- count += tabWidth;
- }
- else {
- count = next;
- }
- break;
- }
- case 11: // '\v'
- case 12: // '\f'
- case 13: // '\r'
- case 0xfeff: // zero-width non-breaking space
- // These characters contribute nothing to indentation.
- break;
- case 32: // ' '
- default:
- // Treat all other whitespace like ' '.
- count += 1;
- break;
- }
- }
- return count;
- }
- exports.countSpaces = countSpaces;
- var leadingSpaceExp = /^\s*/;
- // As specified here: http://www.ecma-international.org/ecma-262/6.0/#sec-line-terminators
- var lineTerminatorSeqExp = /\u000D\u000A|\u000D(?!\u000A)|\u000A|\u2028|\u2029/;
- /**
- * @param {Object} options - Options object that configures printing.
- */
- function fromString(string, options) {
- if (string instanceof Lines)
- return string;
- string += "";
- var tabWidth = options && options.tabWidth;
- var tabless = string.indexOf("\t") < 0;
- var cacheable = !options && tabless && string.length <= maxCacheKeyLen;
- assert_1.default.ok(tabWidth || tabless, "No tab width specified but encountered tabs in string\n" + string);
- if (cacheable && hasOwn.call(fromStringCache, string))
- return fromStringCache[string];
- var lines = new Lines(string.split(lineTerminatorSeqExp).map(function (line) {
- // TODO: handle null exec result
- var spaces = leadingSpaceExp.exec(line)[0];
- return {
- line: line,
- indent: countSpaces(spaces, tabWidth),
- // Boolean indicating whether this line can be reindented.
- locked: false,
- sliceStart: spaces.length,
- sliceEnd: line.length,
- };
- }), (0, options_1.normalize)(options).sourceFileName);
- if (cacheable)
- fromStringCache[string] = lines;
- return lines;
- }
- exports.fromString = fromString;
- function isOnlyWhitespace(string) {
- return !/\S/.test(string);
- }
- function sliceInfo(info, startCol, endCol) {
- var sliceStart = info.sliceStart;
- var sliceEnd = info.sliceEnd;
- var indent = Math.max(info.indent, 0);
- var lineLength = indent + sliceEnd - sliceStart;
- if (typeof endCol === "undefined") {
- endCol = lineLength;
- }
- startCol = Math.max(startCol, 0);
- endCol = Math.min(endCol, lineLength);
- endCol = Math.max(endCol, startCol);
- if (endCol < indent) {
- indent = endCol;
- sliceEnd = sliceStart;
- }
- else {
- sliceEnd -= lineLength - endCol;
- }
- lineLength = endCol;
- lineLength -= startCol;
- if (startCol < indent) {
- indent -= startCol;
- }
- else {
- startCol -= indent;
- indent = 0;
- sliceStart += startCol;
- }
- assert_1.default.ok(indent >= 0);
- assert_1.default.ok(sliceStart <= sliceEnd);
- assert_1.default.strictEqual(lineLength, indent + sliceEnd - sliceStart);
- if (info.indent === indent &&
- info.sliceStart === sliceStart &&
- info.sliceEnd === sliceEnd) {
- return info;
- }
- return {
- line: info.line,
- indent: indent,
- // A destructive slice always unlocks indentation.
- locked: false,
- sliceStart: sliceStart,
- sliceEnd: sliceEnd,
- };
- }
- function concat(elements) {
- return emptyLines.join(elements);
- }
- exports.concat = concat;
- // The emptyLines object needs to be created all the way down here so that
- // Lines.prototype will be fully populated.
- var emptyLines = fromString("");
|