[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 4d8ec67 07/22: Rely on bogus scopes less
From: |
Dmitry Gutov |
Subject: |
[elpa] master 4d8ec67 07/22: Rely on bogus scopes less |
Date: |
Fri, 24 Apr 2015 02:57:10 +0000 |
branch: master
commit 4d8ec67305e63de22312dce8e06bf96d06db863b
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>
Rely on bogus scopes less
---
js2-mode.el | 149 +++++++++++++++++++++++++++++--------------------------
tests/parser.el | 14 +++++
2 files changed, 93 insertions(+), 70 deletions(-)
diff --git a/js2-mode.el b/js2-mode.el
index cb9b454..c7c5f22 100644
--- a/js2-mode.el
+++ b/js2-mode.el
@@ -8551,6 +8551,7 @@ invalid export statements."
"Parse a for, for-in or for each-in statement.
Last matched token must be js2-FOR."
(let ((for-pos (js2-current-token-beg))
+ (tmp-scope (make-js2-scope))
pn is-for-each is-for-in-or-of is-for-of
in-pos each-pos tmp-pos
init ; Node init is also foo in 'foo in object'.
@@ -8568,78 +8569,83 @@ Last matched token must be js2-FOR."
(if (js2-must-match js2-LP "msg.no.paren.for")
(setq lp (- (js2-current-token-beg) for-pos)))
(setq tt (js2-get-token))
- ;; 'for' makes local scope
- (js2-push-scope (make-js2-scope))
+ ;; Capture identifiers inside parens. We can't create the node
+ ;; (and use it as the current scope) until we know its type.
+ (js2-push-scope tmp-scope)
(unwind-protect
- ;; parse init clause
- (let ((js2-in-for-init t)) ; set as dynamic variable
- (cond
- ((= tt js2-SEMI)
- (js2-unget-token)
- (setq init (make-js2-empty-expr-node)))
- ((or (= tt js2-VAR) (= tt js2-LET))
- (setq init (js2-parse-variables tt (js2-current-token-beg))))
- (t
- (js2-unget-token)
- (setq init (js2-parse-expr)))))
- (if (or (js2-match-token js2-IN)
- (and (>= js2-language-version 200)
- (js2-match-contextual-kwd "of")
- (setq is-for-of t)))
- (setq is-for-in-or-of t
- in-pos (- (js2-current-token-beg) for-pos)
- ;; scope of iteration target object is not the scope we've
created above.
- ;; stash current scope temporary.
- cond (let ((js2-current-scope (js2-scope-parent-scope
js2-current-scope)))
- (js2-parse-expr))) ; object over which we're iterating
- ;; else ordinary for loop - parse cond and incr
- (js2-must-match js2-SEMI "msg.no.semi.for")
- (setq cond (if (= (js2-peek-token) js2-SEMI)
- (make-js2-empty-expr-node) ; no loop condition
- (js2-parse-expr)))
- (js2-must-match js2-SEMI "msg.no.semi.for.cond")
- (setq tmp-pos (js2-current-token-end)
- incr (if (= (js2-peek-token) js2-RP)
- (make-js2-empty-expr-node :pos tmp-pos)
- (js2-parse-expr))))
- (if (js2-must-match js2-RP "msg.no.paren.for.ctrl")
- (setq rp (- (js2-current-token-beg) for-pos)))
- (if (not is-for-in-or-of)
- (setq pn (make-js2-for-node :init init
- :condition cond
- :update incr
- :lp lp
- :rp rp))
- ;; cond could be null if 'in obj' got eaten by the init node.
- (if (js2-infix-node-p init)
- ;; it was (foo in bar) instead of (var foo in bar)
- (setq cond (js2-infix-node-right init)
- init (js2-infix-node-left init))
- (if (and (js2-var-decl-node-p init)
- (> (length (js2-var-decl-node-kids init)) 1))
- (js2-report-error "msg.mult.index")))
- (setq pn (make-js2-for-in-node :iterator init
- :object cond
- :in-pos in-pos
- :foreach-p is-for-each
- :each-pos each-pos
- :forof-p is-for-of
- :lp lp
- :rp rp)))
- (unwind-protect
- (progn
- (js2-enter-loop pn)
- ;; We have to parse the body -after- creating the loop node,
- ;; so that the loop node appears in the js2-loop-set, allowing
- ;; break/continue statements to find the enclosing loop.
- (setf body (js2-parse-statement)
- (js2-loop-node-body pn) body
- (js2-node-pos pn) for-pos
- (js2-node-len pn) (- (js2-node-end body) for-pos))
- (js2-node-add-children pn init cond incr body))
- ;; finally
- (js2-exit-loop))
+ (progn
+ ;; parse init clause
+ (let ((js2-in-for-init t)) ; set as dynamic variable
+ (cond
+ ((= tt js2-SEMI)
+ (js2-unget-token)
+ (setq init (make-js2-empty-expr-node)))
+ ((or (= tt js2-VAR) (= tt js2-LET))
+ (setq init (js2-parse-variables tt (js2-current-token-beg))))
+ (t
+ (js2-unget-token)
+ (setq init (js2-parse-expr)))))
+ (if (or (js2-match-token js2-IN)
+ (and (>= js2-language-version 200)
+ (js2-match-contextual-kwd "of")
+ (setq is-for-of t)))
+ (setq is-for-in-or-of t
+ in-pos (- (js2-current-token-beg) for-pos)
+ ;; scope of iteration target object is not the scope we've
created above.
+ ;; stash current scope temporary.
+ cond (let ((js2-current-scope (js2-scope-parent-scope
js2-current-scope)))
+ (js2-parse-expr))) ; object over which we're
iterating
+ ;; else ordinary for loop - parse cond and incr
+ (js2-must-match js2-SEMI "msg.no.semi.for")
+ (setq cond (if (= (js2-peek-token) js2-SEMI)
+ (make-js2-empty-expr-node) ; no loop condition
+ (js2-parse-expr)))
+ (js2-must-match js2-SEMI "msg.no.semi.for.cond")
+ (setq tmp-pos (js2-current-token-end)
+ incr (if (= (js2-peek-token) js2-RP)
+ (make-js2-empty-expr-node :pos tmp-pos)
+ (js2-parse-expr)))))
(js2-pop-scope))
+ (if (js2-must-match js2-RP "msg.no.paren.for.ctrl")
+ (setq rp (- (js2-current-token-beg) for-pos)))
+ (if (not is-for-in-or-of)
+ (setq pn (make-js2-for-node :init init
+ :condition cond
+ :update incr
+ :lp lp
+ :rp rp))
+ ;; cond could be null if 'in obj' got eaten by the init node.
+ (if (js2-infix-node-p init)
+ ;; it was (foo in bar) instead of (var foo in bar)
+ (setq cond (js2-infix-node-right init)
+ init (js2-infix-node-left init))
+ (if (and (js2-var-decl-node-p init)
+ (> (length (js2-var-decl-node-kids init)) 1))
+ (js2-report-error "msg.mult.index")))
+ (setq pn (make-js2-for-in-node :iterator init
+ :object cond
+ :in-pos in-pos
+ :foreach-p is-for-each
+ :each-pos each-pos
+ :forof-p is-for-of
+ :lp lp
+ :rp rp)))
+ ;; Transplant the declarations.
+ (setf (js2-scope-symbol-table pn)
+ (js2-scope-symbol-table tmp-scope))
+ (unwind-protect
+ (progn
+ (js2-enter-loop pn)
+ ;; We have to parse the body -after- creating the loop node,
+ ;; so that the loop node appears in the js2-loop-set, allowing
+ ;; break/continue statements to find the enclosing loop.
+ (setf body (js2-parse-statement)
+ (js2-loop-node-body pn) body
+ (js2-node-pos pn) for-pos
+ (js2-node-len pn) (- (js2-node-end body) for-pos))
+ (js2-node-add-children pn init cond incr body))
+ ;; finally
+ (js2-exit-loop))
pn))
(defun js2-parse-try ()
@@ -10160,6 +10166,9 @@ We should have just parsed the 'for' keyword before
calling this function."
:loops (nreverse loops)
:filters (and filter (list (car filter)))
:form 'LEGACY_ARRAY))
+ ;; Set comp loop's parent to the last loop.
+ ;; TODO: Get rid of the bogus expr scope.
+ (setf (js2-scope-parent-scope result) first)
(apply #'js2-node-add-children result expr (car filter)
(js2-comp-node-loops result))
result))
diff --git a/tests/parser.el b/tests/parser.el
index 8c44028..4c9b467 100644
--- a/tests/parser.el
+++ b/tests/parser.el
@@ -706,6 +706,20 @@ the test."
(should (= (js2-symbol-decl-type var-entry) js2-VAR))
(should (js2-name-node-p (js2-symbol-ast-node var-entry)))))
+(js2-deftest for-node-is-declaration-scope "for (let i = 0; i; ++i) {};"
+ (js2-mode)
+ (search-forward "i")
+ (forward-char -1)
+ (let ((scope (js2-node-get-enclosing-scope (js2-node-at-point))))
+ (should (js2-for-node-p (js2-get-defining-scope scope "i")))))
+
+(js2-deftest array-comp-is-result-scope "[x * 2 for (x in y)];"
+ (js2-mode)
+ (search-forward "x")
+ (forward-char -1)
+ (let ((scope (js2-node-get-enclosing-scope (js2-node-at-point))))
+ (should (js2-comp-loop-node-p (js2-get-defining-scope scope "x")))))
+
;;; Tokenizer
(js2-deftest get-token "(1+1)"
- [elpa] master updated (c10ba4b -> 54df259), Dmitry Gutov, 2015/04/23
- [elpa] master fae5776 01/22: Check that the let declaration comes before the reference, Dmitry Gutov, 2015/04/23
- [elpa] master dd2106b 02/22: Merge branch 'let-temporal-dz', Dmitry Gutov, 2015/04/23
- [elpa] master 28853c9 03/22: do auto semicolon insert on function exports, Dmitry Gutov, 2015/04/23
- [elpa] master dfad0d5 04/22: Merge pull request #211 from cowboyd/no-semicolon-warning-on-function-export, Dmitry Gutov, 2015/04/23
- [elpa] master 02fea21 06/22: Merge pull request #213 from lelit/typos, Dmitry Gutov, 2015/04/23
- [elpa] master bf454ef 05/22: Fix typos in comments and docstrings, Dmitry Gutov, 2015/04/23
- [elpa] master 7bf479a 08/22: Fix js2-paren-node length, Dmitry Gutov, 2015/04/23
- [elpa] master 4d8ec67 07/22: Rely on bogus scopes less,
Dmitry Gutov <=
- [elpa] master 4a1b4e8 09/22: Parse without error first method in a class with keyword name, Dmitry Gutov, 2015/04/23
- [elpa] master 90a9056 10/22: ...or any following one, Dmitry Gutov, 2015/04/23
- [elpa] master bc61ce0 11/22: Fix off-by-one error for comment node length, Dmitry Gutov, 2015/04/23
- [elpa] master 3b76567 12/22: Fix js2-node-get-enclosing-scope, Dmitry Gutov, 2015/04/23
- [elpa] master 458d3fe 14/22: Merge pull request #221 from jacksonrayhamilton/enclosing-scope, Dmitry Gutov, 2015/04/23
- [elpa] master a184642 13/22: Merge pull request #220 from jacksonrayhamilton/comment-length, Dmitry Gutov, 2015/04/23
- [elpa] master 2bb4db0 15/22: Assign quote syntax to backquotes, Dmitry Gutov, 2015/04/23
- [elpa] master 4de6f03 16/22: Don't indent in multiline strings, Dmitry Gutov, 2015/04/23
- [elpa] master ee4a202 18/22: Merge pull request #195 from jacksonrayhamilton/pretty-multiline-declarations, Dmitry Gutov, 2015/04/23
- [elpa] master d4d9c54 17/22: js2-pretty-multiline-declarations: Add 'dynamic option, Dmitry Gutov, 2015/04/23