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*/'
+        },
     ]
 };