branch: externals/js2-mode
commit 392492eb857d9fb72e0cfa12bff0df7b5127d651
Merge: ed955e7 fc323ad
Author: Dmitry Gutov <[email protected]>
Commit: GitHub <[email protected]>
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