]> code.delx.au - gnu-emacs-elpa/blobdiff - js2-mode.el
Remove js2-current-indent
[gnu-emacs-elpa] / js2-mode.el
index e667df00767e4be047f9804b6146e9ef0a806b79..348b0d1e853e0f99c0b6cc434ff8f5d090fba118 100644 (file)
@@ -2465,12 +2465,11 @@ NAME can be a Lisp symbol or string.  SYMBOL is a `js2-symbol'."
                                                      len
                                                      buffer)))
   "The root node of a js2 AST."
-  buffer             ; the source buffer from which the code was parsed
-  comments           ; a Lisp list of comments, ordered by start position
-  errors             ; a Lisp list of errors found during parsing
-  warnings           ; a Lisp list of warnings found during parsing
-  node-count         ; number of nodes in the tree, including the root
-  in-strict-mode)    ; t if the script is running under strict mode
+  buffer         ; the source buffer from which the code was parsed
+  comments       ; a Lisp list of comments, ordered by start position
+  errors         ; a Lisp list of errors found during parsing
+  warnings       ; a Lisp list of warnings found during parsing
+  node-count)    ; number of nodes in the tree, including the root
 
 (put 'cl-struct-js2-ast-root 'js2-visitor 'js2-visit-ast-root)
 (put 'cl-struct-js2-ast-root 'js2-printer 'js2-print-script)
@@ -3347,8 +3346,7 @@ The `params' field is a Lisp list of nodes.  Each node is either a simple
   ignore-dynamic   ; ignore value of the dynamic-scope flag (interpreter only)
   needs-activation ; t if we need an activation object for this frame
   generator-type   ; STAR, LEGACY, COMPREHENSION or nil
-  member-expr      ; nonstandard Ecma extension from Rhino
-  in-strict-mode)  ; t if the function is running under strict mode
+  member-expr)     ; nonstandard Ecma extension from Rhino
 
 (put 'cl-struct-js2-function-node 'js2-visitor 'js2-visit-function-node)
 (put 'cl-struct-js2-function-node 'js2-printer 'js2-print-function-node)
@@ -7959,7 +7957,7 @@ Scanner should be initialized."
         (end js2-ts-cursor)  ; in case file is empty
         root n tt
         (in-directive-prologue t)
-        (saved-strict-mode js2-in-use-strict-directive)
+        (js2-in-use-strict-directive js2-in-use-strict-directive)
         directive)
     ;; initialize buffer-local parsing vars
     (setf root (make-js2-ast-root :buffer (buffer-name) :pos pos)
@@ -7984,12 +7982,10 @@ Scanner should be initialized."
            ((null directive)
             (setq in-directive-prologue nil))
            ((string= directive "use strict")
-            (setq js2-in-use-strict-directive t)
-            (setf (js2-ast-root-in-strict-mode root) t)))))
+            (setq js2-in-use-strict-directive t)))))
       ;; add function or statement to script
       (setq end (js2-node-end n))
       (js2-block-node-push root n))
-    (setq js2-in-use-strict-directive saved-strict-mode)
     ;; add comments to root in lexical order
     (when js2-scanned-comments
       ;; if we find a comment beyond end of normal kids, use its end
@@ -8026,11 +8022,8 @@ Scanner should be initialized."
         tt
         end
         not-in-directive-prologue
-        (saved-strict-mode js2-in-use-strict-directive)
         node
         directive)
