branch: externals/js2-mode commit 392492eb857d9fb72e0cfa12bff0df7b5127d651 Merge: ed955e7 fc323ad Author: Dmitry Gutov <dgu...@yandex.ru> Commit: GitHub <nore...@github.com>
Merge pull request #517 from lelit/issue515 Issue515 --- js2-mode.el | 40 ++++++++++++++++++++++++++++++++++++---- tests/parser.el | 18 ++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/js2-mode.el b/js2-mode.el index fb5d6d5..567d629 100644 --- a/js2-mode.el +++ b/js2-mode.el @@ -7168,7 +7168,8 @@ key of a literal object." ;; ignore later (when (and (not declared) (js2-object-prop-node-p parent) - (eq node (js2-object-prop-node-left parent))) + (eq node (js2-object-prop-node-left parent)) + (not (eq node (js2-object-prop-node-right parent)))) (setq object-key t))) ;; Maybe this is a for loop and the variable is one of its iterators? (unless assigned @@ -7188,10 +7189,41 @@ key of a literal object." finally return syms)))))) (list declared assigned object-key))) +(defun js2--is-param (var-node params) + "Recursively determine whether VAR-NODE is contained in PARAMS." + (cond ((js2-object-prop-node-p params) + (eq var-node (js2-object-prop-node-left params))) + ((js2-name-node-p params) + (eq var-node params)) + (t + (let ((isparam (if (listp params) + (memq var-node params) + (cl-loop with found = nil + for p in (js2-node-child-list params) + while (null found) + do (setq found (eq var-node p)))))) + (unless isparam + (let ((kids (if (listp params) + params + (js2-node-child-list params)))) + (cl-loop for p in kids + while (null isparam) + do (setq isparam (js2--is-param var-node p))))) + isparam)))) + +(defun js2--is-function-param (parent var-node) + "Determine whether VAR-NODE is a function parameter." + (while (and parent (not (js2-function-node-p parent))) + (if (or (js2-var-init-node-p parent) + (js2-assign-node-p parent)) + (setq parent nil) + (setq parent (js2-node-parent parent)))) + (when parent + (js2--is-param var-node (js2-function-node-params parent)))) + (defun js2--classify-variable (parent node vars) - "Classify the single variable NODE, a js2-name-node." - (let ((function-param (and (js2-function-node-p parent) - (memq node (js2-function-node-params parent))))) + "Classify the single variable NODE, a js2-name-node, updating the VARS collection." + (let ((function-param (js2--is-function-param parent node))) (if (js2-prop-get-node-p parent) ;; If we are within a prop-get, e.g. the "bar" in "foo.bar", ;; just mark "foo" as used diff --git a/tests/parser.el b/tests/parser.el index 9137940..b1ac42e 100644 --- a/tests/parser.el +++ b/tests/parser.el @@ -1386,6 +1386,24 @@ the test." "import * as foo from 'module'; function bar() { return foo.x; }" '("foo@13:I" 56 "bar@41:U")) +(js2-deftest-classify-variables destructured-function-params-1 + "\ +function foo({var1}, var0) { + const bar = {var1}, + var2 = {bar}, + var3 = {var2}, + var4 = {bar, var1, var2, var3, var4}; + return({var4}); +}" + '("foo@10:U" "var1@15:P" 47 126 "var0@22:P" "bar@40:I" 72 121 "var2@64:I" 96 132 "var3@88:I" 138 "var4@113:I" 144 163)) + +(js2-deftest-classify-variables destructured-function-params-2 + "\ +function foo([var0, {var1}]) { + return var0 * var1; +}" + '("foo@10:U" "var0@15:P" 43 "var1@22:P" 50)) + ;; Side effects (js2-deftest no-side-effects-at-top-level