Skip to content

Commit 9d6530a

Browse files
committed
Merge pull request estools#208 from kevinb7/preserveBlankLines
Preserve blank lines
2 parents 824f571 + 2cf9e64 commit 9d6530a

19 files changed

Lines changed: 3330 additions & 43 deletions

escodegen-old.js

Lines changed: 2877 additions & 0 deletions
Large diffs are not rendered by default.

escodegen.js

Lines changed: 213 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
extra,
6060
parse,
6161
sourceMap,
62+
sourceCode,
63+
preserveBlankLines,
6264
FORMAT_MINIFY,
6365
FORMAT_DEFAULTS;
6466

@@ -185,7 +187,8 @@
185187
compact: false,
186188
parentheses: true,
187189
semicolons: true,
188-
safeConcatenation: false
190+
safeConcatenation: false,
191+
preserveBlankLines: false
189192
},
190193
moz: {
191194
comprehensionExpressionStartsWithAssignment: false,
@@ -196,7 +199,8 @@
196199
sourceMapWithCode: false,
197200
directive: false,
198201
raw: true,
199-
verbatim: null
202+
verbatim: null,
203+
sourceCode: null
200204
};
201205
}
202206

@@ -645,7 +649,11 @@
645649
return '//' + comment.value;
646650
} else {
647651
// Always use LineTerminator
648-
return '//' + comment.value + '\n';
652+
var result = '//' + comment.value;
653+
if (!preserveBlankLines) {
654+
result += '\n';
655+
}
656+
return result;
649657
}
650658
}
651659
if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
@@ -655,63 +663,132 @@
655663
}
656664

657665
function addComments(stmt, result) {
658-
var i, len, comment, save, tailingToStatement, specialBase, fragment;
666+
var i, len, comment, save, tailingToStatement, specialBase, fragment,
667+
extRange, range, prevRange, prefix, infix, suffix, count;
659668

660669
if (stmt.leadingComments && stmt.leadingComments.length > 0) {
661670
save = result;
662671

663-
comment = stmt.leadingComments[0];
664-
result = [];
665-
if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
666-
result.push('\n');
667-
}
668-
result.push(generateComment(comment));
669-
if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
670-
result.push('\n');
671-
}
672+
if (preserveBlankLines) {
673+
comment = stmt.leadingComments[0];
674+
result = [];
675+
676+
extRange = comment.extendedRange;
677+
range = comment.range;
678+
679+
prefix = sourceCode.substring(extRange[0], range[0]);
680+
count = (prefix.match(/\n/g) || []).length;
681+
if (count > 0) {
682+
result.push(stringRepeat('\n', count));
683+
result.push(addIndent(generateComment(comment)));
684+
} else {
685+
result.push(prefix);
686+
result.push(generateComment(comment));
687+
}
688+
689+
prevRange = range;
690+
691+
for (i = 1, len = stmt.leadingComments.length; i < len; i++) {
692+
comment = stmt.leadingComments[i];
693+
range = comment.range;
694+
695+
infix = sourceCode.substring(prevRange[1], range[0]);
696+
count = (infix.match(/\n/g) || []).length;
697+
result.push(stringRepeat('\n', count));
698+
result.push(addIndent(generateComment(comment)));
699+
700+
prevRange = range;
701+
}
702+
703+
suffix = sourceCode.substring(range[1], extRange[1]);
704+
count = (suffix.match(/\n/g) || []).length;
705+
result.push(stringRepeat('\n', count));
706+
} else {
707+
comment = stmt.leadingComments[0];
708+
result = [];
709+
if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
710+
result.push('\n');
711+
}
712+
result.push(generateComment(comment));
713+
if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
714+
result.push('\n');
715+
}
672716

