(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")
(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))
(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
\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
\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