[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master aaf218a 27/38: Find definition by locating assignment node
From: |
Dmitry Gutov |
Subject: |
[elpa] master aaf218a 27/38: Find definition by locating assignment nodes |
Date: |
Wed, 09 Sep 2015 18:41:48 +0000 |
branch: master
commit aaf218a40225287f053e7f933b5af0d1e72e0f60
Author: ScottyB <address@hidden>
Commit: ScottyB <address@hidden>
Find definition by locating assignment nodes
---
js2-mode.el | 149 +++++++++++++++++++++++++++++++++++++--------------
tests/navigation.el | 8 +++-
2 files changed, 116 insertions(+), 41 deletions(-)
diff --git a/js2-mode.el b/js2-mode.el
index cf99e37..939e904 100644
--- a/js2-mode.el
+++ b/js2-mode.el
@@ -12305,61 +12305,129 @@ it marks the next defun after the ones already
marked."
(ring-insert find-tag-marker-ring (point-marker))
(let* ((node (js2-node-at-point))
(parent (js2-node-parent node))
- (names (if (js2-prop-get-node-p parent)(reverse (js2-prop-names-left
node))))
+ (names (if (js2-prop-get-node-p parent)(reverse (js2-names-left
node))))
node-init)
+ (unless (js2-name-node-p node)
+ (error "Node is not a supported jump node"))
(push (or (and names (pop names))
(unless (and (js2-object-prop-node-p parent)
(eq node (js2-object-prop-node-left parent)))
- (js2-name-node-name node))
- (error "Node is not a supported jump node")) names)
+ (js2-name-node-name node))) names)
(setq node-init (js2-search-scope node names))
+
+ ;; todo: display list of results in buffer
+ ;; todo: group found references by buffer
(unless node-init
- (switch-to-buffer (catch 'found
- (unless arg
- (mapc (lambda (b) (if (derived-mode-p 'js2-mode)
- (with-current-buffer b
- (setq node-init
(js2-search-scope js2-mode-ast names))
- (if node-init
- (throw 'found b)))))
- (buffer-list)))
- nil)))
+ (switch-to-buffer
+ (catch 'found
+ (unless arg
+ (mapc (lambda (b)
+ (with-current-buffer b
+ (when (derived-mode-p 'js2-mode)
+ (setq node-init (js2-search-scope js2-mode-ast names))
+ (if node-init
+ (throw 'found b)))))
+ (buffer-list)))
+ nil)))
+ (setq node-init (if (listp node-init) (first node-init) node-init))
(unless node-init
(pop-tag-mark)
(error "No jump location found"))
(goto-char (js2-node-abs-pos node-init))))
-(defun js2-search-scope (scope names)
+(defun js2-build-prop-name-list (prop-node)
+ "Build a list of names from a PROP-NODE."
+ (let* (names
+ left
+ left-node)
+ (unless (js2-prop-get-node-p prop-node)
+ (error "Node is not a property prop-node"))
+ (while (js2-prop-get-node-p prop-node)
+ (let ((node (js2-prop-get-node-right prop-node)))
+ (push `(,(js2-name-node-name node) . ,node) names)
+ (setq left-node (js2-prop-get-node-left prop-node))
+ (when (js2-name-node-p left-node)
+ (setq left `(,(js2-name-node-name left-node) . ,left-node)))
+ (setq prop-node left-node)))
+ (push left names)))
+
+(defun js2-search-object (node name)
+ "Check if object NODE contains element with NAME."
+ (unless (js2-object-node-p node)
+ (error "Only run depth search on `js2-object-node'"))
+ ;; Only support name and nodes for the time being
+ (cl-loop for elem in (js2-object-node-elems node)
+ for left = (js2-object-prop-node-left elem)
+ if (or (and (js2-name-node-p left)
+ (string= name (js2-name-node-name left)))
+ (and (js2-string-node-p left)
+ (string= name (js2-string-node-value left))))
+ return elem))
+
+(defun js2-search-object-for-prop (object prop-names)
+ "Return node in OBJECT that matches PROP-NAMES or nil.
+PROP-NAMES is a list of values representing a path to a value in OBJECT.
+i.e. ('name' 'value') = {name : { value: 3}}"
+ (let (node
+ (temp-object object)
+ (temp t) ;temporay node
+ (names prop-names))
+ (while (and temp names (js2-object-node-p temp-object))
+ (setq temp (js2-search-object temp-object (pop names)))
+ (and (setq node temp)
+ (setq temp-object (js2-object-prop-node-right temp) )))
+ (unless names node)))
+
+(defun js2-search-scope (node names)
"Searches SCOPE for jump location in NAMES."
- (let (node-init)
- (ignore-errors
- (setq node-init (js2-symbol-ast-node (js2-get-symbol-declaration scope
(pop names))))
- (when names
- (let ((found-node (js2-var-init-node-initializer (js2-node-parent
node-init))))
- (setq node-init nil)
- (when (js2-object-node-p found-node)
- (js2-visit-ast
- found-node
- (lambda (node endp)
- (unless endp
- (when (and (js2-object-prop-node-p node)
- (string= (car names)
- (js2-name-node-name
(js2-object-prop-node-left node))))
- (pop names)
- (unless names (setq node-init node)))
- t)))))))
+ (let (node-init
+ (val (first names)))
+ (setq node-init (js2-get-symbol-declaration node val))
+
+ (when (> (length names) 1)
+
+ ;; Check var declarations
+ (when (and node-init (string= val (js2-name-node-name node-init)))
+ (let ((parent (js2-node-parent node-init))
+ (temp-names names))
+ (pop temp-names) ;; First element is var name
+ (setq node-init (when (js2-var-init-node-p parent)
+ (js2-search-object-for-prop
(js2-var-init-node-initializer parent)
+ temp-names)))))
+
+ ;; Check all assign nodes
+ (js2-visit-ast
+ js2-mode-ast
+ (lambda (node endp)
+ (unless endp
+ (if (js2-assign-node-p node)
+ (let ((left (js2-assign-node-left node))
+ (right (js2-assign-node-right node))
+ (temp-names names))
+ (when (js2-prop-get-node-p left)
+ (let* ((prop-list (js2-build-prop-name-list left))
+ (prop-names (mapcar 'car prop-list))
+ (found (loop for prop in prop-names
+ until (not (string= (pop temp-names)
prop))
+ if (not temp-names) return prop)))
+
+ ;; todo: clean this up!
+ (if found (push (cdr (assoc found prop-list)) node-init)
+ (when (js2-object-node-p right)
+ (setq found (js2-search-object-for-prop right
temp-names)))
+ (if found (push found node-init))))))
+ t)))))
node-init))
(defun js2-names-left (name-node)
- "Create a list of all of the names in the property NAME-NODE.
-NAME-NODE must have a js2-prop-get-node as parent. Only adds
-properties to the left of point. This is so individual jump
-points can be found for each property in the chain."
+"Returns a list of names for a `js2-prop-get-node'.
+NAME-NODE is a node that forms part of the `js2-prop-get-node'."
(let* (name
(parent (js2-node-parent name-node))
left
names)
- (unless (or (js2-prop-get-node-p parent) (js2-name-node-p name-node))
- (error "Not a name node or doesn't have a prop-get-node as parent"))
+ (unless (js2-prop-get-node-p parent)
+ (error "Parent is not a prop-get-node"))
(setq name (js2-name-node-name name-node)
left (js2-prop-get-node-left parent))
(if (and (js2-name-node-p left)
@@ -12376,10 +12444,11 @@ points can be found for each property in the chain."
(if (listp names) names (list names))))
(defun js2-get-symbol-declaration (node name)
- "Find definition for NAME from NODE."
- (js2-scope-get-symbol (js2-get-defining-scope
- (or (js2-node-get-enclosing-scope node)
- node) name) name))
+ "Find scope for NAME from NODE."
+ (let ((scope (js2-get-defining-scope
+ (or (js2-node-get-enclosing-scope node)
+ node) name)))
+ (if scope (js2-symbol-ast-node (js2-scope-get-symbol scope name)))))
(provide 'js2-mode)
diff --git a/tests/navigation.el b/tests/navigation.el
index f07d466..3a3c240 100644
--- a/tests/navigation.el
+++ b/tests/navigation.el
@@ -48,7 +48,13 @@
(js2-navigation-helper "var aObject = {prop1: 3, prop2: \"hello\"};
anotherObject.prop1"))
(ert-deftest js2-jump-to-nested-property ()
- (js2-navigation-helper "var aObject = {prop1: {prop2: { prop3: 4}}};
aObject.prop3" 33))
+ (js2-navigation-helper "var aObject = {prop1: {prop2: { prop3: 4}}};
aObject.prop1.prop2.prop3" 33))
(ert-deftest js2-jump-to-object ()
(js2-navigation-helper "var aObject = {prop1: 3, prop2: \"hello\"};
aObject.prop1" 5 13))
+
+(ert-deftest js2-jump-to-property ()
+ (js2-navigation-helper "aObject.func = functon(){};aObject.func" 9))
+
+(ert-deftest js2-jump-to-property-object-property ()
+ (js2-navigation-helper "aObject.value = {prop:1};aObject.value.prop" 18))
- [elpa] master eba59c5 21/38: Added missing etags dependency, (continued)
- [elpa] master eba59c5 21/38: Added missing etags dependency, Dmitry Gutov, 2015/09/09
- [elpa] master 7184664 20/38: Add a jump to definition command bound to M-., Dmitry Gutov, 2015/09/09
- [elpa] master bc5cdb4 23/38: Simplified property name matching, Dmitry Gutov, 2015/09/09
- [elpa] master 1ee5c45 22/38: Return correct node when searching for the definition of a property., Dmitry Gutov, 2015/09/09
- [elpa] master 579aacb 24/38: Simplified method of searching for nodes based on scope, Dmitry Gutov, 2015/09/09
- [elpa] master f942b83 26/38: Support jumping to buffers of the same major mode, Dmitry Gutov, 2015/09/09
- [elpa] master 145c5d6 25/38: Fixed jumping to object properties, Dmitry Gutov, 2015/09/09
- [elpa] master bb0476c 29/38: Clarified js2-search-scope doc string, Dmitry Gutov, 2015/09/09
- [elpa] master c4f4095 28/38: Only jump if not already at var or function definition, Dmitry Gutov, 2015/09/09
- [elpa] master af85699 30/38: Clean up todo in js2-search-scope and fix year typo, Dmitry Gutov, 2015/09/09
- [elpa] master aaf218a 27/38: Find definition by locating assignment nodes,
Dmitry Gutov <=
- [elpa] master e236923 31/38: Removed functions: js2-build-prop-name-list and js2-names-left., Dmitry Gutov, 2015/09/09
- [elpa] master 75129c1 33/38: Use cl-assert instead of error, Dmitry Gutov, 2015/09/09
- [elpa] master bbb5086 34/38: Remove a space, Dmitry Gutov, 2015/09/09
- [elpa] master 58335d4 36/38: Add NEWS and bump the version, Dmitry Gutov, 2015/09/09
- [elpa] master 9ad7708 32/38: Add cl- prefix, improve line lengths, Dmitry Gutov, 2015/09/09
- [elpa] master ffa06cb 35/38: Explicitly remap js-find-symbol, Dmitry Gutov, 2015/09/09
- [elpa] master 5c9d8b8 37/38: Rephrase, Dmitry Gutov, 2015/09/09
- [elpa] master 5ffca32 38/38: Merge commit '5c9d8b82dddec2fab370ec8798569c7fc5698093' from js2-mode, Dmitry Gutov, 2015/09/09