def compute_next_context(self, prior, match): return js.next_js_ctx(match.group(0), prior)
def compute_next_context(self, prior, match): return js.next_js_ctx(match.group(0), prior)
def test_is_regex_preceder(self): """Test heuristic that is used to update JS_CTX_*""" tests = ( # Statement terminators precede regexps. (context.JS_CTX_REGEX, ";"), # This is not airtight. # ({ valueOf: function () { return 1 } } / 2) # is valid JavaScript but in practice, devs do not do this. # A block followed by a statement starting with a RegExp is # much more common: # while (x) {...} /foo/.test(x) || panic() (context.JS_CTX_REGEX, "}"), # But member, call, grouping, and array expression terminators # precede div ops. (context.JS_CTX_DIV_OP, ")"), (context.JS_CTX_DIV_OP, "]"), # At the start of a primary expression, array, or expression # statement, expect a regexp. (context.JS_CTX_REGEX, "("), (context.JS_CTX_REGEX, "["), (context.JS_CTX_REGEX, "{"), # Assignment operators precede regexps as do all exclusively # prefix and binary operators. (context.JS_CTX_REGEX, "="), (context.JS_CTX_REGEX, "+="), (context.JS_CTX_REGEX, "*="), (context.JS_CTX_REGEX, "*"), (context.JS_CTX_REGEX, "!"), # Whether the + or - is infix or prefix, it cannot precede a # div op. (context.JS_CTX_REGEX, "+"), (context.JS_CTX_REGEX, "-"), # An incr/decr op precedes a div operator. # This is not airtight. In (g = ++/h/i) a regexp follows a # pre-increment operator, but in practice devs do not try to # increment or decrement regular expressions. # (g++/h/i) where ++ is a postfix operator on g is much more # common. (context.JS_CTX_DIV_OP, "--"), (context.JS_CTX_DIV_OP, "++"), (context.JS_CTX_DIV_OP, "x--"), # When we have many dashes or pluses, then they are grouped # left to right. (context.JS_CTX_REGEX, "x---"), # A postfix -- then a -. # return followed by a slash returns the regexp literal or the # slash starts a regexp literal in an expression statement that # is dead code. (context.JS_CTX_REGEX, "return"), (context.JS_CTX_REGEX, "return "), (context.JS_CTX_REGEX, "return\t"), (context.JS_CTX_REGEX, "return\n"), (context.JS_CTX_REGEX, u"return\u2028"), # Identifiers can be divided and cannot validly be preceded by # a regular expressions. Semicolon insertion cannot happen # between an identifier and a regular expression on a new line # because the one token lookahead for semicolon insertion has # to conclude that it could be a div binary op and treat it as # such. (context.JS_CTX_DIV_OP, "x"), (context.JS_CTX_DIV_OP, "x "), (context.JS_CTX_DIV_OP, "x\t"), (context.JS_CTX_DIV_OP, "x\n"), (context.JS_CTX_DIV_OP, u"x\u2028"), (context.JS_CTX_DIV_OP, "preturn"), # Numbers precede div ops. (context.JS_CTX_DIV_OP, "0"), # Dots that are part of a number are div preceders. (context.JS_CTX_DIV_OP, "0."), ) for want_ctx, js_code in tests: for start in (context.JS_CTX_REGEX, context.JS_CTX_DIV_OP, context.JS_CTX_DIV_OP | context.STATE_JS): got = js.next_js_ctx(js_code, start) want = want_ctx | context.state_of(start) self.assertEquals( want, got, "%s: want %s got %s" % ( js_code, debug.context_to_string(want), debug.context_to_string(got))) self.assertEquals( context.STATE_JS | context.JS_CTX_REGEX, js.next_js_ctx(" ", context.STATE_JS | context.JS_CTX_REGEX), "Blank tokens") self.assertEquals( context.STATE_JS | context.JS_CTX_DIV_OP, js.next_js_ctx(" ", context.STATE_JS | context.JS_CTX_DIV_OP), "Blank tokens")