[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}")
- [elpa] master c4f4095 28/38: Only jump if not already at var or function definition, (continued)
- [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, 2015/09/09
- [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 <=