673-
for (i = 1, len = stmt.leadingComments.length; i < len; ++i) {
674-
comment = stmt.leadingComments[i];
675-
fragment = [generateComment(comment)];
676-
if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
677-
fragment.push('\n');
717+
for (i = 1, len = stmt.leadingComments.length; i < len; ++i) {
718+
comment = stmt.leadingComments[i];
719+
fragment = [generateComment(comment)];
720+
if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
721+
fragment.push('\n');
722+
}
723+
result.push(addIndent(fragment));
678724
}
679-
result.push(addIndent(fragment));
680725
}
681726

682727
result.push(addIndent(save));
683728
}
684729

685730
if (stmt.trailingComments) {
686-
tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
687-
specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString()));
688-
for (i = 0, len = stmt.trailingComments.length; i < len; ++i) {
689-
comment = stmt.trailingComments[i];
690-
if (tailingToStatement) {
691-
// We assume target like following script
692-
//
693-
// var t = 20; /**
694-
// * This is comment of t
695-
// */
696-
if (i === 0) {
697-
// first case
698-
result = [result, indent];
699-
} else {
700-
result = [result, specialBase];
701-
}
702-
result.push(generateComment(comment, specialBase));
731+
732+
if (preserveBlankLines) {
733+
comment = stmt.trailingComments[0];
734+
extRange = comment.extendedRange;
735+
range = comment.range;
736+
737+
prefix = sourceCode.substring(extRange[0], range[0]);
738+
count = (prefix.match(/\n/g) || []).length;
739+
740+
if (count > 0) {
741+
result.push(stringRepeat('\n', count));
742+
result.push(addIndent(generateComment(comment)));
703743
} else {
704-
result = [result, addIndent(generateComment(comment))];
744+
result.push(prefix);
745+
result.push(generateComment(comment));
705746
}
706-
if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
707-
result = [result, '\n'];
747+
} else {
748+
tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
749+
specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([base, result, indent]).toString()));
750+
for (i = 0, len = stmt.trailingComments.length; i < len; ++i) {
751+
comment = stmt.trailingComments[i];
752+
if (tailingToStatement) {
753+
// We assume target like following script
754+
//
755+
// var t = 20; /**
756+
// * This is comment of t
757+
// */
758+
if (i === 0) {
759+
// first case
760+
result = [result, indent];
761+
} else {
762+
result = [result, specialBase];
763+
}
764+
result.push(generateComment(comment, specialBase));
765+
} else {
766+
result = [result, addIndent(generateComment(comment))];
767+
}
768+
if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
769+
result = [result, '\n'];
770+
}
708771
}
709772
}
710773
}
711774

712775
return result;
713776
}
714777

