[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master c13eda4 01/33: Generalize object literal parsing to suppor
From: |
Dmitry Gutov |
Subject: |
[elpa] master c13eda4 01/33: Generalize object literal parsing to support short-hand function/generator/getter/setter declarations with all kinds of keys (string, named, computed, numeric). |
Date: |
Sun, 12 Jul 2015 22:35:33 +0000 |
branch: master
commit c13eda48a6fa3af690cf36d799dc813de61f198a
Author: Stephen Hicks <address@hidden>
Commit: Stephen Hicks <address@hidden>
Generalize object literal parsing to support short-hand
function/generator/getter/setter declarations with all kinds of keys (string,
named, computed, numeric).
Previously only a subset of combinations were supported, but appear to be
allowed by the spec.
---
js2-mode.el | 123 ++++++++++++++++++++++++++++++++++---------------------
tests/parser.el | 12 +++++
2 files changed, 88 insertions(+), 47 deletions(-)
diff --git a/js2-mode.el b/js2-mode.el
index 2dd5d9d..54f9c19 100644
--- a/js2-mode.el
+++ b/js2-mode.el
@@ -3952,6 +3952,7 @@ and both fields have the same value.")
(defun js2-print-object-prop-node (n i)
(let* ((left (js2-object-prop-node-left n))
+ (right (js2-object-prop-node-right n))
(computed (not (or (js2-string-node-p left)
(js2-number-node-p left)
(js2-name-node-p left)))))
@@ -3964,7 +3965,7 @@ and both fields have the same value.")
(if (not (js2-node-get-prop n 'SHORTHAND))
(progn
(insert ": ")
- (js2-print-ast (js2-object-prop-node-right n) 0)))))
+ (js2-print-ast right 0)))))
(cl-defstruct (js2-getter-setter-node
(:include js2-infix-node)
@@ -3981,13 +3982,23 @@ property `GETTER_SETTER' set to js2-GET, js2-SET, or
js2-FUNCTION. ")
(put 'cl-struct-js2-getter-setter-node 'js2-printer 'js2-print-getter-setter)
(defun js2-print-getter-setter (n i)
- (let ((pad (js2-make-pad i))
- (left (js2-getter-setter-node-left n))
- (right (js2-getter-setter-node-right n)))
+ (let* ((pad (js2-make-pad i))
+ (left (js2-getter-setter-node-left n))
+ (right (js2-getter-setter-node-right n))
+ (computed (not (or (js2-string-node-p left)
+ (js2-number-node-p left)
+ (js2-name-node-p left)))))
(insert pad)
(if (/= (js2-node-type n) js2-FUNCTION)
(insert (if (= (js2-node-type n) js2-GET) "get " "set ")))
+ (when (and (js2-function-node-p right)
+ (eq 'STAR (js2-function-node-generator-type right)))
+ (insert "*"))
+ (when computed
+ (insert "["))
(js2-print-ast left 0)
+ (when computed
+ (insert "]"))
(js2-print-ast right 0)))
(cl-defstruct (js2-prop-get-node
@@ -10344,38 +10355,41 @@ If ONLY-OF-P is non-nil, only the 'for (foo of bar)'
form is allowed."
(let ((pos (js2-current-token-beg))
(static nil)
(continue t)
- tt elems elem after-comma)
+ tt elems elem after-comma previous-token)
(while continue
(setq tt (js2-get-prop-name-token)
static nil
- elem nil)
+ elem nil
+ previous-token nil)
+ ;; Handle 'static' keyword only if we're in a class
(when (and class-p (= js2-NAME tt)
(string= "static" (js2-current-token-string)))
(js2-record-face 'font-lock-keyword-face)
(setq static t
tt (js2-get-prop-name-token)))
+ ;; Handle generator * before the property name for in-line functions
+ (when (and (>= js2-language-version 200)
+ (= js2-MUL tt))
+ (setq previous-token (js2-current-token)
+ tt (js2-get-prop-name-token)))
+ ;; Handle 'get' or 'set' keywords
+ (let ((prop (js2-current-token-string)))
+ (when (and (>= js2-language-version 200)
+ (= js2-NAME tt)
+ (or (string= prop "get")
+ (string= prop "set"))
+ (member (js2-peek-token)
+ (list js2-NAME js2-STRING js2-NUMBER js2-LB)))
+ (setq previous-token (js2-current-token)
+ tt (js2-get-prop-name-token))))
(cond
- ;; {foo: ...}, {'foo': ...}, {foo, bar, ...},
- ;; {get foo() {...}}, {set foo(x) {...}}, or {foo(x) {...}}
- ;; TODO(sdh): support *foo() {...}
- ((or (= js2-NAME tt)
- (= tt js2-STRING))
+ ;; Found a 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))
+ elem (js2-parse-named-prop tt pos previous-token))
(if (and (null elem)
(not js2-recover-from-parse-errors))
(setq continue nil)))
- ;; {[Symbol.iterator]: ...}
- ((and (= tt js2-LB)
- (>= js2-language-version 200))
- (let ((expr (js2-parse-expr)))
- (js2-must-match js2-RB "msg.missing.computed.rb")
- (setq after-comma nil
- elem (js2-parse-plain-property expr))))
- ;; {12: x} or {10.7: x}
- ((= tt js2-NUMBER)
- (setq after-comma nil
- elem (js2-parse-plain-property (make-js2-number-node))))
;; Break out of loop, and handle trailing commas.
((or (= tt js2-RC)
(= tt js2-EOF))
@@ -10405,42 +10419,55 @@ If ONLY-OF-P is non-nil, only the 'for (foo of bar)'
form is allowed."
(js2-must-match js2-RC "msg.no.brace.prop")
(nreverse elems)))
-(defun js2-parse-named-prop (tt)
+(defun js2-parse-named-prop (tt pos previous-token)
"Parse a name, string, or getter/setter object property.
When `js2-is-in-destructuring' is t, forms like {a, b, c} will be permitted."
- (let ((string-prop (and (= tt js2-STRING)
- (make-js2-string-node)))
+ (let ((key (cond
+ ;; Literal string keys: {'foo': 'bar'}
+ ((= tt js2-STRING)
+ (make-js2-string-node))
+ ;; Handle computed keys: {[Symbol.iterator]: ...}, *[1+2]()
{...}},
+ ;; {[foo + bar]() { ... }}, {[get ['x' + 1]() {...}}
+ ((and (= tt js2-LB)
+ (>= js2-language-version 200))
+ (prog1 (js2-parse-expr)
+ (js2-must-match js2-RB "msg.missing.computed.rb")))
+ ;; Numeric keys: {12: 'foo'}, {10.7: 'bar'}
+ ((= tt js2-NUMBER)
+ (make-js2-number-node))
+ ;; Unquoted names: {foo: 12}
+ ((= tt js2-NAME)
+ (js2-create-name-node))
+ ;; Anything else is an error
+ (t (js2-report-error "msg.bad.prop"))))
expr
- (ppos (js2-current-token-beg))
- (pend (js2-current-token-end))
- (name (js2-create-name-node))
- (prop (js2-current-token-string)))
+ (prop (and previous-token (js2-token-string previous-token)))
+ (property-type (when previous-token
+ (if (= (js2-token-type previous-token) js2-MUL)
+ "*"
+ (js2-token-string previous-token)))))
+ (when (or (string= prop "get")
+ (string= prop "set"))
+ (js2-set-face (js2-token-beg previous-token)
+ (js2-token-end previous-token)
+ 'font-lock-keyword-face 'record)) ; get/set
(cond
- ;; getter/setter prop
- ((and (= tt js2-NAME)
- (= (js2-peek-token) js2-NAME)
- (or (string= prop "get")
- (string= prop "set")))
- (js2-get-token)
- (js2-set-face ppos pend 'font-lock-keyword-face 'record) ; get/set
- (js2-record-face 'font-lock-function-name-face) ; for peeked name
- (setq name (js2-create-name-node)) ; discard get/set & use peeked name
- (js2-parse-getter-setter-prop ppos name prop))
;; method definition: {f() {...}}
((and (= (js2-peek-token) js2-LP)
(>= js2-language-version 200))
- (js2-record-face 'font-lock-function-name-face) ; name
- (js2-parse-getter-setter-prop ppos name ""))
+ (when (js2-name-node-p key) ; highlight function name properties
+ (js2-record-face 'font-lock-function-name-face))
+ (js2-parse-getter-setter-prop pos key property-type))
;; regular prop
(t
(prog1
- (setq expr (js2-parse-plain-property (or string-prop name)))
- (when (and (not string-prop)
+ (setq expr (js2-parse-plain-property key))
+ (when (and (= tt js2-NAME)
(not js2-is-in-destructuring)
js2-highlight-external-variables
(js2-node-get-prop expr 'SHORTHAND))
- (js2-record-name-node name))
- (js2-set-face ppos pend
+ (js2-record-name-node key))
+ (js2-set-face (js2-current-token-beg) (js2-current-token-end)
(if (js2-function-node-p
(js2-object-prop-node-right expr))
'font-lock-function-name-face
@@ -10499,7 +10526,7 @@ and expression closure style is also supported
POS is the start position of the `get' or `set' keyword.
PROP is the `js2-name-node' representing the property name.
-GET-P is non-nil if the keyword was `get'."
+TYPE-STRING is a string `get', `set', `*', or nil, indicating a found keyword."
(let ((type (cond
((string= "get" type-string) js2-GET)
((string= "set" type-string) js2-SET)
@@ -10512,6 +10539,8 @@ GET-P is non-nil if the keyword was `get'."
(if (cl-plusp (length (js2-function-name fn)))
(js2-report-error "msg.bad.prop")))
(js2-node-set-prop fn 'GETTER_SETTER type) ; for codegen
+ (when (string= type-string "*")
+ (setf (js2-function-node-generator-type fn) 'STAR))
(setq end (js2-node-end fn)
result (make-js2-getter-setter-node :type type
:pos pos
diff --git a/tests/parser.el b/tests/parser.el
index 0dd1502..6050a8f 100644
--- a/tests/parser.el
+++ b/tests/parser.el
@@ -198,6 +198,18 @@ the test."
(js2-deftest-parse object-literal-computed-keys
"var x = {[Symbol.iterator]: function() {}};")
+(js2-deftest-parse object-literal-computed-function-keys
+ "var x = {[foo + bar](y) { return y;\n}};")
+
+(js2-deftest-parse object-literal-computed-getter-key
+ "var x = {get [foo + bar]() { return 42;\n}};")
+
+(js2-deftest-parse object-literal-generator
+ "var x = {*foo() { yield 42;\n}};")
+
+(js2-deftest-parse object-literal-computed-generator-key
+ "var x = {*[foo + bar]() { yield 42;\n}};")
+
;;; Function definition
(js2-deftest function-redeclaring-var "var gen = 3; function gen() {};"
- [elpa] master updated (af721ab -> 2763c9a), Dmitry Gutov, 2015/07/12
- [elpa] master 6d4aa28 03/33: Don't unset `js2-recorded-identifiers', Dmitry Gutov, 2015/07/12
- [elpa] master 709ff60 05/33: Add a NEWS entry for d4d9c54, Dmitry Gutov, 2015/07/12
- [elpa] master a632b02 04/33: Merge pull request #232 from jacksonrayhamilton/unset-identifiers, Dmitry Gutov, 2015/07/12
- [elpa] master d6e6cd6 06/33: Fix object keys highlighting (closes #234), Dmitry Gutov, 2015/07/12
- [elpa] master 422be2d 08/33: Add NEWS entry, Dmitry Gutov, 2015/07/12
- [elpa] master c13eda4 01/33: Generalize object literal parsing to support short-hand function/generator/getter/setter declarations with all kinds of keys (string, named, computed, numeric).,
Dmitry Gutov <=
- [elpa] master 09a86b2 09/33: js2-node-externs: Add querystring, Dmitry Gutov, 2015/07/12
- [elpa] master 7c423dd 10/33: Define const variables in the current block., Dmitry Gutov, 2015/07/12
- [elpa] master d39764f 02/33: Merge pull request #231 from shicks/computed, Dmitry Gutov, 2015/07/12
- [elpa] master 88d7565 11/33: Respect strict mode., Dmitry Gutov, 2015/07/12
- [elpa] master a5b586f 13/33: Test const scoping., Dmitry Gutov, 2015/07/12
- [elpa] master 254c78c 07/33: Highlight unused and/or uninitialized variables, Dmitry Gutov, 2015/07/12
- [elpa] master 1277c7d 12/33: Track script and function strict mode., Dmitry Gutov, 2015/07/12
- [elpa] master 498bcca 21/33: Fix refactoring regression., Dmitry Gutov, 2015/07/12
- [elpa] master 663efb1 24/33: Remove strict mode slots on nodes., Dmitry Gutov, 2015/07/12
- [elpa] master 6255edb 18/33: Cleanup, Dmitry Gutov, 2015/07/12