-    ;; Inherit strict mode.
-    (setf (js2-function-node-in-strict-mode fn-node) js2-in-use-strict-directive)
     (cl-incf js2-nesting-of-function)
     (unwind-protect
         (while (not (or (= (setq tt (js2-peek-token)) js2-ERROR)
@@ -8047,13 +8040,15 @@ Scanner should be initialized."
                   ((null directive)
                    (setq not-in-directive-prologue t))
                   ((string= directive "use strict")
-                   (setq js2-in-use-strict-directive t)
-                   (setf (js2-function-node-in-strict-mode fn-node) t)))
+                   ;; Back up and reparse the function, because new rules apply
+                   ;; to the function name and parameters.
+                   (when (not js2-in-use-strict-directive)
+                     (setq js2-in-use-strict-directive t)
+                     (throw 'reparse t))))
                  node)
              (js2-get-token)
              (js2-parse-function-stmt))))
-      (cl-decf js2-nesting-of-function)
-      (setq js2-in-use-strict-directive saved-strict-mode))
+      (cl-decf js2-nesting-of-function))
     (setq end (js2-current-token-end))  ; assume no curly and leave at current token
     (if (js2-must-match js2-RC "msg.no.brace.after.body" pos)
         (setq end (js2-current-token-end)))
@@ -8063,13 +8058,10 @@ Scanner should be initialized."
     (js2-node-add-children fn-node pn)
     pn))
 
