[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/js2-mode b3841a7 24/61: Merge pull request #533 from re
From: |
Dmitry Gutov |
Subject: |
[elpa] externals/js2-mode b3841a7 24/61: Merge pull request #533 from redguardtoo/master |
Date: |
Sun, 20 Dec 2020 12:20:02 -0500 (EST) |
branch: externals/js2-mode
commit b3841a7a304d9d1328fdb0868fbbecf0c2f9831f
Merge: 999c0e7 8841175
Author: Dmitry Gutov <dgutov@yandex.ru>
Commit: GitHub <noreply@github.com>
Merge pull request #533 from redguardtoo/master
support optional chaining operator
---
NEWS.md | 1 +
js2-mode.el | 36 +++++++++++++++++++++++++++++++++---
tests/parser.el | 21 +++++++++++++++++++++
3 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/NEWS.md b/NEWS.md
index b3163a4..7fc9a6e 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -7,6 +7,7 @@
`js-mode` with `js2-minor-mode` (see README), rather than
`js2-jsx-mode`.
* Using `js2-jsx-mode` will now trigger a warning in Emacs 27.
+* Support for optional-chaining operator `?.`
## 2019-02-19
diff --git a/js2-mode.el b/js2-mode.el
index 4686be8..c05be21 100644
--- a/js2-mode.el
+++ b/js2-mode.el
@@ -635,7 +635,8 @@ which doesn't seem particularly useful, but Rhino permits
it."
(defvar js2-AWAIT 169) ; await (pseudo keyword)
(defvar js2-HOOK 170) ; conditional (?:)
-(defvar js2-EXPON 171)
+(defvar js2-OPTIONAL-CHAINING 171) ; optional chaining (?.prop obj?.[expr]
func?.())
+(defvar js2-EXPON 172)
(defconst js2-num-tokens (1+ js2-EXPON))
@@ -1656,6 +1657,9 @@ the correct number of ARGS must be provided."
(js2-msg "msg.no.colon.cond"
"missing : in conditional expression")
+(js2-msg "msg.bad.optional.chaining"
+ "missing property name or [ or ( after optional chaining operator")
+
(js2-msg "msg.no.paren.arg"
"missing ) after argument list")
@@ -6074,7 +6078,9 @@ its relevant fields and puts it into `js2-ti-tokens'."
(?,
(throw 'return js2-COMMA))
(??
- (throw 'return js2-HOOK))
+ (if (js2-match-char ?.)
+ (throw 'return js2-OPTIONAL-CHAINING)
+ (throw 'return js2-HOOK)))
(?:
(if (js2-match-char ?:)
js2-COLONCOLON
@@ -10276,6 +10282,24 @@ Returns the list in reverse order. Consumes the
right-paren token."
(setf (js2-node-len pn) (- end beg))) ; end outer if
(js2-parse-member-expr-tail allow-call-syntax pn)))
+(defun js2-parse-optional-chaining-operator (allow-call-syntax pn)
+ (let ((tt (js2-peek-token)))
+ (cond
+ ((eq tt js2-NAME)
+ (setq pn (js2-parse-property-access js2-DOT pn)))
+ ((eq tt js2-LB)
+ ;; skip left bracket token
+ (js2-get-token)
+ (setq pn (js2-parse-element-get pn)))
+ ((and (eq tt js2-LP) allow-call-syntax)
+ ;; unget optional chaining operator
+ ;; so current token is function name and could be highlighted
+ (js2-unget-token)
+ (setq pn (js2-parse-function-call pn t)))
+ (t
+ (js2-report-error "msg.bad.optional.chaining")))
+ pn))
+
(defun js2-parse-member-expr-tail (allow-call-syntax pn)
"Parse a chain of property/array accesses or function calls.
Includes parsing for E4X operators like `..' and `.@'.
@@ -10288,6 +10312,9 @@ Returns an expression tree that includes PN, the parent
node."
(cond
((or (= tt js2-DOT) (= tt js2-DOTDOT))
(setq pn (js2-parse-property-access tt pn)))
+ ((= tt js2-OPTIONAL-CHAINING)
+ (setq pn (js2-parse-optional-chaining-operator allow-call-syntax pn))
+ (unless pn (setq continue nil)))
((= tt js2-DOTQUERY)
(setq pn (js2-parse-dot-query pn)))
((= tt js2-LB)
@@ -10365,11 +10392,14 @@ Last token parsed must be `js2-RB'."
(when (eq (js2-token-type token) js2-NAME)
(js2-record-face 'js2-function-call token)))
-(defun js2-parse-function-call (pn)
+(defun js2-parse-function-call (pn &optional use-optional-chaining-p)
(js2-highlight-function-call (js2-current-token))
(js2-get-token)
(let (args
(pos (js2-node-pos pn)))
+ (when use-optional-chaining-p
+ ;; skip optional chaining operator
+ (js2-get-token))
(setq pn (make-js2-call-node :pos pos
:target pn
:lp (- (js2-current-token-beg) pos)))
diff --git a/tests/parser.el b/tests/parser.el
index 88d3dab..c87fa5f 100644
--- a/tests/parser.el
+++ b/tests/parser.el
@@ -990,6 +990,27 @@ the test."
(js2-deftest-parse exponentiation-prohibits-unary-op
"var a = -b ** c" :syntax-error "-b")
+(js2-deftest optional-chaining-operator-on-property-access
+ "var a = {}; a?.b;"
+ (js2-mode--and-parse)
+ (let ((node (js2-find-node js2-mode-ast 'js2-name-node-p)))
+ (should node)
+ (should (string= (js2-node-text node) "b"))))
+
+(js2-deftest optional-chaining-operator-on-get-element
+ "var a = []; a?.[99];"
+ (js2-mode--and-parse)
+ (let ((node (js2-find-node js2-mode-ast 'js2-number-node-p)))
+ (should node)
+ (should (string= (js2-node-text node) "99"))))
+
+(js2-deftest optional-chaining-operator-on-functioncall
+ "var a = function(b){}; a?.(99);"
+ (js2-mode--and-parse)
+ (let ((node (js2-find-node js2-mode-ast 'js2-number-node-p)))
+ (should node)
+ (should (string= (js2-node-text node) "99"))))
+
(js2-deftest unary-void-node-start
"var c = void 0"
(js2-mode--and-parse)
- [elpa] externals/js2-mode 3a80b00 25/61: use type face for class, (continued)
- [elpa] externals/js2-mode 3a80b00 25/61: use type face for class, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 9837d78 28/61: Fix ‘huge-hex’ test for newer Emacsen., Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 515d876 27/61: Fix parsing static props without semicolons, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 61a8c91 29/61: Merge pull request #550 from phst/huge-hex, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 997d6bd 30/61: Avoid undefined behavior in indentation tests., Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 999c0e7 22/61: Merge pull request #531 from jacksonrayhamilton/jsx-documentation, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 2d2fb4b 21/61: Reference latest revision of the commentary, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 146c1f6 32/61: Migrate off deprecated ‘cl’ library., Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode d642b7b 34/61: Remove an unused variable, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 8841175 23/61: support optional-chaining operator, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode b3841a7 24/61: Merge pull request #533 from redguardtoo/master,
Dmitry Gutov <=
- [elpa] externals/js2-mode 1a5dee9 38/61: Merge pull request #552 from phst/cl, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode a6e1305 41/61: Merge pull request #555 from phst/unused-arg, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 5049e54 43/61: Merge pull request #556 from ArneBab/browser-symbols, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 6b84319 44/61: Remove a few unused variables., Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 56991f7 45/61: Merge pull request #557 from phst/unused, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode fe53814 26/61: Merge pull request #544 from wyuenho/use-type-face-for-class, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode e8bbfd2 31/61: Merge pull request #551 from phst/let, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 710e430 33/61: Migrate remaining files to lexical binding, Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode 124d4a3 35/61: Prefix an unused argument with an underscore., Dmitry Gutov, 2020/12/20
- [elpa] externals/js2-mode c00a562 37/61: Add browser symbols from the jslint setup, Dmitry Gutov, 2020/12/20