You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2019/12/18 17:57:05 UTC
[couchdb-escodegen] 01/02: adding support for 'extras' (leading and
trailing whitespace, single-line comments,
multiline comments) to be tracked on (and thus outputted from) all AST-Node
types (identifiers, expressions, statements, etc
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to reference refs/pull/133/head
in repository https://gitbox.apache.org/repos/asf/couchdb-escodegen.git
commit 037de229942ae16d185587bf551c0e911c7686eb
Author: Kyle Simpson <ge...@gmail.com>
AuthorDate: Sun Sep 22 14:23:45 2013 -0500
adding support for 'extras' (leading and trailing whitespace, single-line comments, multiline comments) to be tracked on (and thus outputted from) all AST-Node types (identifiers, expressions, statements, etc
---
escodegen.js | 95 +++++++++++++++
test/ast.js | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 479 insertions(+)
diff --git a/escodegen.js b/escodegen.js
index 6f32f66..c9c814b 100644
--- a/escodegen.js
+++ b/escodegen.js
@@ -81,6 +81,7 @@
DoWhileStatement: 'DoWhileStatement',
DebuggerStatement: 'DebuggerStatement',
EmptyStatement: 'EmptyStatement',
+ EmptyExpression: 'EmptyExpression',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
@@ -304,6 +305,10 @@
return ch === '\r' || ch === '\n';
}
+ function startsWithLineTerminator(str) {
+ return isLineTerminator(str.charAt(0));
+ }
+
function updateDeeply(target, override) {
var key, val;
@@ -769,6 +774,78 @@
return result;
}
+ function addExtrasToNode(node, result) {
+
+ function addExtras(extras, result) {
+ var i, len, extra;
+
+ for (i = 0, len = extras.length; i < len; i += 1) {
+ // was previous extra a line-comment?
+ if (previousLineComment) {
+ // need to insert a new-line to delimit previous line-comment?
+ if (!startsWithLineTerminator(extras[i].value)) {
+ result.push('\n');
+ }
+ }
+
+ extra = extras[i];
+
+ if (extra.type === 'Whitespace') {
+ result.push(extra.value);
+ previousLineComment = false;
+ }
+ else if (extra.type === 'LineComment') {
+ result.push((extra.marker || '//') + extra.value);
+ previousLineComment = true;
+ }
+ else if (extra.type === 'MultilineComment') {
+ result.push('/*' + extra.value + '*/');
+ previousLineComment = false;
+ }
+ }
+
+ return result;
+ }
+
+ var save, previousLineComment = false;
+
+ if (node && node.extras) {
+ if (node.extras.leading && node.extras.leading.length > 0) {
+ save = result;
+ result = [];
+
+ result = addExtras(node.extras.leading, result);
+
+ // was last extra a line-comment?
+ if (previousLineComment) {
+ // need to insert a new-line to delimit previous line-comment?
+ if (!startsWithLineTerminator(toSourceNode(save).toString() || '')) {
+ result.push('\n');
+ previousLineComment = false;
+ }
+ }
+
+ result.push(save);
+ }
+
+ if (node.extras.trailing && node.extras.trailing.length > 0) {
+ // if result is not yet an array, make it one so we can add to it
+ if (!Array.isArray(result)) {
+ result = [result];
+ }
+ result = addExtras(node.extras.trailing, result);
+
+ // was last extra a line-comment?
+ if (previousLineComment) {
+ // insert a new-line to delimit previous line-comment
+ result.push('\n');
+ }
+ }
+ }
+
+ return result;
+ }
+
function parenthesize(text, current, should) {
if (current < should) {
return ['(', text, ')'];
@@ -890,6 +967,15 @@
}
switch (type) {
+
+ case Syntax.EmptyExpression:
+ // 'EmptyExpression' is just a placeholder node for where only
+ // extras are present.
+ // Example: comment or whitespace extras in an otherwise empty
+ // arguments list of a call expression
+ result = [];
+ break;
+
case Syntax.SequenceExpression:
result = [];
allowIn |= (Precedence.Sequence < precedence);
@@ -1488,6 +1574,10 @@
throw new Error('Unknown expression type: ' + expr.type);
}
+ if (expr.extras) {
+ result = addExtrasToNode(expr, result);
+ }
+
return toSourceNode(result, expr);
}
@@ -1957,6 +2047,10 @@
result = toSourceNode(result).replaceRight(/\s+$/, '');
}
+ if (stmt.extras) {
+ result = addExtrasToNode(stmt, result);
+ }
+
return toSourceNode(result, stmt);
}
@@ -2052,6 +2146,7 @@
case Syntax.BinaryExpression:
case Syntax.CallExpression:
case Syntax.ConditionalExpression:
+ case Syntax.EmptyExpression:
case Syntax.FunctionExpression:
case Syntax.Identifier:
case Syntax.Literal:
diff --git a/test/ast.js b/test/ast.js
index 8fc648a..997fceb 100644
--- a/test/ast.js
+++ b/test/ast.js
@@ -148,6 +148,390 @@ data = {
}],
expected: '/(?:)/i;'
}
+ ],
+ 'AST-Node "extras"': [
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'Identifier',
+ name: 'foo'
+ },
+ }],
+ extras: {
+ leading: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ },
+ expected: '\tfoo;'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'Identifier',
+ name: 'foo'
+ },
+ }],
+ extras: {
+ trailing: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ },
+ expected: 'foo;\t'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'Identifier',
+ name: 'foo'
+ },
+ extras: {
+ leading: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ trailing: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ },
+ }],
+ expected: '\tfoo;\t'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'Identifier',
+ name: 'foo',
+ extras: {
+ leading: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ trailing: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ },
+ },
+ }],
+ expected: '\tfoo\t;'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: 'foo'
+ },
+ arguments: [
+ {
+ type: 'EmptyExpression',
+ value: '',
+ extras: {
+ leading: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ trailing: [
+ {
+ type: 'Whitespace',
+ value: '\t'
+ }
+ ],
+ },
+ }
+ ],
+ },
+ }],
+ expected: 'foo(\t\t);'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: 'foo',
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '2'
+ },
+ ],
+ }
+ },
+ arguments: [
+ {
+ type: 'EmptyExpression',
+ value: '',
+ extras: {
+ leading: [
+ {
+ type: 'MultilineComment',
+ value: '3'
+ },
+ ],
+ },
+ }
+ ],
+ extras: {
+ leading: [
+ {
+ type: 'MultilineComment',
+ value: '1'
+ },
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '4'
+ },
+ ],
+ }
+ },
+ }],
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '5'
+ },
+ ],
+ },
+ expected: '/*1*/foo/*2*/(/*3*/)/*4*/;/*5*/'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: 'foo',
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '2'
+ },
+ ],
+ }
+ },
+ arguments: [
+ {
+ type: 'EmptyExpression',
+ value: '',
+ extras: {
+ leading: [
+ {
+ type: 'LineComment',
+ value: '3'
+ }
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '4'
+ },
+ ],
+ },
+ }
+ ],
+ extras: {
+ leading: [
+ {
+ type: 'MultilineComment',
+ value: '1'
+ },
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '5'
+ },
+ ]
+ }
+ },
+ }],
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '6'
+ },
+ ],
+ },
+ expected: '/*1*/foo/*2*/(//3\n/*4*/)/*5*/;/*6*/'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: 'foo',
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '2'
+ },
+ ],
+ }
+ },
+ arguments: [
+ {
+ type: 'Literal',
+ value: 4,
+ raw: '4',
+ extras: {
+ leading: [
+ {
+ type: 'LineComment',
+ value: '3'
+ }
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '5'
+ },
+ ],
+ },
+ }
+ ],
+ extras: {
+ leading: [
+ {
+ type: 'MultilineComment',
+ value: '1'
+ },
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '6'
+ },
+ ]
+ }
+ },
+ }],
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '7'
+ },
+ ],
+ },
+ expected: '/*1*/foo/*2*/(//3\n4/*5*/)/*6*/;/*7*/'
+ },
+ {
+ type: 'Program',
+ body: [{
+ type: 'ExpressionStatement',
+ expression: {
+ type: 'CallExpression',
+ callee: {
+ type: 'Identifier',
+ name: 'foo',
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '2'
+ },
+ ],
+ }
+ },
+ arguments: [
+ {
+ type: 'Literal',
+ value: 4,
+ raw: '4',
+ extras: {
+ leading: [
+ {
+ type: 'LineComment',
+ value: '3'
+ }
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '5'
+ },
+ // NOTE: testing custom line-comment markers,
+ // in support of HTML-style line-comment markers
+ // Ref: http://javascript.spec.whatwg.org/#comment-syntax
+ {
+ type: 'LineComment',
+ value: '6',
+ marker: '<!--'
+ }
+ ],
+ },
+ }
+ ],
+ extras: {
+ leading: [
+ {
+ type: 'MultilineComment',
+ value: '1'
+ },
+ ],
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '7'
+ },
+ ]
+ }
+ },
+ }],
+ extras: {
+ trailing: [
+ {
+ type: 'MultilineComment',
+ value: '8'
+ },
+ ],
+ },
+ expected: '/*1*/foo/*2*/(//3\n4/*5*/<!--6\n)/*7*/;/*8*/'
+ },
]
};