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)
Exemplo n.º 3
0
    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")