def findAssociatedComment(node): # traverse <node> tree left-most, looking for comments from ecmascript.frontend import treeutil # ugly here, but due to import cycle ## # For every <start_node> find the enclosing statement node, and from that # the node of the first token (as this will carry a pot. comment) def statement_head_from(start_node): # 1. find enclosing "local root" node # (e.g. the enclosing statement or file node) tnode = start_node stmt_node = None while True: # this will always terminate, as every JS node is a child of a statement if tnode.isStatement(): stmt_node = tnode break elif tnode.type == 'file': # TODO: (bug#6765) why does/n't it crash without this?! # are file-level comments being picked up correctly?! stmt_node = tnode break elif tnode.parent: tnode = tnode.parent else: break # 2. determine left-most token #if stmt_node.isPrefixOp(): # head_token_node = stmt_node #else: # head_token_node = treeutil.findLeftmostChild(stmt_node) head_token_node = stmt_node.toListG().next() return head_token_node # -------------------------------------------------------------------------- res = None if node.comments: res = node else: # above current expression left_most = treeutil.findLeftmostChild( node) # this might return <node> itself if left_most.comments: res = left_most else: # above key : value in maps next_root = treeutil.findAncestor(node, ["keyvalue"], radius=5) if next_root: if next_root.comments: res = next_root else: # above current statement stmt_head = statement_head_from(node) if stmt_head and stmt_head.comments: res = stmt_head return res
def findAssociatedComment(node): # traverse <node> tree left-most, looking for comments from ecmascript.frontend import treeutil # ugly here, but due to import cycle ## # For every <start_node> find the enclosing statement node, and from that # the node of the first token (as this will carry a pot. comment) def statement_head_from(start_node): # 1. find enclosing "local root" node # (e.g. the enclosing statement or file node) tnode = start_node stmt_node = None while True: # this will always terminate, as every JS node is a child of a statement if tnode.isStatement(): stmt_node = tnode break elif tnode.type == 'file': # TODO: (bug#6765) why does/n't it crash without this?! # are file-level comments being picked up correctly?! stmt_node = tnode break elif tnode.parent: tnode = tnode.parent else: break # 2. determine left-most token #if stmt_node.isPrefixOp(): # head_token_node = stmt_node #else: # head_token_node = treeutil.findLeftmostChild(stmt_node) head_token_node = stmt_node.toListG().next() return head_token_node # -------------------------------------------------------------------------- res = None if node.comments: res = node else: # above current expression left_most = treeutil.findLeftmostChild(node) # this might return <node> itself if left_most.comments: res = left_most else: # above key : value in maps next_root = treeutil.findAncestor(node, ["keyvalue"], radius=5) if next_root: if next_root.comments: res = next_root else: # above current statement stmt_head = statement_head_from(node) if stmt_head and stmt_head.comments: res = stmt_head return res
def findAssociatedComment(node): # traverse <node> tree left-most, looking for comments from ecmascript.frontend import treeutil # ugly here, but due to import cycle if node.comments: return node else: if node.children: left_most = treeutil.findLeftmostChild(node) return findAssociatedComment(left_most) return None
def checkNodeContext(node): context = 'interesting' # every context is interesting, maybe we get more specific or reset to '' # don't treat label references if node.parent.type in ("break", "continue"): return '' # as _isInterestingReference is run on *any* var node while # traversing the tree intermediate occurrences var nodes like # in 'a.b().c[d].e' are run through it as well; but it is enough to treat # the longest left-most expression, so we restrict ourself to the "head" var # expression like 'a.b' here, and skip other occurrences (like 'c', 'd' # and 'e' in the example) #myFirst = node.getFirstChild(mandatory=False, ignoreComments=True) #if not treeutil.checkFirstChainChild(myFirst): # see if myFirst is the first identifier in a chain # context = '' leftmostChild = treeutil.findLeftmostChild(node) # works for leafs too # get the top-most dotaccessor of this identifier/constant if leftmostChild.hasParentContext("dotaccessor/*"): # operand of a dotaccessor localTop = leftmostChild.parent.parent.getHighestPureDotParent() else: localTop = leftmostChild # testing for the 'a.b' in 'a.b().c[d].e'; bare 'a' in 'a' is also caught if localTop != node: context = '' # '/^\s*$/.test(value)' or '[].push' or '{}.toString' elif leftmostChild.type in ("constant", "array", "map"): context = '' ## testing for the 'a' in 'a.b().c[d].e' #elif not treeutil.checkFirstChainChild(treeutil.findLeftmostChild(localTop)): # context = '' # check name in 'new ...' position elif ((node.hasParentContext("operation/first") and node.parent.parent.get("operator",0) == "new") or (node.hasParentContext("operation/first/call/operand") and node.parent.parent.parent.parent.get("operator",0) == "new") # WISH: hasParentContext("operation[@operator='new']/...") ): context = 'new' # check name in call position elif (node.hasParentContext("call/operand")): context = 'call' # check name in "'extend' : ..." position elif (node.hasParentContext("keyvalue/*") and node.parent.parent.get('key') in ['extend']): #, 'include']): #print "-- found context: %s" % node.parent.parent.get('key') context = 'extend' return context
def checkNodeContext(node): ## # Getting the longest left-most dotaccessor in the expression <node> # is in, e.g. the 'a.b' in 'a.b().c.d[0].e'. # # The idea is to only treat 'a.b' as interesting, and ignore all # other vars in such an expression. So the check is to see whether # <node> represents 'a.b'. # # To get this we # (a) use the leftmostChild of <node> ("downwards") # (If <node> represents 'a.b', this should be 'a', but would # be 'c' if in 'c.d'). The leftmostChild is also used # elsewhere, so it is passed in as a param. # (b) from that search upwards the tree to get the highest enclosing # dotaccessor node. # If this is identical to <node>, <node> is interesting. # def is_leftmost_and_highest_pure_dotaccessor(node, leftmost_child): res = False # as _isInterestingReference is run on *any* var node while # traversing the tree intermediate occurrences var nodes like # in 'a.b().c[d].e' are run through it as well; but it is enough to treat # the longest left-most expression, so we restrict ourself to the "head" var # expression like 'a.b' here, and skip other occurrences (like 'c', 'd' # and 'e' in the example) #myFirst = node.getFirstChild(mandatory=False, ignoreComments=True) #if not treeutil.checkFirstChainChild(myFirst): # see if myFirst is the first identifier in a chain # context = '' # get the top-most dotaccessor of this identifier/constant(?) ##localTop = treeutil.findVarRoot(leftmostChild) # testing for the 'a.b' in 'a.b().c[d].e'; bare 'a' in 'a' is also caught ##if localTop != node: ## context = '' # ---------------------------------------------------- # assumption: not is_right_dot_operand(node), so # we're on the 'left' axis of the (left-leaning) expression var_root = treeutil.findVarRoot(leftmost_child) # get the highest pur dotaccessor above it res = var_root == node return res def is_right_dot_operand(node): return node.parent.type == "dotaccessor" and node.parent.getChild(1) == node # ------------------------------------------------------------------ context = 'interesting' # every context is interesting, maybe we get more specific or reset to '' # don't treat label references if node.parent.type in ("break", "continue"): context = '' # skip right dot operands (the 'b' in 'a.b') elif is_right_dot_operand(node): context = '' else: leftmost_child = treeutil.findLeftmostChild(node) # get left-most child # skip inner parts of a complex dotaccessor chain ('.c' in 'a.b().c.d[3].f') if not is_leftmost_and_highest_pure_dotaccessor(node, leftmost_child): context = '' # '/^\s*$/.test(value)' or '[].push' or '{}.toString' elif leftmost_child.type in ("constant", "array", "map"): context = '' # check name in 'new ...' position elif treeutil.isNEWoperand(node): context = 'new' # check name in call position elif (node.hasParentContext("call/operand")): context = 'call' # check name in "'extend' : ..." position elif (node.hasParentContext("keyvalue/*") and node.parent.parent.get('key') in ['extend']): #, 'include']): #print "-- found context: %s" % node.parent.parent.get('key') context = 'extend' return context
def checkNodeContext(node): ## # Getting the longest left-most dotaccessor in the expression <node> # is in, e.g. the 'a.b' in 'a.b().c.d[0].e'. # # The idea is to only treat 'a.b' as interesting, and ignore all # other vars in such an expression. So the check is to see whether # <node> represents 'a.b'. # # To get this we # (a) use the leftmostChild of <node> ("downwards") # (If <node> represents 'a.b', this should be 'a', but would # be 'c' if in 'c.d'). The leftmostChild is also used # elsewhere, so it is passed in as a param. # (b) from that search upwards the tree to get the highest enclosing # dotaccessor node. # If this is identical to <node>, <node> is interesting. # def is_leftmost_and_highest_pure_dotaccessor(node, leftmost_child): res = False # as _isInterestingReference is run on *any* var node while # traversing the tree intermediate occurrences var nodes like # in 'a.b().c[d].e' are run through it as well; but it is enough to treat # the longest left-most expression, so we restrict ourself to the "head" var # expression like 'a.b' here, and skip other occurrences (like 'c', 'd' # and 'e' in the example) #myFirst = node.getFirstChild(mandatory=False, ignoreComments=True) #if not treeutil.checkFirstChainChild(myFirst): # see if myFirst is the first identifier in a chain # context = '' # get the top-most dotaccessor of this identifier/constant(?) ##localTop = treeutil.findVarRoot(leftmostChild) # testing for the 'a.b' in 'a.b().c[d].e'; bare 'a' in 'a' is also caught ##if localTop != node: ## context = '' # ---------------------------------------------------- # assumption: not is_right_dot_operand(node), so # we're on the 'left' axis of the (left-leaning) expression var_root = treeutil.findVarRoot( leftmost_child) # get the highest pur dotaccessor above it res = var_root == node return res def is_right_dot_operand(node): return node.parent.type == "dotaccessor" and node.parent.getChild( 1) == node # ------------------------------------------------------------------ context = 'interesting' # every context is interesting, maybe we get more specific or reset to '' # don't treat label references if node.parent.type in ("break", "continue"): context = '' # skip right dot operands (the 'b' in 'a.b') elif is_right_dot_operand(node): context = '' else: leftmost_child = treeutil.findLeftmostChild( node) # get left-most child # skip inner parts of a complex dotaccessor chain ('.c' in 'a.b().c.d[3].f') if not is_leftmost_and_highest_pure_dotaccessor( node, leftmost_child): context = '' # '/^\s*$/.test(value)' or '[].push' or '{}.toString' elif leftmost_child.type in ("constant", "array", "map"): context = '' # check name in 'new ...' position elif treeutil.isNEWoperand(node): context = 'new' # check name in call position elif (node.hasParentContext("call/operand")): context = 'call' # check name in "'extend' : ..." position elif (node.hasParentContext("keyvalue/*") and node.parent.parent.get('key') in ['extend']): #, 'include']): #print "-- found context: %s" % node.parent.parent.get('key') context = 'extend' return context