]> code.delx.au - gnu-emacs-elpa/commitdiff
Support parsing the ES6 'super' keyword.
authorStephen Hicks <sdh@google.com>
Tue, 11 Nov 2014 02:05:31 +0000 (18:05 -0800)
committerStephen Hicks <sdh@google.com>
Sat, 15 Nov 2014 09:02:32 +0000 (01:02 -0800)
This is basically implemented by imitating the handling of 'this', since they behave in very similar ways.  The keyword is defined in the various productions in ยง12.3 of the draft ES6 spec: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-left-hand-side-expressions, and usage examples are available at e.g. https://github.com/lukehoban/es6features#classes.

js2-mode.el
tests/parser.el

index 769abeda75f5af31f0828c505b2354aafa429a66..c340ba377b9417f7f7731ee700bae7e013e73b25 100644 (file)
@@ -664,8 +664,9 @@ which doesn't seem particularly useful, but Rhino permits it."
 (defvar js2-CLASS 164)
 (defvar js2-EXTENDS 165)
 (defvar js2-STATIC 166)
+(defvar js2-SUPER 167)
 
-(defconst js2-num-tokens (1+ js2-STATIC))
+(defconst js2-num-tokens (1+ js2-SUPER))
 
 (defconst js2-debug-print-trees nil)
 
@@ -3354,15 +3355,17 @@ The node type is set to js2-NULL, js2-THIS, etc.")
           (let ((tt (js2-node-type n)))
             (cond
              ((= tt js2-THIS) "this")
+             ((= tt js2-SUPER) "super")
              ((= tt js2-NULL) "null")
              ((= tt js2-TRUE) "true")
              ((= tt js2-FALSE) "false")
              ((= tt js2-DEBUGGER) "debugger")
              (t (error "Invalid keyword literal type: %d" tt))))))
 
-(defsubst js2-this-node-p (node)
-  "Return t if NODE is a `js2-literal-node' of type js2-THIS."
-  (eq (js2-node-type node) js2-THIS))
+(defsubst js2-this-or-super-node-p (node)
+  "Return t if NODE is a `js2-literal-node' of type js2-THIS or js2-SUPER."
+  (let ((type (js2-node-type node)))
+    (or (eq type js2-THIS) (eq type js2-SUPER))))
 
 (defstruct (js2-new-node
             (:include js2-node)
@@ -5356,7 +5359,7 @@ into temp buffers."
     let
     new null
     return
-    static switch
+    static super switch
     this throw true try typeof
     var void
     while with
@@ -5376,7 +5379,7 @@ into temp buffers."
                js2-LET
                js2-NEW js2-NULL
                js2-RETURN
-               js2-STATIC js2-SWITCH
+               js2-STATIC js2-SUPER js2-SWITCH
                js2-THIS js2-THROW js2-TRUE js2-TRY js2-TYPEOF
                js2-VAR
                js2-WHILE js2-WITH
@@ -5387,6 +5390,7 @@ into temp buffers."
     (aset table js2-REGEXP 'font-lock-string-face)
     (aset table js2-COMMENT 'font-lock-comment-face)
     (aset table js2-THIS 'font-lock-builtin-face)
+    (aset table js2-SUPER 'font-lock-builtin-face)
     (aset table js2-VOID 'font-lock-constant-face)
     (aset table js2-NULL 'font-lock-constant-face)
     (aset table js2-TRUE 'font-lock-constant-face)
@@ -6811,8 +6815,10 @@ returns nil.  Otherwise returns the string name/value of the node."
    ((and (js2-number-node-p node)
          (string-match "^[0-9]+$" (js2-number-node-value node)))
     (js2-number-node-value node))
-   ((js2-this-node-p node)
-    "this")))
+   ((eq (js2-node-type node) js2-THIS)
+    "this")
+   ((eq (js2-node-type node) js2-SUPER)
+    "super")))
 
 (defun js2-node-qname-component (node)
   "Return the name of this node, if it contributes to a qname.
@@ -6870,7 +6876,7 @@ as property-gets if the index expression is a string, or a positive integer."
   (let (left right head)
     (cond
      ((or (js2-name-node-p node)
-          (js2-this-node-p node))
+          (js2-this-or-super-node-p node))
       (list node))
      ;; foo.bar.baz is parenthesized as (foo.bar).baz => right operand is a leaf
      ((js2-prop-get-node-p node)        ; foo.bar
@@ -6923,7 +6929,7 @@ that it's an external variable, which must also be in the top-level scope."
          (this-scope (js2-node-get-enclosing-scope node))
          defining-scope)
     (cond
-     ((js2-this-node-p node)
+     ((js2-this-or-super-node-p node)
       nil)
      ((null this-scope)
       t)
@@ -6959,7 +6965,7 @@ For instance, processing a nested scope requires a parent function node."
         ;; Pre-processed chain, or top-level/external, keep as-is.
         (if (or (stringp head) (js2-node-top-level-decl-p head))
             (push chain result)
-          (when (js2-this-node-p head)
+          (when (js2-this-or-super-node-p head)
             (setq chain (cdr chain))) ; discard this-node
           (when (setq fn (js2-node-parent-script-or-fn current-fn))
             (setq parent-qname (gethash fn js2-imenu-function-map 'not-found))
@@ -9344,6 +9350,7 @@ array-literals, array comprehensions and regular expressions."
           (js2-record-text-property px-pos end 'syntax-table '(2)))))
      ((or (= tt js2-NULL)
           (= tt js2-THIS)
+          (= tt js2-SUPER)
           (= tt js2-FALSE)
           (= tt js2-TRUE))
       (make-js2-keyword-node :type tt))
index 10b0c1322dc9d40865b13b59404b3b5be379693e..8d2cf706182bd4d020ec5a1f55e8e79c5f6efbe8 100644 (file)
@@ -367,6 +367,9 @@ the test."
   "class Foo {\n  get bar() {  return 42;\n}"
   :syntax-error "}")
 
+(js2-deftest-parse parse-super-keyword
+  "class Foo {\n  constructor() {  super(42);\n}\n  foo() {  super.foo();\n}\n}")
+
 ;;; Scopes
 
 (js2-deftest ast-symbol-table-includes-fn-node "function foo() {}"