X-Git-Url: https://code.delx.au/gnu-emacs-elpa/blobdiff_plain/87f43f37c6b4a94fa15b0d95dfdb3ac7dafde77b..58857dc01d4de5196f39f02afd12151ac4d0d349:/js2-mode.el?ds=sidebyside diff --git a/js2-mode.el b/js2-mode.el index c999e481a..4d9bbf8da 100644 --- a/js2-mode.el +++ b/js2-mode.el @@ -1456,7 +1456,7 @@ the correct number of ARGS must be provided." "Compilation produced %s syntax errors.") (js2-msg "msg.var.redecl" - "TypeError: redeclaration of var %s.") + "Redeclaration of var %s.") (js2-msg "msg.const.redecl" "TypeError: redeclaration of const %s.") @@ -7264,7 +7264,7 @@ are ignored." when (and (eq 'block (js2-comment-node-format node)) (save-excursion (goto-char (js2-node-abs-pos node)) - (looking-at "/\\*global "))) + (looking-at "/\\* *global "))) append (js2-get-jslint-globals-in (match-end 0) (js2-node-abs-end node)))) @@ -7456,22 +7456,23 @@ We do a depth-first traversal of NODE. For any functions we find, we append the property name to QNAME, then call `js2-record-imenu-entry'." (let (right) (dolist (e (js2-object-node-elems node)) ; e is a `js2-object-prop-node' - (let ((left (js2-infix-node-left e)) - ;; Element positions are relative to the parent position. - (pos (+ pos (js2-node-pos e)))) - (cond - ;; foo: function() {...} - ((js2-function-node-p (setq right (js2-infix-node-right e))) - (when (js2-prop-node-name left) - ;; As a policy decision, we record the position of the property, - ;; not the position of the `function' keyword, since the property - ;; is effectively the name of the function. - (js2-record-imenu-entry right (append qname (list left)) pos))) - ;; foo: {object-literal} -- add foo to qname, offset position, and recurse - ((js2-object-node-p right) - (js2-record-object-literal right - (append qname (list (js2-infix-node-left e))) - (+ pos (js2-node-pos right))))))))) + (when (js2-infix-node-p e) + (let ((left (js2-infix-node-left e)) + ;; Element positions are relative to the parent position. + (pos (+ pos (js2-node-pos e)))) + (cond + ;; foo: function() {...} + ((js2-function-node-p (setq right (js2-infix-node-right e))) + (when (js2-prop-node-name left) + ;; As a policy decision, we record the position of the property, + ;; not the position of the `function' keyword, since the property + ;; is effectively the name of the function. + (js2-record-imenu-entry right (append qname (list left)) pos))) + ;; foo: {object-literal} -- add foo to qname, offset position, and recurse + ((js2-object-node-p right) + (js2-record-object-literal right + (append qname (list (js2-infix-node-left e))) + (+ pos (js2-node-pos right)))))))))) (defun js2-node-top-level-decl-p (node) "Return t if NODE's name is defined in the top-level scope. @@ -8098,13 +8099,25 @@ declared; probably to check them for errors." (list node))) ((js2-object-node-p node) (dolist (elem (js2-object-node-elems node)) - ;; js2-infix-node-p catches both object prop node and initialized - ;; binding element (which is directly an infix node). - (when (js2-infix-node-p elem) - (push (js2-define-destruct-symbols - (js2-infix-node-left elem) - decl-type face ignore-not-in-block) - name-nodes))) + (let ((subexpr (cond + ((and (js2-infix-node-p elem) + (= js2-ASSIGN (js2-infix-node-type elem))) + ;; Destructuring with default argument. + (js2-infix-node-left elem)) + ((and (js2-infix-node-p elem) + (= js2-COLON (js2-infix-node-type elem))) + ;; In regular destructuring {a: aa, b: bb}, + ;; the var is on the right. In abbreviated + ;; destructuring {a, b}, right == left. + (js2-infix-node-right elem)) + ((and (js2-unary-node-p elem) + (= js2-TRIPLEDOT (js2-unary-node-type elem))) + ;; Destructuring with spread. + (js2-unary-node-operand elem))))) + (when subexpr + (push (js2-define-destruct-symbols + subexpr 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)) @@ -8599,7 +8612,7 @@ imports or a namespace import that follows it. (js2-define-symbol js2-LET (js2-name-node-name name-node) name-node t)))))) ((= (js2-peek-token) js2-NAME) - (let ((binding (js2-maybe-parse-export-binding))) + (let ((binding (js2-maybe-parse-export-binding t))) (let ((node-name (js2-export-binding-node-local-name binding))) (js2-define-symbol js2-LET (js2-name-node-name node-name) node-name t)) (setf (js2-import-clause-node-default-binding clause) binding) @@ -8632,50 +8645,47 @@ imports or a namespace import that follows it. "Parse a namespace import expression such as '* as bar'. The current token must be js2-MUL." (let ((beg (js2-current-token-beg))) - (when (js2-must-match js2-NAME "msg.syntax") - (if (equal "as" (js2-current-token-string)) - (when (js2-must-match-prop-name "msg.syntax") - (let ((node (make-js2-namespace-import-node - :pos beg - :len (- (js2-current-token-end) beg) - :name (make-js2-name-node - :pos (js2-current-token-beg) - :len (js2-current-token-end) - :name (js2-current-token-string))))) - (js2-node-add-children node (js2-namespace-import-node-name node)) - node)) - (js2-unget-token) - (js2-report-error "msg.syntax"))))) + (if (js2-match-contextual-kwd "as") + (when (js2-must-match-prop-name "msg.syntax") + (let ((node (make-js2-namespace-import-node + :pos beg + :len (- (js2-current-token-end) beg) + :name (make-js2-name-node + :pos (js2-current-token-beg) + :len (js2-current-token-end) + :name (js2-current-token-string))))) + (js2-node-add-children node (js2-namespace-import-node-name node)) + node)) + (js2-unget-token) + (js2-report-error "msg.syntax")))) (defun js2-parse-from-clause () "Parse the from clause in an import or export statement. E.g. from 'src/lib'" - (when (js2-must-match-name "msg.mod.from.after.import.spec.set") - (let ((beg (js2-current-token-beg))) - (if (equal "from" (js2-current-token-string)) - (cond - ((js2-match-token js2-STRING) - (make-js2-from-clause-node - :pos beg - :len (- (js2-current-token-end) beg) - :module-id (js2-current-token-string) - :metadata-p nil)) - ((js2-match-token js2-THIS) - (when (js2-must-match-name "msg.mod.spec.after.from") - (if (equal "module" (js2-current-token-string)) - (make-js2-from-clause-node - :pos beg - :len (- (js2-current-token-end) beg) - :module-id "this" - :metadata-p t) - (js2-unget-token) - (js2-unget-token) - (js2-report-error "msg.mod.spec.after.from") - nil))) - (t (js2-report-error "msg.mod.spec.after.from") nil)) - (js2-unget-token) - (js2-report-error "msg.mod.from.after.import.spec.set") - nil)))) + (if (js2-match-contextual-kwd "from") + (let ((beg (js2-current-token-beg))) + (cond + ((js2-match-token js2-STRING) + (make-js2-from-clause-node + :pos beg + :len (- (js2-current-token-end) beg) + :module-id (js2-current-token-string) + :metadata-p nil)) + ((js2-match-token js2-THIS) + (when (js2-must-match-name "msg.mod.spec.after.from") + (if (equal "module" (js2-current-token-string)) + (make-js2-from-clause-node + :pos beg + :len (- (js2-current-token-end) beg) + :module-id "this" + :metadata-p t) + (js2-unget-token) + (js2-unget-token) + (js2-report-error "msg.mod.spec.after.from") + nil))) + (t (js2-report-error "msg.mod.spec.after.from") nil))) + (js2-report-error "msg.mod.from.after.import.spec.set") + nil)) (defun js2-parse-export-bindings (&optional import-p) "Parse a list of export binding expressions such as {}, {foo, bar}, and @@ -8683,7 +8693,7 @@ The current token must be js2-MUL." js2-LC. Return a lisp list of js2-export-binding-node" (let ((bindings (list))) (while - (let ((binding (js2-maybe-parse-export-binding))) + (let ((binding (js2-maybe-parse-export-binding import-p))) (when binding (push binding bindings)) (js2-match-token js2-COMMA))) @@ -8692,7 +8702,7 @@ js2-LC. Return a lisp list of js2-export-binding-node" "msg.mod.rc.after.export.spec.list")) (reverse bindings)))) -(defun js2-maybe-parse-export-binding () +(defun js2-maybe-parse-export-binding (&optional import-p) "Attempt to parse a binding expression found inside an import/export statement. This can take the form of either as single js2-NAME token as in 'foo' or as in a rebinding expression 'bar as foo'. If it matches, it will return an instance of @@ -8704,45 +8714,49 @@ consumes no tokens." (is-reserved-name (or (= (js2-current-token-type) js2-RESERVED) (aref js2-kwd-tokens (js2-current-token-type))))) (if extern-name - (let ((as (and (js2-match-token js2-NAME) (js2-current-token-string)))) - (if (and as (equal "as" (js2-current-token-string))) - (let ((name - (or - (and (js2-match-token js2-DEFAULT) "default") - (and (js2-match-token js2-NAME) (js2-current-token-string))))) - (if name - (let ((node (make-js2-export-binding-node - :pos beg - :len (- (js2-current-token-end) beg) - :local-name (make-js2-name-node - :name name - :pos (js2-current-token-beg) - :len (js2-current-token-len)) - :extern-name (make-js2-name-node - :name extern-name - :pos beg - :len extern-name-len)))) - (js2-node-add-children - node - (js2-export-binding-node-local-name node) - (js2-export-binding-node-extern-name node)) - node) - (js2-unget-token) - nil)) - (when as (js2-unget-token)) - (let* ((name-node (make-js2-name-node - :name (js2-current-token-string) - :pos (js2-current-token-beg) - :len (js2-current-token-len))) - (node (make-js2-export-binding-node - :pos (js2-current-token-beg) - :len (js2-current-token-len) - :local-name name-node - :extern-name name-node))) - (when is-reserved-name - (js2-report-error "msg.mod.as.after.reserved.word" extern-name)) - (js2-node-add-children node name-node) - node))) + (if (js2-match-contextual-kwd "as") + (let ((name + (or + (and (js2-match-token js2-DEFAULT) "default") + (and (js2-match-token js2-NAME) (js2-current-token-string))))) + (if name + (let ((node (make-js2-export-binding-node + :pos beg + :len (- (js2-current-token-end) beg) + :local-name (make-js2-name-node + :name name + :pos (js2-current-token-beg) + :len (js2-current-token-len)) + :extern-name (make-js2-name-node + :name extern-name + :pos beg + :len extern-name-len)))) + (js2-node-add-children + node + (js2-export-binding-node-local-name node) + (js2-export-binding-node-extern-name node)) + (if import-p + (js2-set-face (js2-current-token-beg) (js2-current-token-end) + 'font-lock-variable-name-face 'record)) + node) + (js2-unget-token) + nil)) + (let* ((name-node (make-js2-name-node + :name (js2-current-token-string) + :pos (js2-current-token-beg) + :len (js2-current-token-len))) + (node (make-js2-export-binding-node + :pos (js2-current-token-beg) + :len (js2-current-token-len) + :local-name name-node + :extern-name name-node))) + (when is-reserved-name + (js2-report-error "msg.mod.as.after.reserved.word" extern-name)) + (js2-node-add-children node name-node) + (if import-p + (js2-set-face (js2-current-token-beg) (js2-current-token-end) + 'font-lock-variable-name-face 'record)) + node)) nil))) (defun js2-parse-switch () @@ -8870,12 +8884,9 @@ invalid export statements." (when exports-list (dolist (export exports-list) (push export children))) - (when (js2-match-token js2-NAME) - (if (equal "from" (js2-current-token-string)) - (progn - (js2-unget-token) - (setq from-clause (js2-parse-from-clause))) - (js2-unget-token)))) + (when (js2-match-contextual-kwd "from") + (js2-unget-token) + (setq from-clause (js2-parse-from-clause)))) ((js2-match-token js2-DEFAULT) (setq default (cond ((js2-match-token js2-CLASS) (js2-parse-class-stmt)) @@ -10732,16 +10743,19 @@ If ONLY-OF-P is non-nil, only the 'for (foo of bar)' form is allowed." `js2-method-node') as a string, or nil if it can't be represented as a string (e.g., the key is computed by an expression)." - (let ((key (js2-infix-node-left property-node))) - (when (js2-computed-prop-name-node-p key) - (setq key (js2-computed-prop-name-node-expr key))) - (cond - ((js2-name-node-p key) - (js2-name-node-name key)) - ((js2-string-node-p key) - (js2-string-node-value key)) - ((js2-number-node-p key) - (js2-number-node-value key))))) + (cond + ((js2-unary-node-p property-node) nil) ;; {...foo} + (t + (let ((key (js2-infix-node-left property-node))) + (when (js2-computed-prop-name-node-p key) + (setq key (js2-computed-prop-name-node-expr key))) + (cond + ((js2-name-node-p key) + (js2-name-node-name key)) + ((js2-string-node-p key) + (js2-string-node-value key)) + ((js2-number-node-p key) + (js2-number-node-value key))))))) (defun js2-parse-object-literal-elems (&optional class-p) (let ((pos (js2-current-token-beg)) @@ -10776,7 +10790,13 @@ expression)." (setq previous-token (js2-current-token) tt (js2-get-prop-name-token)))) (cond - ;; Found a property (of any sort) + ;; Rest/spread (...expr) + ((and (>= js2-language-version 200) + (not class-p) (not static) (not previous-token) + (= js2-TRIPLEDOT tt)) + (setq after-comma nil + elem (js2-make-unary js2-TRIPLEDOT 'js2-parse-assign-expr))) + ;; Found a key/value property (of any sort) ((member tt (list js2-NAME js2-STRING js2-NUMBER js2-LB)) (setq after-comma nil elem (js2-parse-named-prop tt previous-token)) @@ -12569,7 +12589,9 @@ it marks the next defun after the ones already marked." (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)) + (if (eval-when-compile (fboundp 'xref-push-marker-stack)) + (xref-push-marker-stack) + (ring-insert find-tag-marker-ring (point-marker))) (js2-reparse) (let* ((node (js2-node-at-point)) (parent (js2-node-parent node))