;;; tests/parser.el --- Some tests for js2-mode.
-;; Copyright (C) 2009, 2011-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2011-2016 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
,@body)
(fundamental-mode)))))
+(defun js2-mode--and-parse ()
+ (js2-mode)
+ (js2-reparse))
+
(defun js2-test-string-to-ast (s)
(insert s)
- (js2-mode)
+ (js2-mode--and-parse)
(should (null js2-mode-buffer-dirty-p))
js2-mode-ast)
(cl-defun js2-test-parse-string (code-string &key syntax-error errors-count
- reference)
+ reference warnings-count)
(ert-with-test-buffer (:name 'origin)
(let ((ast (js2-test-string-to-ast code-string)))
(if syntax-error
(skip-chars-backward " \t\n")
(should (string= (or reference code-string)
(buffer-substring-no-properties
- (point-min) (point)))))))))
+ (point-min) (point)))))
+ (when warnings-count
+ (should (= warnings-count
+ (length (js2-ast-root-warnings ast)))))))))
(cl-defmacro js2-deftest-parse (name code-string &key bind syntax-error errors-count
- reference)
+ reference warnings-count)
"Parse CODE-STRING. If SYNTAX-ERROR is nil, print syntax tree
with `js2-print-tree' and assert the result to be equal to
REFERENCE, if present, or the original string. If SYNTAX-ERROR
(js2-test-parse-string ,code-string
:syntax-error ,syntax-error
:errors-count ,errors-count
+ :warnings-count ,warnings-count
:reference ,reference))))
;;; Basics
(js2-deftest-parse parse-for-of
"for (var a of []) {\n}")
+(js2-deftest-parse of-can-be-name
+ "void of;")
+
+(js2-deftest-parse of-can-be-object-name
+ "of.z;")
+
(js2-deftest-parse of-can-be-var-name
"var of = 3;")
;;; Destructuring binding
(js2-deftest-parse destruct-in-declaration
- "var {a, b} = {a: 1, b: 2};")
+ "var {a, b} = {a: 1, b: 2};"
+ :warnings-count 0)
(js2-deftest-parse destruct-in-arguments
- "function f({a: aa, b: bb}) {\n}")
+ "function f({a: aa, b: bb}) {\n}"
+ :warnings-count 0)
(js2-deftest-parse destruct-in-array-comp-loop
"[a + b for ([a, b] in [[0, 1], [1, 2]])];")
(js2-deftest-parse destruct-in-catch-clause
- "try {\n} catch ({a, b}) {\n a + b;\n}")
+ "try {\n} catch ({a, b}) {\n a + b;\n}"
+ :warnings-count 0)
(js2-deftest-parse destruct-with-initializer-in-object
- "var {a, b = 2, c} = {};")
+ "var {a, b = 2, c} = {};\nb;"
+ :warnings-count 0)
(js2-deftest-parse destruct-with-initializer-in-array
- "var [a, b = 2, c] = [];")
+ "var [a, b = 2, c] = [];\nb;"
+ :warnings-count 0)
(js2-deftest-parse destruct-non-name-target-is-error
"var {1=1} = {};" :syntax-error "1" :errors-count 1)
"\"use strict\";\nvar {a=1,a=2} = {};" :syntax-error "a" :errors-count 1)
(js2-deftest destruct-name-conflict-is-warning-in-array "\"use strict\";\nvar [a=1,a=2] = [];"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal '("msg.var.redecl" "a")
(caar js2-parsed-warnings))))
(js2-deftest initializer-outside-destruct-is-error "({a=1});"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal "msg.init.no.destruct"
(car (caar js2-parsed-errors)))))
"var x = {f(y) { return y;\n}};")
(js2-deftest object-literal-method-own-name-in-scope "({f(){f();}});"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal '("msg.undeclared.variable" "f")
(caar js2-parsed-warnings))))
"var x = {get [foo + bar]() { return 42;\n}};")
(js2-deftest-parse object-literal-generator
- "var x = {*foo() { yield 42;\n}};")
+ "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() {};"
- (js2-mode)
+ (js2-mode--and-parse)
(should (= (length (js2-ast-root-warnings js2-mode-ast)) 1)))
(js2-deftest function-expression-var-same-name "var gen = function gen() {};"
- (js2-mode)
+ (js2-mode--and-parse)
(should (null (js2-ast-root-warnings js2-mode-ast))))
;;; Function parameters
(js2-deftest-parse spread-in-function-call
"f(3, ...[t(2), t(3)], 42, ...[t(4)]);")
+(js2-deftest-parse rest-in-array-destructure
+ "let [x, y, z, ...w] = [1, ...a, ...b, c];")
+
+(js2-deftest-parse comma-after-rest-in-array
+ "let [...x,] = [1, 2, 3];"
+ :syntax-error "," :errors-count 1)
+
+(js2-deftest-parse elem-after-rest-in-array
+ "let [...x, y] = [1, 2, 3];"
+ :syntax-error "," :errors-count 2)
+
+(js2-deftest-parse array-destructure-expr-default
+ "let [[x] = [3]] = y;")
+
+(js2-deftest-parse spread-in-object-literal
+ "f({x, y, ...z});")
+
+(js2-deftest-parse rest-in-object-literal
+ "const {x, y, ...z} = f();")
+
;;; Arrow functions
(js2-deftest-parse arrow-function-with-empty-args-and-no-curlies
(js2-deftest no-label-node-inside-expr "x = y:"
(let (js2-parse-interruptable-p)
- (js2-mode))
+ (js2-mode--and-parse))
(let ((assignment (js2-expr-stmt-node-expr (car (js2-scope-kids js2-mode-ast)))))
(should (js2-name-node-p (js2-assign-node-right assignment)))))
(js2-deftest-parse async-can-be-function-name
"function async() {\n}")
+(js2-deftest-parse await-can-be-name
+ "void await;")
+
+(js2-deftest-parse await-can-be-object-name
+ "await.z;")
+
(js2-deftest-parse await-can-be-var-name
"var await = 3;")
(should (js2-export-node-default export-node))))
(js2-deftest export-function-no-semicolon "export default function foo() {}"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal nil js2-parsed-warnings)))
(js2-deftest export-default-function-no-semicolon "export function foo() {}"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal nil js2-parsed-warnings)))
(js2-deftest export-anything-else-does-require-a-semicolon "export var obj = {}"
- (js2-mode)
+ (js2-mode--and-parse)
(should (not (equal nil js2-parsed-warnings))))
(js2-deftest export-default-async-function-no-semicolon "export default async function foo() {}"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal nil js2-parsed-warnings)))
(js2-deftest export-async-function-no-semicolon "export async function foo() {}"
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal nil js2-parsed-warnings)))
(js2-deftest-parse parse-export-rexport "export * from 'other/lib';")
;;; Scopes
(js2-deftest ast-symbol-table-includes-fn-node "function foo() {}"
- (js2-mode)
+ (js2-mode--and-parse)
(let ((entry (js2-scope-get-symbol js2-mode-ast 'foo)))
(should (= (js2-symbol-decl-type entry) js2-FUNCTION))
(should (equal (js2-symbol-name entry) "foo"))
function bar() {}
var x;
}"
- (js2-mode)
+ (js2-mode--and-parse)
(let* ((scope (js2-node-at-point (point-min)))
(fn-entry (js2-scope-get-symbol scope 'bar))
(var-entry (js2-scope-get-symbol scope 'x)))
(should (funcall predicate (js2-get-defining-scope scope variable)))))
(js2-deftest for-node-is-declaration-scope "for (let i = 0; i; ++i) {};"
- (js2-mode)
+ (js2-mode--and-parse)
(js2-test-scope-of-nth-variable-satisifies-predicate "i" 0 #'js2-for-node-p))
-(js2-deftest const-scope-sloppy-script "{const a;} a;"
- (js2-mode)
- (js2-test-scope-of-nth-variable-satisifies-predicate "a" 0 #'js2-script-node-p)
- (js2-test-scope-of-nth-variable-satisifies-predicate "a" 1 #'js2-script-node-p))
-
-(js2-deftest const-scope-strict-script "'use strict'; { const a; } a;"
- (js2-mode)
+(js2-deftest const-scope-inside-script "{ const a; } a;"
+ (js2-mode--and-parse)
(js2-test-scope-of-nth-variable-satisifies-predicate "a" 0 #'js2-block-node-p)
(js2-test-scope-of-nth-variable-satisifies-predicate "a" 1 #'null))
-(js2-deftest const-scope-sloppy-function "function f() { { const a; } a; }"
- (js2-mode)
- (js2-test-scope-of-nth-variable-satisifies-predicate "a" 0 #'js2-function-node-p)
- (js2-test-scope-of-nth-variable-satisifies-predicate "a" 1 #'js2-function-node-p))
-
-(js2-deftest const-scope-strict-function "function f() { 'use strict'; { const a; } a; }"
- (js2-mode)
+(js2-deftest const-scope-inside-function "function f() { { const a; } a; }"
+ (js2-mode--and-parse)
(js2-test-scope-of-nth-variable-satisifies-predicate "a" 0 #'js2-block-node-p)
(js2-test-scope-of-nth-variable-satisifies-predicate "a" 1 #'null))
(js2-deftest array-comp-is-result-scope "[x * 2 for (x in y)];"
- (js2-mode)
+ (js2-mode--and-parse)
(js2-test-scope-of-nth-variable-satisifies-predicate "x" 0 #'js2-comp-loop-node-p))
(js2-deftest array-comp-has-parent-scope
"var a,b=[for (i of [[1,2]]) for (j of i) j * a];"
- (js2-mode)
+ (js2-mode--and-parse)
(search-forward "for")
(forward-char -3)
(let ((node (js2-node-at-point)))
;;; Error handling
(js2-deftest for-node-with-error-len "for "
- (js2-mode)
+ (js2-mode--and-parse)
(let ((node (js2-node-at-point (point-min))))
(should (= (js2-node-len (js2-node-parent node)) 4))))
(js2-deftest function-without-parens-error "function b {}"
;; Should finish the parse.
- (js2-mode))
+ (js2-mode--and-parse))
;;; Comments
(js2-deftest comment-node-length "//"
- (js2-mode)
+ (js2-mode--and-parse)
(let ((node (js2-node-at-point (point-min))))
(should (= (js2-node-len node) 2))))
(js2-deftest comment-node-length-newline "//\n"
- (js2-mode)
+ (js2-mode--and-parse)
(let ((node (js2-node-at-point (point-min))))
(should (= (js2-node-len node) 3))))
(insert ,buffer-contents))
(unwind-protect
(progn
- (js2-mode)
+ (js2-mode--and-parse)
(should (equal ,summary (js2--variables-summary
(js2--classify-variables)))))
(fundamental-mode)))))