summaryrefslogtreecommitdiffstats
path: root/third_party/python/esprima/esprima/comment_handler.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/python/esprima/esprima/comment_handler.py')
-rw-r--r--third_party/python/esprima/esprima/comment_handler.py176
1 files changed, 176 insertions, 0 deletions
diff --git a/third_party/python/esprima/esprima/comment_handler.py b/third_party/python/esprima/esprima/comment_handler.py
new file mode 100644
index 0000000000..09a37a5fd2
--- /dev/null
+++ b/third_party/python/esprima/esprima/comment_handler.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+# Copyright JS Foundation and other contributors, https://js.foundation/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, self.list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, self.list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# self.SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES
+# LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# self.SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from __future__ import absolute_import, unicode_literals
+
+from .objects import Object
+from .nodes import Node
+from .syntax import Syntax
+
+
+class Comment(Node):
+ def __init__(self, type, value, range=None, loc=None):
+ self.type = type
+ self.value = value
+ self.range = range
+ self.loc = loc
+
+
+class Entry(Object):
+ def __init__(self, comment, start):
+ self.comment = comment
+ self.start = start
+
+
+class NodeInfo(Object):
+ def __init__(self, node, start):
+ self.node = node
+ self.start = start
+
+
+class CommentHandler(object):
+ def __init__(self):
+ self.attach = False
+ self.comments = []
+ self.stack = []
+ self.leading = []
+ self.trailing = []
+
+ def insertInnerComments(self, node, metadata):
+ # innnerComments for properties empty block
+ # `function a(:/** comments **\/}`
+ if node.type is Syntax.BlockStatement and not node.body:
+ innerComments = []
+ for i, entry in enumerate(self.leading):
+ if metadata.end.offset >= entry.start:
+ innerComments.append(entry.comment)
+ self.leading[i] = None
+ self.trailing[i] = None
+ if innerComments:
+ node.innerComments = innerComments
+ self.leading = [v for v in self.leading if v is not None]
+ self.trailing = [v for v in self.trailing if v is not None]
+
+ def findTrailingComments(self, metadata):
+ trailingComments = []
+
+ if self.trailing:
+ for i, entry in enumerate(self.trailing):
+ if entry.start >= metadata.end.offset:
+ trailingComments.append(entry.comment)
+ if trailingComments:
+ self.trailing = []
+ return trailingComments
+
+ last = self.stack and self.stack[-1]
+ if last and last.node.trailingComments:
+ firstComment = last.node.trailingComments[0]
+ if firstComment and firstComment.range[0] >= metadata.end.offset:
+ trailingComments = last.node.trailingComments
+ del last.node.trailingComments
+ return trailingComments
+
+ def findLeadingComments(self, metadata):
+ leadingComments = []
+
+ target = None
+ while self.stack:
+ entry = self.stack and self.stack[-1]
+ if entry and entry.start >= metadata.start.offset:
+ target = entry.node
+ self.stack.pop()
+ else:
+ break
+
+ if target:
+ if target.leadingComments:
+ for i, comment in enumerate(target.leadingComments):
+ if comment.range[1] <= metadata.start.offset:
+ leadingComments.append(comment)
+ target.leadingComments[i] = None
+ if leadingComments:
+ target.leadingComments = [v for v in target.leadingComments if v is not None]
+ if not target.leadingComments:
+ del target.leadingComments
+ return leadingComments
+
+ for i, entry in enumerate(self.leading):
+ if entry.start <= metadata.start.offset:
+ leadingComments.append(entry.comment)
+ self.leading[i] = None
+ if leadingComments:
+ self.leading = [v for v in self.leading if v is not None]
+
+ return leadingComments
+
+ def visitNode(self, node, metadata):
+ if node.type is Syntax.Program and node.body:
+ return
+
+ self.insertInnerComments(node, metadata)
+ trailingComments = self.findTrailingComments(metadata)
+ leadingComments = self.findLeadingComments(metadata)
+ if leadingComments:
+ node.leadingComments = leadingComments
+ if trailingComments:
+ node.trailingComments = trailingComments
+
+ self.stack.append(NodeInfo(
+ node=node,
+ start=metadata.start.offset
+ ))
+
+ def visitComment(self, node, metadata):
+ type = 'Line' if node.type[0] == 'L' else 'Block'
+ comment = Comment(
+ type=type,
+ value=node.value
+ )
+ if node.range:
+ comment.range = node.range
+ if node.loc:
+ comment.loc = node.loc
+ self.comments.append(comment)
+
+ if self.attach:
+ entry = Entry(
+ comment=Comment(
+ type=type,
+ value=node.value,
+ range=[metadata.start.offset, metadata.end.offset]
+ ),
+ start=metadata.start.offset
+ )
+ if node.loc:
+ entry.comment.loc = node.loc
+ node.type = type
+ self.leading.append(entry)
+ self.trailing.append(entry)
+
+ def visit(self, node, metadata):
+ if node.type == 'LineComment':
+ self.visitComment(node, metadata)
+ elif node.type == 'BlockComment':
+ self.visitComment(node, metadata)
+ elif self.attach:
+ self.visitNode(node, metadata)