emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 5ffca32 38/38: Merge commit '5c9d8b82dddec2fab370ec8798569


From: Dmitry Gutov
Subject: [elpa] master 5ffca32 38/38: Merge commit '5c9d8b82dddec2fab370ec8798569c7fc5698093' from js2-mode
Date: Wed, 09 Sep 2015 18:41:52 +0000

branch: master
commit 5ffca32900b224805cb6e679798d53d999b1dcc0
Merge: 8ad76a7 5c9d8b8
Author: Dmitry Gutov <address@hidden>
Commit: Dmitry Gutov <address@hidden>

    Merge commit '5c9d8b82dddec2fab370ec8798569c7fc5698093' from js2-mode
---
 packages/js2-mode/Makefile            |    2 +-
 packages/js2-mode/NEWS.md             |   18 +++
 packages/js2-mode/js2-mode.el         |  223 +++++++++++++++++++++++++--------
 packages/js2-mode/js2-old-indent.el   |   20 ++--
 packages/js2-mode/tests/indent.el     |    1 +
 packages/js2-mode/tests/navigation.el |   60 +++++++++
 packages/js2-mode/tests/parser.el     |    6 +-
 7 files changed, 258 insertions(+), 72 deletions(-)

diff --git a/packages/js2-mode/Makefile b/packages/js2-mode/Makefile
index f86786f..08b1e48 100644
--- a/packages/js2-mode/Makefile
+++ b/packages/js2-mode/Makefile
@@ -22,5 +22,5 @@ js2-imenu-extras.elc: js2-mode.elc
        ${EMACS} $(BATCHFLAGS) -l ./js2-mode.elc -f batch-byte-compile $*.el
 
 test:
-       ${EMACS} $(BATCHFLAGS) -l js2-mode.el -l tests/parser.el\
+       ${EMACS} $(BATCHFLAGS) -L . -l js2-mode.el -l js2-old-indent.el -l 
tests/parser.el\
          -l tests/indent.el -l tests/externs.el -f ert-run-tests-batch-and-exit
diff --git a/packages/js2-mode/NEWS.md b/packages/js2-mode/NEWS.md
index 300bc84..2984e91 100644
--- a/packages/js2-mode/NEWS.md
+++ b/packages/js2-mode/NEWS.md
@@ -1,5 +1,23 @@
 # History of user-visible changes
 