-(defun js2-define-destruct-symbols
+(defun js2-define-destruct-symbols-internal
     (node decl-type face &optional ignore-not-in-block name-nodes)
-  "Declare and fontify destructuring parameters inside NODE.
-NODE is either `js2-array-node', `js2-object-node', or `js2-name-node'.
-
-Return a list of `js2-name-node' nodes representing the symbols
-declared; probably to check them for errors."
+  "Internal version of `js2-define-destruct-symbols'.  The only
+difference is that NAME-NODES is passed down recursively."
   (cond
    ((js2-name-node-p node)
     (let (leftpos)
@@ -8084,7 +8076,7 @@ declared; probably to check them for errors."
     (dolist (elem (js2-object-node-elems node))
       (setq name-nodes
             (append name-nodes
-                    (js2-define-destruct-symbols
+                    (js2-define-destruct-symbols-internal
                      ;; In abbreviated destructuring {a, b}, right == left.
                      (js2-object-prop-node-right elem)
                      decl-type face ignore-not-in-block name-nodes)))))
@@ -8093,12 +8085,20 @@ declared; probably to check them for errors."
       (when elem
         (setq name-nodes
               (append name-nodes
-                      (js2-define-destruct-symbols
+                      (js2-define-destruct-symbols-internal
                        elem decl-type face ignore-not-in-block name-nodes))))))
    (t (js2-report-error "msg.no.parm" nil (js2-node-abs-pos node)
                         (js2-node-len node))))
   name-nodes)
 
+(defun js2-define-destruct-symbols (node decl-type face &optional ignore-not-in-block)
+  "Declare and fontify destructuring parameters inside NODE.
+NODE is either `js2-array-node', `js2-object-node', or `js2-name-node'.
+
+Return a list of `js2-name-node' nodes representing the symbols
+declared; probably to check them for errors."
+  (js2-define-destruct-symbols-internal node decl-type face ignore-not-in-block))
+
 (defvar js2-illegal-strict-identifiers
   '("eval" "arguments")
   "Identifiers not allowed as variables in strict mode.")
@@ -8126,23 +8126,13 @@ for strict mode errors caused by PARAMS."
 
 (defun js2-parse-function-params (function-type fn-node pos)
   "Parse the parameters of a function of FUNCTION-TYPE
-represented by FN-NODE at POS.
-
-Return a list of lists of arguments to apply many times to
-`js2-check-strict-function-params' to retroactively check for
-strict mode errors that occurred.  Because the function body is
-parsed after its parameters, and the body might activate strict
-mode for that function, the check has to occur after the body is
-parsed."
+represented by FN-NODE at POS."
   (if (js2-match-token js2-RP)
-      (progn (setf (js2-function-node-rp fn-node) (- (js2-current-token-beg) pos))
-             ;; Return an empty list for consistency.
-             '())
+      (setf (js2-function-node-rp fn-node) (- (js2-current-token-beg) pos))
     (let ((paren-free-arrow (and (eq function-type 'FUNCTION_ARROW)
                                  (eq (js2-current-token-type) js2-NAME)))
           params param
           param-name-nodes new-param-name-nodes
-          error-checking-arguments
           default-found rest-param-at)
       (when paren-free-arrow
         (js2-unget-token))
@@ -8157,14 +8147,9 @@ parsed."
                    (js2-report-error "msg.no.default.after.default.param"))
                  (setq param (js2-parse-destruct-primary-expr)
                        new-param-name-nodes (js2-define-destruct-symbols
-                                             param js2-LP 'js2-function-param)
-                       error-checking-arguments (append
-                                                 error-checking-arguments
-                                                 (list
-                                                  (list
-                                                   param-name-nodes
-                                                   new-param-name-nodes)))
-                       param-name-nodes (append param-name-nodes new-param-name-nodes))
+                                             param js2-LP 'js2-function-param))
+                 (js2-check-strict-function-params param-name-nodes new-param-name-nodes)
+                 (setq param-name-nodes (append param-name-nodes new-param-name-nodes))
                  (push param params))
                 ;; variable name
                 (t
@@ -8178,12 +8163,8 @@ parsed."
                  (js2-record-face 'js2-function-param)
                  (setq param (js2-create-name-node))
                  (js2-define-symbol js2-LP (js2-current-token-string) param)
-                 (setq error-checking-arguments (append
-                                                 error-checking-arguments
-                                                 (list
-                                                  (list param-name-nodes
-                                                        (list param))))
-                       param-name-nodes (append param-name-nodes (list param)))
+                 (js2-check-strict-function-params param-name-nodes (list param))
+                 (setq param-name-nodes (append param-name-nodes (list param)))
                  ;; default parameter value
                  (when (or (and default-found
                                 (not rest-param-at)
@@ -8218,8 +8199,7 @@ parsed."
         (setf (js2-function-node-rest-p fn-node) t))
       (dolist (p params)
         (js2-node-add-children fn-node p)
-        (push p (js2-function-node-params fn-node)))
-      error-checking-arguments)))
+        (push p (js2-function-node-params fn-node))))))
 
 (defun js2-check-inconsistent-return-warning (fn-node name)
   "Possibly show inconsistent-return warning.
@@ -8268,10 +8248,7 @@ Last token scanned is the close-curly for the function body."
     (js2-must-match js2-LP "msg.no.paren.parms")
     (js2-parse-function 'FUNCTION_EXPRESSION pos star-p name)))
 
-(defun js2-parse-function (function-type pos star-p &optional name)
-  "Function parser.  FUNCTION-TYPE is a symbol, POS is the
-beginning of the first token (function keyword, unless it's an
-arrow function), NAME is js2-name-node."
+(defun js2-parse-function-internal (function-type pos star-p &optional name)
   (let (fn-node lp)
     (if (= (js2-current-token-type) js2-LP) ; eventually matched LP?
         (setq lp (js2-current-token-beg)))
@@ -8286,7 +8263,9 @@ arrow function), NAME is js2-name-node."
       (when (and (eq function-type 'FUNCTION_STATEMENT)
                  (cl-plusp (js2-name-node-length name)))
         ;; Function statements define a symbol in the enclosing scope
-        (js2-define-symbol js2-FUNCTION (js2-name-node-name name) fn-node)))
+        (js2-define-symbol js2-FUNCTION (js2-name-node-name name) fn-node))
+      (when js2-in-use-strict-directive
+        (js2-check-strict-identifier name)))
     (if (or (js2-inside-function) (cl-plusp js2-nesting-of-with))
         ;; 1. Nested functions are not affected by the dynamic scope flag
         ;;    as dynamic scope is already a parent of their scope.
@@ -8301,23 +8280,14 @@ arrow function), NAME is js2-name-node."
           (js2-end-flags 0)
           js2-label-set
           js2-loop-set
-          js2-loop-and-switch-set
-          (error-checking-arguments (js2-parse-function-params
-                                     function-type fn-node pos)))
+          js2-loop-and-switch-set)
+      (js2-parse-function-params function-type fn-node pos)
       (when (eq function-type 'FUNCTION_ARROW)
         (js2-must-match js2-ARROW "msg.bad.arrow.args"))
       (if (and (>= js2-language-version 180)
                (/= (js2-peek-token) js2-LC))
           (js2-parse-function-closure-body fn-node)
         (js2-parse-function-body fn-node))
-      (when (js2-function-node-in-strict-mode fn-node)
-        ;; Pretend that we're inside the function again.  It cleans up its
-        ;; `js2-in-use-strict-directive' binding.
-        (let ((js2-in-use-strict-directive t))
-          (when name
-            (js2-check-strict-identifier name))
-          (dolist (arguments error-checking-arguments)
-            (apply #'js2-check-strict-function-params arguments))))
       (js2-check-inconsistent-return-warning fn-node name)
 
       (when name
@@ -8341,6 +8311,29 @@ arrow function), NAME is js2-name-node."
     (setf (js2-scope-parent-scope fn-node) js2-current-scope)
     fn-node))
 
+(defun js2-parse-function (function-type pos star-p &optional name)
+  "Function parser.  FUNCTION-TYPE is a symbol, POS is the
+beginning of the first token (function keyword, unless it's an
+arrow function), NAME is js2-name-node."
+  (let ((continue t)
+        ts-state
+        fn-node
+        ;; Preserve strict state outside this function.
+        (js2-in-use-strict-directive js2-in-use-strict-directive))
+    ;; Parse multiple times if a new strict mode directive is discovered in the
+    ;; function body, as new rules will be retroactively applied to the legality
+    ;; of function names and parameters.
+    (while continue
+      (setq ts-state (make-js2-ts-state))
+      (setq continue (catch 'reparse
+                       (setq fn-node (js2-parse-function-internal
+                                      function-type pos star-p name))
+                       ;; Don't continue.
+                       nil))
+      (when continue
+        (js2-ts-seek ts-state)))
+    fn-node))
+
 (defun js2-parse-statements (&optional parent)
   "Parse a statement list.  Last token consumed must be js2-LC.
 
@@ -9675,7 +9668,10 @@ If NODE is non-nil, it is the AST node associated with the symbol."
         ;; tt express assignment (=, |=, ^=, ..., %=)
         (setq op-pos (- (js2-current-token-beg) pos)  ; relative
               left pn)
-        (js2-check-strict-identifier left)
+        ;; The assigned node could be a js2-prop-get-node (foo.bar = 0), we only
+        ;; care about assignment to strict variable names.
+        (when (js2-name-node-p left)
+          (js2-check-strict-identifier left))
         (setq right (js2-parse-assign-expr)
               pn (make-js2-assign-node :type tt
                                        :pos pos
@@ -10755,9 +10751,8 @@ expression)."
           (js2-unget-token)
           (unless class-p (setq continue nil))))
       (when elem
-        (setq elem-key-string (js2-property-key-string elem))
         (when (and js2-in-use-strict-directive
-                   elem-key-string
+                   (setq elem-key-string (js2-property-key-string elem))
                    (cl-some
                     (lambda (previous-elem)
                       (and (setq previous-elem-key-string
@@ -11310,15 +11305,6 @@ indentation is aligned to that column."
   (interactive)
   (while (forward-comment 1)))
 
-(defun js2-current-indent (&optional pos)
-  "Return column of indentation on current line.
-If POS is non-nil, go to that point and return indentation for that line."
-  (save-excursion
-    (if pos
-        (goto-char pos))
-    (back-to-indentation)
-    (current-column)))
-
 (defun js2-arglist-close ()
   "Return non-nil if we're on a line beginning with a close-paren/brace."
   (save-excursion
@@ -11373,7 +11359,7 @@ of the buffer to the current point.  NORMAL-COL is the indentation
 column computed by the heuristic guesser based on current paren,
 bracket, brace and statement nesting.  If BACKWARDS, cycle positions
 in reverse."
-  (let ((cur-indent (js2-current-indent))
+  (let ((cur-indent (current-indentation))
         (old-buffer-undo-list buffer-undo-list)
         ;; Emacs 21 only has `count-lines', not `line-number-at-pos'
         (current-line (save-excursion