diff --git a/js2-mode.el b/js2-mode.el index 11ebb373..637bb768 100644 --- a/js2-mode.el +++ b/js2-mode.el @@ -2344,6 +2344,15 @@ If any given node in NODES is nil, doesn't record that link." (defun js2-node-get-enclosing-scope (node) "Return the innermost `js2-scope' node surrounding NODE. Returns nil if there is no enclosing scope node." + ;; when node is the name of a function statement, the enclosing + ;; scope is not that function itself but the surrounding scope. + (let ((parent (js2-node-parent node))) + (when (and (js2-name-node-p node) + (js2-function-node-p parent) + (eq 'FUNCTION_STATEMENT (js2-function-node-form parent)) + (eq node (js2-function-node-name parent))) + (setq node parent))) + ;; dig up to find the closest scope parent (while (and (setq node (js2-node-parent node)) (not (js2-scope-p node)))) node) diff --git a/tests/parser.el b/tests/parser.el index 32c33e55..f6e6abcd 100644 --- a/tests/parser.el +++ b/tests/parser.el @@ -1214,11 +1214,14 @@ the test." (should (= (js2-symbol-decl-type var-entry) js2-VAR)) (should (js2-name-node-p (js2-symbol-ast-node var-entry))))) -(defun js2-test-scope-of-nth-variable-satisifies-predicate (variable nth predicate) +(defun js2-get-nth-variable-enclosing-scope (variable nth) (goto-char (point-min)) (dotimes (_ (1+ nth)) (search-forward variable)) (forward-char -1) - (let ((scope (js2-node-get-enclosing-scope (js2-node-at-point)))) + (js2-node-get-enclosing-scope (js2-node-at-point))) + +(defun js2-test-scope-of-nth-variable-satisifies-predicate (variable nth predicate) + (let ((scope (js2-get-nth-variable-enclosing-scope variable nth))) (should (funcall predicate (js2-get-defining-scope scope variable))))) (js2-deftest for-node-is-declaration-scope "for (let i = 0; i; ++i) {};" @@ -1239,6 +1242,12 @@ the test." (js2-mode--and-parse) (js2-test-scope-of-nth-variable-satisifies-predicate "x" 0 #'js2-comp-loop-node-p)) +(js2-deftest function-name-enclosing-scope-is-parent-scope "(function(){ var bar; function foo(){} })()" + (js2-mode--and-parse) + (let ((scope1 (js2-get-nth-variable-enclosing-scope "bar" 0)) + (scope2 (js2-get-nth-variable-enclosing-scope "foo" 0))) + (should (eq scope1 scope2)))) + (js2-deftest array-comp-has-parent-scope "var a,b=[for (i of [[1,2]]) for (j of i) j * a];" (js2-mode--and-parse)