+## 20150909
+
+* `js2-mode` now derives from `js-mode`. That means the former
+  function will run `js-mode-hook`, as well as `js2-mode-hook`. The
+  key bindings will default to `js-mode-map` where they're not set in
+  `js2-mode-map`. And in Emacs 25 or later (including the snapshot
+  builds), `js2-mode` uses the indentation code from `js-mode`.  Where
+  feasible, the user options (and functions) now have aliases, but if
+  you're using Emacs 25 and you see an indentation-related setting
+  that stopped working, try looking for a corresponding one in the
+  `js` group: `M-x customize-group RET js RET`.
+
+* New command: `js2-jump-to-definition`. It's bound to `M-.` by
+  default, via remapping `js-find-symbol`. To get back to the default
+  `M-.` binding (e.g. `find-tag`), put this in your init file:
+
+      (eval-after-load 'js (define-key js-mode-map (kbd "M-.") nil))
+
 ## 20150713
 
 * More comprehensive strict mode warnings and syntax errors.
diff --git a/packages/js2-mode/js2-mode.el b/packages/js2-mode/js2-mode.el
index 6ea2461..97f3269 100644
--- a/packages/js2-mode/js2-mode.el
+++ b/packages/js2-mode/js2-mode.el
@@ -7,7 +7,7 @@
 ;;         Dmitry Gutov <address@hidden>
 ;; URL:  https://github.com/mooz/js2-mode/
 ;;       http://code.google.com/p/js2-mode/
-;; Version: 20150713
+;; Version: 20150909
 ;; Keywords: languages, javascript
 ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
 
@@ -88,13 +88,15 @@
 (require 'cl-lib)
 (require 'imenu)
 (require 'js)
+(require 'etags)
 
 (eval-and-compile
   (if (version< emacs-version "25.0")
       (require 'js2-old-indent)
     (defvaralias 'js2-basic-offset 'js-indent-level nil)
     (defalias 'js2-proper-indentation 'js--proper-indentation)
-    (defalias 'js2-indent-line 'js-indent-line)))
+    (defalias 'js2-indent-line 'js-indent-line)
+    (defalias 'js2-re-search-forward 'js--re-search-forward)))
 
 ;;; Externs (variables presumed to be defined by the host system)
 
@@ -1114,6 +1116,7 @@ information."
     (define-key map (kbd "C-c C-o") #'js2-mode-toggle-element)
     (define-key map (kbd "C-c C-w") #'js2-mode-toggle-warnings-and-errors)
     (define-key map [down-mouse-3] #'js2-down-mouse-3)
+    (define-key map [remap js-find-symbol] #'js2-jump-to-definition)
 
     (define-key map [menu-bar javascript]
       (cons "JavaScript" (make-sparse-keymap "JavaScript")))
@@ -6818,7 +6821,7 @@ of a simple name.  Called before EXPR has a parent node."
 
 (defconst js2-jsdoc-param-tag-regexp
   (concat "^\\s-*\\*+\\s-*\\(@"
-          "\\(?:param\\|argument\\)"
+          "\\(?:param\\|arg\\(?:ument\\)?\\|prop\\(?:erty\\)?\\)"
           "\\)"
           "\\s-*\\({[^}]+}\\)?"         ; optional type
           "\\s-*\\[?\\([[:alnum:]_$\.]+\\)?\\]?"  ; name
@@ -6860,7 +6863,6 @@ of a simple name.  Called before EXPR has a parent node."
              "memberOf"
              "name"
              "namespace"
-             "property"
              "since"
              "suppress"
              "this"
@@ -7966,46 +7968,42 @@ Scanner should be initialized."
     (js2-node-add-children fn-node pn)
     pn))
 
-(defun js2-define-destruct-symbols-internal
-    (node decl-type face &optional ignore-not-in-block name-nodes)
-  "Internal version of `js2-define-destruct-symbols'.  The only
-difference is that NAME-NODES is passed down recursively."
-  (cond
-   ((js2-name-node-p node)
-    (let (leftpos)
-      (js2-define-symbol decl-type (js2-name-node-name node)
-                         node ignore-not-in-block)
-      (when face
-        (js2-set-face (setq leftpos (js2-node-abs-pos node))
-                      (+ leftpos (js2-node-len node))
-                      face 'record))
-      (setq name-nodes (append name-nodes (list node)))))
-   ((js2-object-node-p node)
-    (dolist (elem (js2-object-node-elems node))
-      (setq name-nodes
-            (append name-nodes
-                    (js2-define-destruct-symbols-internal
-                     ;; In abbreviated destructuring {a, b}, right == left.
-                     (js2-object-prop-node-right elem)
-                     decl-type face ignore-not-in-block name-nodes)))))
-   ((js2-array-node-p node)
-    (dolist (elem (js2-array-node-elems node))
-      (when elem
-        (setq name-nodes
-              (append name-nodes
-                      (js2-define-destruct-symbols-internal
-                       elem decl-type face ignore-not-in-block name-nodes))))))
-   (t (js2-report-error "msg.no.parm" nil (js2-node-abs-pos node)
-                        (js2-node-len node))))
-  name-nodes)
-
 (defun js2-define-destruct-symbols (node decl-type face &optional 
ignore-not-in-block)
   "Declare and fontify destructuring parameters inside NODE.
 NODE is either `js2-array-node', `js2-object-node', or `js2-name-node'.
 
 Return a list of `js2-name-node' nodes representing the symbols
 declared; probably to check them for errors."
-  (js2-define-destruct-symbols-internal node decl-type face 
ignore-not-in-block))
+  (let (name-nodes)
+    (cond
+     ((js2-name-node-p node)
+      (let (leftpos)
+        (js2-define-symbol decl-type (js2-name-node-name node)
+                           node ignore-not-in-block)
+        (when face
+          (js2-set-face (setq leftpos (js2-node-abs-pos node))
+                        (+ leftpos (js2-node-len node))
+                        face 'record))
+        (list node)))
+     ((js2-object-node-p node)
+      (dolist (elem (js2-object-node-elems node))
+        (when (js2-object-prop-node-p elem)
+          (push (js2-define-destruct-symbols
+                 ;; In abbreviated destructuring {a, b}, right == left.
+                 (js2-object-prop-node-right elem)
+                 decl-type face ignore-not-in-block)
+                name-nodes)))
+      (apply #'append (nreverse name-nodes)))
+     ((js2-array-node-p node)
+      (dolist (elem (js2-array-node-elems node))
+        (when elem
+          (push (js2-define-destruct-symbols
+                 elem decl-type face ignore-not-in-block)
+                name-nodes)))
+      (apply #'append (nreverse name-nodes)))
+     (t (js2-report-error "msg.no.parm" nil (js2-node-abs-pos node)
+                          (js2-node-len node))
+        nil))))
 
 (defvar js2-illegal-strict-identifiers
   '("eval" "arguments")
@@ -8041,7 +8039,7 @@ represented by FN-NODE at POS."
                                  (eq (js2-current-token-type) js2-NAME)))
           params param
           param-name-nodes new-param-name-nodes
-          default-found rest-param-at)
+          rest-param-at)
       (when paren-free-arrow
         (js2-unget-token))
       (cl-loop for tt = (js2-peek-token)
@@ -8051,8 +8049,6 @@ represented by FN-NODE at POS."
                 ((and (not paren-free-arrow)
                       (or (= tt js2-LB) (= tt js2-LC)))
                  (js2-get-token)
-                 (when default-found
-                   (js2-report-error "msg.no.default.after.default.param"))
                  (setq param (js2-parse-destruct-primary-expr)
                        new-param-name-nodes (js2-define-destruct-symbols
                                              param js2-LP 'js2-function-param))
@@ -8074,14 +8070,8 @@ represented by FN-NODE at POS."
                  (js2-check-strict-function-params param-name-nodes (list 
param))
                  (setq param-name-nodes (append param-name-nodes (list param)))
                  ;; default parameter value
-                 (when (or (and default-found
-                                (not rest-param-at)
-                                (js2-must-match js2-ASSIGN
-                                                
"msg.no.default.after.default.param"
-                                                (js2-node-pos param)
-                                                (js2-node-len param)))
-                           (and (>= js2-language-version 200)
-                                (js2-match-token js2-ASSIGN)))
+                 (when (and (>= js2-language-version 200)
+                            (js2-match-token js2-ASSIGN))
                    (cl-assert (not paren-free-arrow))
                    (let* ((pos (js2-node-pos param))
                           (tt (js2-current-token-type))
@@ -8091,8 +8081,7 @@ represented by FN-NODE at POS."
                           (len (- (js2-node-end right) pos)))
                      (setq param (make-js2-assign-node
                                   :type tt :pos pos :len len :op-pos op-pos
-                                  :left left :right right)
-                           default-found t)
+                                  :left left :right right))
                      (js2-node-add-children param left right)))
                  (push param params)))
                (when (and rest-param-at (> (length params) (1+ rest-param-at)))
@@ -11129,9 +11118,11 @@ such as `js-mode', while retaining the asynchronous 
error/warning
 highlighting features of `js2-mode'."
   :group 'js2-mode
   :lighter " js-lint"
-  (if js2-minor-mode
-      (js2-minor-mode-enter)
-    (js2-minor-mode-exit)))
+  (if (derived-mode-p 'js2-mode)
+      (setq js2-minor-mode nil)
+    (if js2-minor-mode
+        (js2-minor-mode-enter)
+      (js2-minor-mode-exit))))
 
 (defun js2-minor-mode-enter ()
   "Initialization for `js2-minor-mode'."
@@ -11278,7 +11269,6 @@ Selecting an error will jump it to the corresponding 
source-buffer error.
 ;;;###autoload
 (define-derived-mode js2-mode js-mode "Javascript-IDE"
   "Major mode for editing JavaScript code."
-  ;; Used by comment-region; don't change it.
   (set (make-local-variable 'max-lisp-eval-depth)
        (max max-lisp-eval-depth 3000))
   (set (make-local-variable 'indent-line-function) #'js2-indent-line)
@@ -12309,6 +12299,129 @@ it marks the next defun after the ones already 
marked."
     (unless (js2-ast-root-p fn)
       (narrow-to-region beg (+ beg (js2-node-len fn))))))
 
+(defun js2-jump-to-definition (&optional arg)
+  "Jump to the definition of an object's property, variable or function."
+  (interactive "P")
+  (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 (let ((temp (js2-compute-nested-prop-get parent)))
+                               (cl-loop for n in temp
+                                        with result = '()
+                                        do (push n result)
+                                        until (equal node n)
+                                        finally return result)))))
+         node-init)
+    (unless (and (js2-name-node-p node)
+                 (not (js2-var-init-node-p parent))
+                 (not (js2-function-node-p parent)))
+      (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)))
+                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)
+                   (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) (car 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-object (node name-node)
+  "Check if object NODE contains element with NAME-NODE."
+  (cl-assert (js2-object-node-p node))
+  ;; Only support name-node 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)
+                       (equal (js2-name-node-name name-node)
+                              (js2-name-node-name left)))
+                  (and (js2-string-node-p left)
+                       (string= (js2-name-node-name name-node)
+                                (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 NODE scope for jump location matching NAMES.
+NAMES is a list of property values to search for. For functions
+and variables NAMES will contain one element."
+  (let (node-init
+        (val (js2-name-node-name (car 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-compute-nested-prop-get left))
+                          (found (cl-loop for prop in prop-list
+                                          until (not (string= 
(js2-name-node-name
+                                                               (pop 
temp-names))
+                                                              
(js2-name-node-name prop)))
+                                          if (not temp-names) return prop))
+                          (found-node (or found
+                                          (when (js2-object-node-p right)
+                                            (js2-search-object-for-prop right
+                                                                        
temp-names)))))
+                     (if found-node (push found-node node-init))))))
+           t))))
+    node-init))
+
+(defun js2-get-symbol-declaration (node 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)
 
 ;;; js2-mode.el ends here
diff --git a/packages/js2-mode/js2-old-indent.el 
b/packages/js2-mode/js2-old-indent.el
index 9b1c929..efc9053 100644
--- a/packages/js2-mode/js2-old-indent.el
+++ b/packages/js2-mode/js2-old-indent.el
@@ -396,7 +396,7 @@ indentation is aligned to that column."
   (save-excursion
     (back-to-indentation)
     (when (nth 4 parse-status)
-      (cl-return (js2-lineup-comment parse-status)))
+      (cl-return-from js2-proper-indentation (js2--comment-indent 
parse-status)))
     (let* ((at-closing-bracket (looking-at "[]})]"))
            (same-indent-p (or at-closing-bracket
                               (looking-at "\\_<case\\_>[^:]")
@@ -458,17 +458,13 @@ indentation is aligned to that column."
 
        (t 0)))))
 
-(defun js2-lineup-comment (parse-status)
-  "Indent a multi-line block comment continuation line."
-  (let* ((beg (nth 8 parse-status))
-         (first-line (js2-same-line beg))
-         (offset (save-excursion
-                   (goto-char beg)
-                   (if (looking-at "/\\*")
-                       (+ 1 (current-column))
-                     0))))
-    (unless first-line
-      (indent-line-to offset))))
+(defun js2--comment-indent (parse-status)
+  "Indentation inside a multi-line block comment continuation line."
+  (save-excursion
+    (goto-char (nth 8 parse-status))
+    (if (looking-at "/\\*")
+        (+ 1 (current-column))
+      0)))
 
 (defun js2-indent-line (&optional bounce-backwards)
   "Indent the current line as JavaScript source text."
diff --git a/packages/js2-mode/tests/indent.el 
b/packages/js2-mode/tests/indent.el
index df69202..27b6c5a 100644
--- a/packages/js2-mode/tests/indent.el
+++ b/packages/js2-mode/tests/indent.el
@@ -22,6 +22,7 @@
 (require 'ert)
 (require 'js2-mode)
 (require 'cl-lib)
+(require 'js2-old-indent)
 
 (defun js2-test-indent (content keep-indent)
   (let ((s (replace-regexp-in-string "^ *|" "" content)))
diff --git a/packages/js2-mode/tests/navigation.el 
b/packages/js2-mode/tests/navigation.el
new file mode 100644
index 0000000..d7a8314
--- /dev/null
+++ b/packages/js2-mode/tests/navigation.el
@@ -0,0 +1,60 @@
+;;; tests/navigation.el --- Some tests for js2-mode.
+
+;; Copyright (C) 2009, 2011-2015  Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'js2-mode)
+
+(cl-defun js2-navigation-helper (buffer-content &optional expected-point 
(point-offset 1))
+  (with-temp-buffer
+    (insert buffer-content)
+    (let ((start-point (or (- (point) point-offset))))
+      (js2-mode)
+      (goto-char start-point)
+      (ignore-errors (js2-jump-to-definition))
+      (print (format "%d %d" (point) start-point))
+      (should (= (point) (or expected-point start-point))))))
+
+(ert-deftest js2-jump-to-var ()
+  (js2-navigation-helper "var soup = 2; soup" 5))
+
+(ert-deftest js2-jump-to-function ()
+  (js2-navigation-helper "function aFunction() {}; aFunction" 1))
+
+(ert-deftest js2-jump-to-function-parameters ()
+  (js2-navigation-helper "var p1 = 4; function aFunction(p1, p2) {p1};" 32 4))
+
+(ert-deftest js2-jump-to-object-property ()
+  (js2-navigation-helper "var aObject = {prop1: 3, prop2: \"hello\"}; 
aObject.prop1" 16))
+
+(ert-deftest js2-no-jump-to-object-property ()
+  (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.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))
diff --git a/packages/js2-mode/tests/parser.el 
b/packages/js2-mode/tests/parser.el
index bfc5653..dc8c001 100644
--- a/packages/js2-mode/tests/parser.el
+++ b/packages/js2-mode/tests/parser.el
@@ -226,12 +226,10 @@ the test."
   "function foo(a = 1, b = a + 1) {\n}")
 
 (js2-deftest-parse function-with-no-default-after-default
-  "function foo(a = 1, b) {\n}"
-  :syntax-error "b")
+  "function foo(a = 1, b) {\n}")
 
 (js2-deftest-parse function-with-destruct-after-default
-  "function foo(a = 1, {b, c}) {\n}"
-  :syntax-error "{")
+  "function foo(a = 1, {b, c}) {\n}")
 
 (js2-deftest-parse function-with-rest-parameter
   "function foo(a, b, ...rest) {\n}")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]