]> code.delx.au - gnu-emacs-elpa/commitdiff
Parse default parameters
authorDmitry Gutov <dgutov@yandex.ru>
Sun, 17 Jun 2012 06:16:14 +0000 (10:16 +0400)
committerDmitry Gutov <dgutov@yandex.ru>
Sun, 17 Jun 2012 07:42:12 +0000 (11:42 +0400)
Closes #50

js2-mode.el
tests/ast.el

index 215af348ef50c64ebc0cccd281ad9ec93b3a79c0..1a94fd479494d0eb686fbb71569465b1dcabb858 100644 (file)
@@ -1562,6 +1562,9 @@ the correct number of ARGS must be provided."
 (js2-msg "msg.no.paren.after.parms"
          "missing ) after formal parameters")
 
+(js2-msg "msg.no.default.after.default.param" ; added by js2-mode
+         "parameter without default follows parameter with default")
+
 (js2-msg "msg.no.brace.body"
          "missing '{' before function body")
 
@@ -7466,23 +7469,44 @@ NODE is either `js2-array-node', `js2-object-node', or `js2-name-node'."
 (defun js2-parse-function-params (fn-node pos)
   (if (js2-match-token js2-RP)
       (setf (js2-function-node-rp fn-node) (- js2-token-beg pos))
-    (let (params len param)
+    (let (params len param default-found)
       (loop for tt = (js2-peek-token)
             do
             (cond
              ;; destructuring param
              ((or (= tt js2-LB) (= tt js2-LC))
+              (when default-found
+                (js2-report-error "msg.no.default.after.default.param"))
               (setq param (js2-parse-destruct-primary-expr))
               (js2-define-destruct-symbols param
                                            js2-LP
                                            'js2-function-param-face)
               (push param params))
-             ;; simple name
+             ;; variable name
              (t
               (js2-must-match js2-NAME "msg.no.parm")
               (js2-record-face 'js2-function-param-face)
               (setq param (js2-create-name-node))
               (js2-define-symbol js2-LP js2-ts-string param)
+              ;; default parameter value
+              (when (or (and default-found
+                             (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)))
+                (let* ((pos (js2-node-pos param))
+                       (tt js2-current-token)
+                       (op-pos (- js2-token-beg pos))
+                       (left param)
+                       (right (js2-parse-assign-expr))
+                       (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)
+                  (js2-node-add-children param left right)))
               (push param params)))
             while
             (js2-match-token js2-COMMA))
index 7644aea9241e749afa353ab6486b6a5fddd4b97e..b67960d874536dce79b6ec9b58acfc80e9582948 100644 (file)
@@ -9,21 +9,29 @@
     (should (null js2-mode-buffer-dirty-p))\r
     js2-mode-ast))\r
 \r
-(defun js2-test-ast-string (code-string)\r
+(defun js2-test-ast-string (code-string &key syntax-error)\r
   (let ((ast (js2-test-string-to-ast code-string)))\r
-    (ert-with-test-buffer (:name 'copy)\r
-      (js2-print-tree ast)\r
-      (skip-chars-backward " \t\n")\r
-      (should (string= code-string (buffer-substring-no-properties\r
-                                    (point-min) (point)))))))\r
-\r
-(defmacro js2-deftest-ast (name code-string &optional bindings)\r
-  "Parse CODE-STRING, print it out with `js2-print-tree', and\r
-assert the result to be equal to the original string.\r
-When BINDINGS are specified, apply them around the test."\r
+    (if syntax-error\r
+        (let ((errors (js2-ast-root-errors ast)))\r
+          (should (= 1 (length errors)))\r
+          (destructuring-bind (_ pos len) (first errors)\r
+            (should (string= syntax-error (substring code-string\r
+                                                     (1- pos) (+ pos len -1))))))\r
+      (ert-with-test-buffer (:name 'copy)\r
+        (js2-print-tree ast)\r
+        (skip-chars-backward " \t\n")\r
+        (should (string= code-string (buffer-substring-no-properties\r
+                                      (point-min) (point))))))))\r
+\r
+(defmacro* js2-deftest-ast (name code-string &key bind syntax-error)\r
+  "Parse CODE-STRING.  If SYNTAX-ERROR is nil, print syntax tree\r
+with `js2-print-tree' and assert the result to be equal to the\r
+original string.  If SYNTAX-ERROR is passed, expect syntax error\r
+highlighting substring equal to SYNTAX-ERROR value.\r
+BIND defines bindings to apply them around the test."\r
   `(ert-deftest ,name ()\r
-     (let ,(append bindings '((js2-basic-offset 2)))\r
-       (js2-test-ast-string ,code-string))))\r
+     (let ,(append bind '((js2-basic-offset 2)))\r
+       (js2-test-ast-string ,code-string :syntax-error ,syntax-error))))\r
 \r
 (put 'js2-deftest-ast 'lisp-indent-function 'defun)\r
 \r
@@ -34,19 +42,19 @@ When BINDINGS are specified, apply them around the test."
 \r
 (js2-deftest-ast parse-property-access-when-keyword\r
   "A.in = 3;"\r
-  ((js2-allow-keywords-as-property-names t)))\r
+  :bind ((js2-allow-keywords-as-property-names t)))\r
 \r
 (js2-deftest-ast parse-property-access-when-keyword-no-xml\r
   "A.in = 3;"\r
-  ((js2-allow-keywords-as-property-names t)\r
-   (js2-compiler-xml-available nil)))\r
+  :bind ((js2-allow-keywords-as-property-names t)\r
+         (js2-compiler-xml-available nil)))\r
 \r
 (js2-deftest-ast parse-array-literal-when-not-keyword\r
   "a = {b: 1};")\r
 \r
 (js2-deftest-ast parse-array-literal-when-keyword\r
   "a = {in: 1};"\r
-  ((js2-allow-keywords-as-property-names t)))\r
+  :bind ((js2-allow-keywords-as-property-names t)))\r
 \r
 ;;; 'of' contextual keyword.\r
 \r
@@ -75,3 +83,16 @@ When BINDINGS are specified, apply them around the test."
 \r
 (js2-deftest-ast destruct-in-catch-clause\r
   "try {\n} catch ({a, b}) {\n  return a + b;\n}")\r
+\r
+;;; Function arguments.\r
+\r
+(js2-deftest-ast function-with-default-parameters\r
+  "function foo(a = 1, b = a + 1) {\n}")\r
+\r
+(js2-deftest-ast function-with-no-default-after-default\r
+  "function foo(a = 1, b) {\n}"\r
+  :syntax-error "b")\r
+\r
+(js2-deftest-ast function-with-destruct-after-default\r
+  "function foo(a = 1, {b, c}) {\n}"\r
+  :syntax-error "{")\r