778+
function generateBlankLines(start, end, result) {
779+
var j, newlineCount = 0;
780+
781+
for (j = start; j < end; j++) {
782+
if (sourceCode[j] === '\n') {
783+
newlineCount++;
784+
}
785+
}
786+
787+
for (j = 1; j < newlineCount; j++) {
788+
result.push(newline);
789+
}
790+
}
791+
715792
function parenthesize(text, current, should) {
716793
if (current < should) {
717794
return ['(', text, ')'];
@@ -924,22 +1001,81 @@
9241001
CodeGenerator.Statement = {
9251002

9261003
BlockStatement: function (stmt, flags) {
927-
var result = ['{', newline], that = this;
1004+
var range, content, result = ['{', newline], that = this;
9281005

9291006
withIndent(function () {
1007+
// handle functions without any code
1008+
if (stmt.body.length === 0 && preserveBlankLines) {
1009+
range = stmt.range;
1010+
if (range[1] - range[0] > 2) {
1011+
content = sourceCode.substring(range[0] + 1, range[1] - 1);
1012+
if (content[0] === '\n') {
1013+
result = ['{'];
1014+
}
1015+
result.push(content);
1016+
}
1017+
}
1018+
9301019
var i, iz, fragment, bodyFlags;
9311020
bodyFlags = S_TFFF;
9321021
if (flags & F_FUNC_BODY) {
9331022
bodyFlags |= F_DIRECTIVE_CTX;
9341023
}
1024+
9351025
for (i = 0, iz = stmt.body.length; i < iz; ++i) {
1026+
if (preserveBlankLines) {
1027+
// handle spaces before the first line
1028+
if (i === 0) {
1029+
if (stmt.body[0].leadingComments) {
1030+
range = stmt.body[0].leadingComments[0].extendedRange;
1031+
content = sourceCode.substring(range[0], range[1]);
1032+
if (content[0] === '\n') {
1033+
result = ['{'];
1034+
}
1035+
}
1036+
if (!stmt.body[0].leadingComments) {
1037+
generateBlankLines(stmt.range[0], stmt.body[0].range[0], result);
1038+
}
1039+
}
1040+
1041+
// handle spaces between lines
1042+
if (i > 0) {
1043+
if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {
1044+
generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);
1045+
}
1046+
}
1047+
}
1048+
9361049
if (i === iz - 1) {
9371050
bodyFlags |= F_SEMICOLON_OPT;
9381051
}
939-
fragment = addIndent(that.generateStatement(stmt.body[i], bodyFlags));
1052+
1053+
if (stmt.body[i].leadingComments && preserveBlankLines) {
1054+
fragment = that.generateStatement(stmt.body[i], bodyFlags);
1055+
} else {
1056+
fragment = addIndent(that.generateStatement(stmt.body[i], bodyFlags));
1057+
}
1058+
9401059
result.push(fragment);
9411060
if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
942-
result.push(newline);
1061+
if (preserveBlankLines && i < iz - 1) {
1062+
// don't add a new line if there are leading coments
1063+
// in the next statement
1064+
if (!stmt.body[i + 1].leadingComments) {
1065+
result.push(newline);
1066+
}
1067+
} else {
1068+
result.push(newline);
1069+
}
1070+
}
1071+
1072+
if (preserveBlankLines) {
1073+
// handle spaces after the last line
1074+
if (i === iz - 1) {
1075+
if (!stmt.body[i].trailingComments) {
1076+
generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);
1077+
}
1078+
}
9431079
}
9441080
}
9451081
});
@@ -1474,10 +1610,42 @@
14741610
if (!safeConcatenation && i === iz - 1) {
14751611
bodyFlags |= F_SEMICOLON_OPT;
14761612
}
1613+
1614+
if (preserveBlankLines) {
1615+
// handle spaces before the first line
1616+
if (i === 0) {
1617+
if (!stmt.body[0].leadingComments) {
1618+
generateBlankLines(stmt.range[0], stmt.body[i].range[0], result);
1619+
}
1620+
}
1621+
1622+
// handle spaces between lines
1623+
if (i > 0) {
1624+
if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {
1625+
generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);
1626+
}
1627+
}
1628+
}
1629+
14771630
fragment = addIndent(this.generateStatement(stmt.body[i], bodyFlags));
14781631
result.push(fragment);
14791632
if (i + 1 < iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
1480-
result.push(newline);
1633+
if (preserveBlankLines) {
1634+
if (!stmt.body[i + 1].leadingComments) {
1635+
result.push(newline);
1636+
}
1637+
} else {
1638+
result.push(newline);
1639+
}
1640+
}
1641+
1642+
if (preserveBlankLines) {
1643+
// handle spaces after the last line
1644+
if (i === iz - 1) {
1645+
if (!stmt.body[i].trailingComments) {
1646+
generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);
1647+
}
1648+
}
14811649
}
14821650
}
14831651
return result;
@@ -2257,6 +2425,8 @@
22572425
directive = options.directive;
22582426
parse = json ? null : options.parse;
22592427
sourceMap = options.sourceMap;
2428+
sourceCode = options.sourceCode;
2429+
preserveBlankLines = options.format.preserveBlankLines && sourceCode !== null;
22602430
extra = options;
22612431

22622432
if (sourceMap) {

0 commit comments

Comments
 (0)