From f0871b53f1a4c33d9b6eaf1ed03e013ebdf9aa80 Mon Sep 17 00:00:00 2001 From: Dirk Wilden Date: Tue, 16 Mar 2021 13:42:32 +0100 Subject: [PATCH] make array generation configurable (fixes #260) --- escodegen.js | 97 ++++++++++++++++++++++++++++++++++++++++++------- test/options.js | 72 ++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 13 deletions(-) diff --git a/escodegen.js b/escodegen.js index 82417cd7..442d313b 100644 --- a/escodegen.js +++ b/escodegen.js @@ -56,6 +56,9 @@ parentheses, semicolons, safeConcatenation, + multilineArrayStartsInline, + maxArrayElementsPerLine, + arrayMaxLineWidth, directive, extra, parse, @@ -196,7 +199,12 @@ parentheses: true, semicolons: true, safeConcatenation: false, - preserveBlankLines: false + preserveBlankLines: false, + arrays: { + multilineArrayStartsInline: false, + maxElementsPerLine: 1, + maxLineWidth: 80 + } }, moz: { comprehensionExpressionStartsWithAssignment: false, @@ -2087,35 +2095,95 @@ }, ArrayExpression: function (expr, precedence, flags, isPattern) { - var result, multiline, that = this; + var result, multiline, currentLine, elementsInLine, that = this; if (!expr.elements.length) { return '[]'; } - multiline = isPattern ? false : expr.elements.length > 1; - result = ['[', multiline ? newline : '']; + + var i, iz; + + result = ['[']; + + for (i = 0, iz = expr.elements.length; i < iz; ++i) { + if (!expr.elements[i]) { + if (i + 1 === iz) { + result.push(','); + } + } else { + result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT)); + } + if (i + 1 < iz) { + result.push(',' + space); + } + } + + result.push(']'); + + var arrayLength = (base + toSourceNodeWhenNeeded(result).toString()).length; + multiline = !isPattern && (arrayLength > arrayMaxLineWidth || expr.elements.length > maxArrayElementsPerLine); + + if (!multiline) { + return result; + } + withIndent(function (indent) { - var i, iz; + + if (multilineArrayStartsInline) { + result = ['[']; + currentLine = base + '['; + } else { + result = ['[', newline, indent]; + currentLine = indent; + } + + elementsInLine = 0; + + var i, iz, content, contentPrefix, contentStr, exceedsMaxLength; + for (i = 0, iz = expr.elements.length; i < iz; ++i) { + + content = []; + if (!expr.elements[i]) { - if (multiline) { - result.push(indent); - } if (i + 1 === iz) { result.push(','); } } else { - result.push(multiline ? indent : ''); - result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT)); + content.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT)); } if (i + 1 < iz) { - result.push(',' + (multiline ? newline : space)); + content.push(','); } + + contentPrefix = (i > 0 ? space : ''); + contentStr = contentPrefix + toSourceNodeWhenNeeded(content).toString(); + exceedsMaxLength = (currentLine + contentStr.split(newline)[0]).length > arrayMaxLineWidth; + + if (exceedsMaxLength && currentLine === indent) { + // it will never fit + exceedsMaxLength = false; + } + + if (exceedsMaxLength || elementsInLine >= maxArrayElementsPerLine) { + result.push(newline + indent); + currentLine = indent; + elementsInLine = 1; + } else { + result.push(contentPrefix); + currentLine += contentPrefix + contentStr; + var lines = currentLine.split(newline) + currentLine = lines[lines.length-1]; + elementsInLine++; + } + + result.push(content); } }); - if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { + + if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) { result.push(newline); } - result.push(multiline ? base : ''); + result.push(base); result.push(']'); return result; }, @@ -2598,6 +2666,9 @@ parentheses = options.format.parentheses; semicolons = options.format.semicolons; safeConcatenation = options.format.safeConcatenation; + multilineArrayStartsInline = options.format.arrays.multilineArrayStartsInline; + maxArrayElementsPerLine = options.format.arrays.maxElementsPerLine; + arrayMaxLineWidth = options.format.arrays.maxLineWidth; directive = options.directive; parse = json ? null : options.parse; sourceMap = options.sourceMap; diff --git a/test/options.js b/test/options.js index 1acbced4..4e2c684a 100644 --- a/test/options.js +++ b/test/options.js @@ -958,6 +958,78 @@ data = [{ '!function(){42}': '!function\t()\t{\n 42\n}', '42;foo': '42;\nfoo' } +}, { + options: { + format: { + arrays: { + multilineArrayStartsInline: true, + maxElementsPerLine: 1, + maxLineWidth: 40 + } + } + }, + items: { + '[,,3]': '[,\n ,\n 3\n];', + '[1, 2, 3]': '[1,\n 2,\n 3\n];', + '[1, 2, 3, 4]': '[1,\n 2,\n 3,\n 4\n];', + '[1, 2, "three-is-a-longer-string-in-this-test"]': '[1,\n 2,\n \'three-is-a-longer-string-in-this-test\'\n];', + 'foo = ["long-text-that-only-fits-in-singl-row"]': 'foo = [\n \'long-text-that-only-fits-in-singl-row\'\n];', + 'foo = ["very-long-text-that-will-never-fit-according-to-the-configured-max-width"]': 'foo = [\n \'very-long-text-that-will-never-fit-according-to-the-configured-max-width\'\n];' + } +}, { + options: { + format: { + arrays: { + multilineArrayStartsInline: false, + maxElementsPerLine: 1, + maxLineWidth: 40 + } + } +}, +items: { + '[,,3]': '[\n ,\n ,\n 3\n];', + '[1, 2, 3]': '[\n 1,\n 2,\n 3\n];', + '[1, 2, 3, 4]': '[\n 1,\n 2,\n 3,\n 4\n];', + '[1, 2, "three-is-a-longer-string-in-this-test"]': '[\n 1,\n 2,\n \'three-is-a-longer-string-in-this-test\'\n];', + 'foo = ["long-text-that-only-fits-in-singl-row"]': 'foo = [\n \'long-text-that-only-fits-in-singl-row\'\n];', + 'foo = ["very-long-text-that-will-never-fit-according-to-the-configured-max-width"]': 'foo = [\n \'very-long-text-that-will-never-fit-according-to-the-configured-max-width\'\n];' +} +}, { + options: { + format: { + arrays: { + multilineArrayStartsInline: false, + maxElementsPerLine: 3, + maxLineWidth: 40 + } + } +}, +items: { + '[,,3]': '[, , 3];', + '[1, 2, 3]': '[1, 2, 3];', + '[1, 2, 3, 4]': '[\n 1, 2, 3,\n 4\n];', + '[1, 2, "three-is-a-longer-string-in-this-test"]': '[\n 1, 2,\n \'three-is-a-longer-string-in-this-test\'\n];', + 'foo = ["long-text-that-only-fits-in-singl-row"]': 'foo = [\n \'long-text-that-only-fits-in-singl-row\'\n];', + 'foo = ["very-long-text-that-will-never-fit-according-to-the-configured-max-width"]': 'foo = [\n \'very-long-text-that-will-never-fit-according-to-the-configured-max-width\'\n];' +} +}, { + options: { + format: { + arrays: { + multilineArrayStartsInline: true, + maxElementsPerLine: 3, + maxLineWidth: 40 + } + } +}, +items: { + '[,,3]': '[, , 3];', + '[1, 2, 3]': '[1, 2, 3];', + '[1, 2, 3, 4]': '[1, 2, 3,\n 4\n];', + '[1, 2, "three-is-a-longer-string-in-this-test"]': '[1, 2,\n \'three-is-a-longer-string-in-this-test\'\n];', + 'foo = ["long-text-that-only-fits-in-singl-row"]': 'foo = [\n \'long-text-that-only-fits-in-singl-row\'\n];', + 'foo = ["very-long-text-that-will-never-fit-according-to-the-configured-max-width"]': 'foo = [\n \'very-long-text-that-will-never-fit-according-to-the-configured-max-width\'\n];' +} }]; function adjustRegexLiteral(key, value) {