Mercurial > dotfiles
changeset 27:614a83a1c5dd
Add js2-mode.
author | Augie Fackler <durin42@gmail.com> |
---|---|
date | Tue, 30 Dec 2008 13:25:23 -0600 |
parents | 895bcf0db86a |
children | 260deb14fbc8 |
files | .elisp/js2.el .elisp/js2.elc .emacs |
diffstat | 3 files changed, 11662 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/.elisp/js2.el @@ -0,0 +1,11659 @@ +;;; js2.el -- an improved JavaScript editing mode +;;; +;;; This file was auto-generated on Mon Jun 16 01:46:45 2008 from files: +;;; js2-vars.el +;;; js2-util.el +;;; js2-scan.el +;;; js2-messages.el +;;; js2-ast.el +;;; js2-highlight.el +;;; js2-browse.el +;;; js2-parse.el +;;; js2-indent.el +;;; js2-mode.el + +;;; js2-mode.el --- an improved JavaScript editing mode + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Version: 20080616 +;; Keywords: javascript languages + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of +;; the License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be +;; useful, but WITHOUT ANY WARRANTY; without even the implied +;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. See the GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public +;; License along with this program; if not, write to the Free +;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, +;; MA 02111-1307 USA + +;;; Commentary: + +;; This JavaScript editing mode supports: +;; +;; - the full JavaScript language through version 1.7 +;; - support for most Rhino and SpiderMonkey extensions from 1.5 to 1.7 +;; - accurate syntax highlighting using a recursive-descent parser +;; - syntax-error and strict-mode warning reporting +;; - "bouncing" line indentation to choose among alternate indentation points +;; - smart line-wrapping within comments (Emacs 22+) and strings +;; - code folding: +;; - show some or all function bodies as {...} +;; - show some or all block comments as /*...*/ +;; - context-sensitive menu bar and popup menus +;; - code browsing using the `imenu' package +;; - typing helpers (e.g. inserting matching braces/parens) +;; - many customization options +;; +;; It is only compatible with GNU Emacs versions 21 and higher (not XEmacs). +;; +;; Installation: +;; +;; - put `js2.el' somewhere in your emacs load path +;; - M-x byte-compile-file RET <path-to-js2.el> RET +;; Note: it will refuse to run unless byte-compiled +;; - add these lines to your .emacs file: +;; (autoload 'js2-mode "js2" nil t) +;; (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) +;; +;; To customize how it works: +;; M-x customize-group RET js2-mode RET +;; +;; The variable `js2-mode-version' is a date stamp. When you upgrade +;; to a newer version, you must byte-compile the file again. +;; +;; Notes: +;; +;; This mode is different in many ways from standard Emacs language editing +;; modes, inasmuch as it attempts to be more like an IDE. If this drives +;; you crazy, it IS possible to customize it to be more like other Emacs +;; editing modes. Please customize the group `js2-mode' to see all of the +;; configuration options. +;; +;; Some of the functionality does not work in Emacs 21 -- upgrading to +;; Emacs 22 or higher will get you better results. If you byte-compiled +;; js2.el with Emacs 21, you should re-compile it for Emacs 22. +;; +;; Unlike cc-engine based language modes, js2-mode's line-indentation is not +;; customizable. It is a surprising amount of work to support customizable +;; indentation. The current compromise is that the tab key lets you cycle among +;; various likely indentation points, similar to the behavior of python-mode. +;; +;; This mode does not yet work with "multi-mode" modes such as mmm-mode +;; and mumamo, although it could possibly be made to do so with some effort. +;; This means that js2-mode is currently only useful for editing JavaScript +;; files, and not for editing JavaScript within <script> tags or templates. +;; +;; This code is part of a larger project, in progress, to enable writing +;; Emacs customizations in JavaScript. +;; +;; Please email bug reports and suggestions to the author, or submit them +;; at http://code.google.com/p/js2-mode/issues + +;; TODO: +;; - add unreachable-code warning (error?) using the inconsistent-return analysis +;; - labeled stmt length is now 1 +;; - "anonymous function does not always return a value" - use getter/setter name +;; - extend js2-missing-semi-one-line-override to handle catch (e) {return x} +;; - set a text prop on autoinserted delimiters and don't biff user-entered ones +;; - when inserting magic curlies, look for matching close-curly before inserting +;; - get more use out of the symbol table: +;; - jump to declaration (put hyperlinks on all non-decl var usages?) +;; - rename variable/function +;; - warn on unused var +;; - add some dabbrev-expansions for built-in keywords like finally, function +;; - add at least some completion support, e.g. for built-ins +;; - code formatting + +;;; Code: +;;; js2-vars.el -- byte-compiler support for js2-mode + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Code: + +(eval-when-compile + (require 'cl)) + +(eval-and-compile + (require 'cc-mode) ; (only) for `c-populate-syntax-table' + (require 'cc-langs) ; it's here in Emacs 21... + (require 'cc-engine)) ; for `c-paragraph-start' et. al. + +(defvar js2-emacs22 (>= emacs-major-version 22)) + +(defcustom js2-highlight-level 2 + "Amount of syntax highlighting to perform. +nil, zero or negative means none. +1 adds basic syntax highlighting. +2 adds highlighting of some Ecma built-in properties. +3 adds highlighting of many Ecma built-in functions." + :type 'integer + :group 'js2-mode) + +(defvar js2-mode-dev-mode-p nil + "Non-nil if running in development mode. Normally nil.") + +(defgroup js2-mode nil + "An improved JavaScript mode." + :group 'languages) + +(defcustom js2-basic-offset (if (and (boundp 'c-basic-offset) + (numberp c-basic-offset)) + c-basic-offset + 2) + "Number of spaces to indent nested statements. +Similar to `c-basic-offset'." + :group 'js2-mode + :type 'integer) +(make-variable-buffer-local 'js2-basic-offset) + +(defcustom js2-cleanup-whitespace t + "Non-nil to invoke `delete-trailing-whitespace' before saves." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-move-point-on-right-click t + "Non-nil to move insertion point when you right-click. +This makes right-click context menu behavior a bit more intuitive, +since menu operations generally apply to the point. The exception +is if there is a region selection, in which case the point does -not- +move, so cut/copy/paste etc. can work properly. + +Note that IntelliJ moves the point, and Eclipse leaves it alone, +so this behavior is customizable." + :group 'js2-mode + :type 'boolean) + +(defcustom js2-mirror-mode t + "Non-nil to insert closing brackets, parens, etc. automatically." + :group 'js2-mode + :type 'boolean) + +(defcustom js2-auto-indent-flag t + "Automatic indentation with punctuation characters. If non-nil, the +current line is indented when certain punctuations are inserted." + :group 'js2-mode + :type 'boolean) + +(defcustom js2-bounce-indent-flag t + "Non-nil to have indent-line function choose among alternatives. +If nil, the indent-line function will indent to a predetermined column +based on heuristic guessing. If non-nil, then if the current line is +already indented to that predetermined column, indenting will choose +another likely column and indent to that spot. Repeated invocation of +the indent-line function will cycle among the computed alternatives. +See the function `js2-bounce-indent' for details." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-indent-on-enter-key nil + "Non-nil to have Enter/Return key indent the line. +This is unusual for Emacs modes but common in IDEs like Eclipse." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-enter-indents-newline t + "Non-nil to have Enter/Return key indent the newly-inserted line. +This is unusual for Emacs modes but common in IDEs like Eclipse." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-rebind-eol-bol-keys t + "Non-nil to rebind beginning-of-line and end-of-line keys. +If non-nil, bounce between bol/eol and first/last non-whitespace char." + :group 'js2-mode + :type 'boolean) + +(defcustom js2-electric-keys '("{" "}" "(" ")" "[" "]" ":" ";" "," "*") + "Keys that auto-indent when `js2-auto-indent-flag' is non-nil. +Each value in the list is passed to `define-key'." + :type 'list + :group 'js2-mode) + +(defcustom js2-idle-timer-delay 0.2 + "Delay in secs before re-parsing after user makes changes. +Multiplied by `js2-dynamic-idle-timer-adjust', which see." + :type 'number + :group 'js2-mode) +(make-variable-buffer-local 'js2-idle-timer-delay) + +(defcustom js2-dynamic-idle-timer-adjust 0 + "Positive to adjust `js2-idle-timer-delay' based on file size. +The idea is that for short files, parsing is faster so we can be +more responsive to user edits without interfering with editing. +The buffer length in characters (typically bytes) is divided by +this value and used to multiply `js2-idle-timer-delay' for the +buffer. For example, a 21k file and 10k adjust yields 21k/10k +== 2, so js2-idle-timer-delay is multiplied by 2. +If `js2-dynamic-idle-timer-adjust' is 0 or negative, +`js2-idle-timer-delay' is not dependent on the file size." + :type 'number + :group 'js2-mode) + +(defcustom js2-mode-escape-quotes t + "Non-nil to disable automatic quote-escaping inside strings." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-mode-squeeze-spaces t + "Non-nil to normalize whitespace when filling in comments. +Multiple runs of spaces are converted to a single space." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-mode-show-parse-errors t + "True to highlight parse errors." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-mode-show-strict-warnings t + "Non-nil to emit Ecma strict-mode warnings. +Some of the warnings can be individually disabled by other flags, +even if this flag is non-nil." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-trailing-comma-warning t + "Non-nil to warn about trailing commas in array literals. +Ecma-262 forbids them, but many browsers permit them. IE is the +big exception, and can produce bugs if you have trailing commas." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-missing-semi-warning t + "Non-nil to warn about semicolon auto-insertion after statement. +Technically this is legal per Ecma-262, but some style guides disallow +depending on it." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-missing-semi-one-line-override nil + "Non-nil to permit missing semicolons in one-line functions. +In one-liner functions such as `function identity(x) {return x}' +people often omit the semicolon for a cleaner look. If you are +such a person, you can suppress the missing-semicolon warning +by setting this variable to t." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-inconsistent-return-warning t + "Non-nil to warn about mixing returns with value-returns. +It's perfectly legal to have a `return' and a `return foo' in the +same function, but it's often an indicator of a bug, and it also +interferes with type inference (in systems that support it.)" + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-cond-assign-warning t + "Non-nil to warn about expressions like if (a = b). +This often should have been '==' instead of '='. If the warning +is enabled, you can suppress it on a per-expression basis by +parenthesizing the expression, e.g. if ((a = b)) ..." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-cond-assign-warning t + "Non-nil to warn about expressions like if (a = b). +This often should have been '==' instead of '='. If the warning +is enabled, you can suppress it on a per-expression basis by +parenthesizing the expression, e.g. if ((a = b)) ..." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-var-redeclaration-warning t + "Non-nil to warn about redeclaring variables in a script or function." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-strict-var-hides-function-arg-warning t + "Non-nil to warn about a var decl hiding a function argument." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-skip-preprocessor-directives nil + "Non-nil to treat lines beginning with # as comments. +Useful for viewing Mozilla JavaScript source code." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-basic-offset c-basic-offset + "Functions like `c-basic-offset' in js2-mode buffers." + :type 'integer + :group 'js2-mode) +(make-variable-buffer-local 'js2-basic-offset) + +(defcustom js2-language-version 170 + "Configures what JavaScript language version to recognize. +Currently only 150, 160 and 170 are supported, corresponding +to JavaScript 1.5, 1.6 and 1.7, respectively. In a nutshell, +1.6 adds E4X support, and 1.7 adds let, yield, and Array +comprehensions." + :type 'integer + :group 'js2-mode) + +(defcustom js2-allow-keywords-as-property-names t + "If non-nil, you can use JavaScript keywords as object property names. +Examples: + + var foo = {int: 5, while: 6, continue: 7}; + foo.return = 8; + +Ecma-262 forbids this syntax, but many browsers support it." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-instanceof-has-side-effects nil + "If non-nil, treats the instanceof operator as having side effects. +This is useful for xulrunner apps." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-allow-rhino-new-expr-initializer nil + "Non-nil to support a Rhino's experimental syntactic construct. + +Rhino supports the ability to follow a `new' expression with an object +literal, which is used to set additional properties on the new object +after calling its constructor. Syntax: + + new <expr> [ ( arglist ) ] [initializer] + +Hence, this expression: + + new Object {a: 1, b: 2} + +results in an Object with properties a=1 and b=2. This syntax is +apparently not configurable in Rhino - it's currently always enabled, +as of Rhino version 1.7R2." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-allow-member-expr-as-function-name nil + "Non-nil to support experimental Rhino syntax for function names. + +Rhino supports an experimental syntax configured via the Rhino Context +setting `allowMemberExprAsFunctionName'. The experimental syntax is: + + function <member-expr> ( [ arg-list ] ) { <body> } + +Where member-expr is a non-parenthesized 'member expression', which +is anything at the grammar level of a new-expression or lower, meaning +any expression that does not involve infix or unary operators. + +When <member-expr> is not a simple identifier, then it is syntactic +sugar for assigning the anonymous function to the <member-expr>. Hence, +this code: + + function a.b().c[2] (x, y) { ... } + +is rewritten as: + + a.b().c[2] = function(x, y) {...} + +which doesn't seem particularly useful, but Rhino permits it." + :type 'boolean + :group 'js2-mode) + +(defvar js2-mode-version 20080616 + "Release number for `js2-mode'.") + +;; scanner variables + +;; We record the start and end position of each token. +(defvar js2-token-beg 1) +(make-variable-buffer-local 'js2-token-beg) +(defvar js2-token-end -1) +(make-variable-buffer-local 'js2-token-end) + +(defvar js2-EOF_CHAR -1 + "Represents end of stream. Distinct from js2-EOF token type.") + +;; I originally used symbols to represent tokens, but Rhino uses +;; ints and then sets various flag bits in them, so ints it is. +;; The upshot is that we need a `js2-' prefix in front of each name. +(defvar js2-ERROR -1) +(defvar js2-EOF 0) +(defvar js2-EOL 1) +(defvar js2-ENTERWITH 2) ; begin interpreter bytecodes +(defvar js2-LEAVEWITH 3) +(defvar js2-RETURN 4) +(defvar js2-GOTO 5) +(defvar js2-IFEQ 6) +(defvar js2-IFNE 7) +(defvar js2-SETNAME 8) +(defvar js2-BITOR 9) +(defvar js2-BITXOR 10) +(defvar js2-BITAND 11) +(defvar js2-EQ 12) +(defvar js2-NE 13) +(defvar js2-LT 14) +(defvar js2-LE 15) +(defvar js2-GT 16) +(defvar js2-GE 17) +(defvar js2-LSH 18) +(defvar js2-RSH 19) +(defvar js2-URSH 20) +(defvar js2-ADD 21) ; infix plus +(defvar js2-SUB 22) ; infix minus +(defvar js2-MUL 23) +(defvar js2-DIV 24) +(defvar js2-MOD 25) +(defvar js2-NOT 26) +(defvar js2-BITNOT 27) +(defvar js2-POS 28) ; unary plus +(defvar js2-NEG 29) ; unary minus +(defvar js2-NEW 30) +(defvar js2-DELPROP 31) +(defvar js2-TYPEOF 32) +(defvar js2-GETPROP 33) +(defvar js2-GETPROPNOWARN 34) +(defvar js2-SETPROP 35) +(defvar js2-GETELEM 36) +(defvar js2-SETELEM 37) +(defvar js2-CALL 38) +(defvar js2-NAME 39) ; an identifier +(defvar js2-NUMBER 40) +(defvar js2-STRING 41) +(defvar js2-NULL 42) +(defvar js2-THIS 43) +(defvar js2-FALSE 44) +(defvar js2-TRUE 45) +(defvar js2-SHEQ 46) ; shallow equality (===) +(defvar js2-SHNE 47) ; shallow inequality (!==) +(defvar js2-REGEXP 48) +(defvar js2-BINDNAME 49) +(defvar js2-THROW 50) +(defvar js2-RETHROW 51) ; rethrow caught exception: catch (e if ) uses it +(defvar js2-IN 52) +(defvar js2-INSTANCEOF 53) +(defvar js2-LOCAL_LOAD 54) +(defvar js2-GETVAR 55) +(defvar js2-SETVAR 56) +(defvar js2-CATCH_SCOPE 57) +(defvar js2-ENUM_INIT_KEYS 58) +(defvar js2-ENUM_INIT_VALUES 59) +(defvar js2-ENUM_INIT_ARRAY 60) +(defvar js2-ENUM_NEXT 61) +(defvar js2-ENUM_ID 62) +(defvar js2-THISFN 63) +(defvar js2-RETURN_RESULT 64) ; to return previously stored return result +(defvar js2-ARRAYLIT 65) ; array literal +(defvar js2-OBJECTLIT 66) ; object literal +(defvar js2-GET_REF 67) ; *reference +(defvar js2-SET_REF 68) ; *reference = something +(defvar js2-DEL_REF 69) ; delete reference +(defvar js2-REF_CALL 70) ; f(args) = something or f(args)++ +(defvar js2-REF_SPECIAL 71) ; reference for special properties like __proto +(defvar js2-YIELD 72) ; JS 1.7 yield pseudo keyword + +;; XML support +(defvar js2-DEFAULTNAMESPACE 73) +(defvar js2-ESCXMLATTR 74) +(defvar js2-ESCXMLTEXT 75) +(defvar js2-REF_MEMBER 76) ; Reference for x.@y, x..y etc. +(defvar js2-REF_NS_MEMBER 77) ; Reference for x.ns::y, x..ns::y etc. +(defvar js2-REF_NAME 78) ; Reference for @y, @[y] etc. +(defvar js2-REF_NS_NAME 79) ; Reference for ns::y, @ns::y@[y] etc. + +(defvar js2-first-bytecode js2-ENTERWITH) +(defvar js2-last-bytecode js2-REF_NS_NAME) + +(defvar js2-TRY 80) +(defvar js2-SEMI 81) ; semicolon +(defvar js2-LB 82) ; left and right brackets +(defvar js2-RB 83) +(defvar js2-LC 84) ; left and right curly-braces +(defvar js2-RC 85) +(defvar js2-LP 86) ; left and right parens +(defvar js2-RP 87) +(defvar js2-COMMA 88) ; comma operator + +(defvar js2-ASSIGN 89) ; simple assignment (=) +(defvar js2-ASSIGN_BITOR 90) ; |= +(defvar js2-ASSIGN_BITXOR 91) ; ^= +(defvar js2-ASSIGN_BITAND 92) ; &= +(defvar js2-ASSIGN_LSH 93) ; <<= +(defvar js2-ASSIGN_RSH 94) ; >>= +(defvar js2-ASSIGN_URSH 95) ; >>>= +(defvar js2-ASSIGN_ADD 96) ; += +(defvar js2-ASSIGN_SUB 97) ; -= +(defvar js2-ASSIGN_MUL 98) ; *= +(defvar js2-ASSIGN_DIV 99) ; /= +(defvar js2-ASSIGN_MOD 100) ; %= + +(defvar js2-first-assign js2-ASSIGN) +(defvar js2-last-assign js2-ASSIGN_MOD) + +(defvar js2-HOOK 101) ; conditional (?:) +(defvar js2-COLON 102) +(defvar js2-OR 103) ; logical or (||) +(defvar js2-AND 104) ; logical and (&&) +(defvar js2-INC 105) ; increment/decrement (++ --) +(defvar js2-DEC 106) +(defvar js2-DOT 107) ; member operator (.) +(defvar js2-FUNCTION 108) ; function keyword +(defvar js2-EXPORT 109) ; export keyword +(defvar js2-IMPORT 110) ; import keyword +(defvar js2-IF 111) ; if keyword +(defvar js2-ELSE 112) ; else keyword +(defvar js2-SWITCH 113) ; switch keyword +(defvar js2-CASE 114) ; case keyword +(defvar js2-DEFAULT 115) ; default keyword +(defvar js2-WHILE 116) ; while keyword +(defvar js2-DO 117) ; do keyword +(defvar js2-FOR 118) ; for keyword +(defvar js2-BREAK 119) ; break keyword +(defvar js2-CONTINUE 120) ; continue keyword +(defvar js2-VAR 121) ; var keyword +(defvar js2-WITH 122) ; with keyword +(defvar js2-CATCH 123) ; catch keyword +(defvar js2-FINALLY 124) ; finally keyword +(defvar js2-VOID 125) ; void keyword +(defvar js2-RESERVED 126) ; reserved keywords + +(defvar js2-EMPTY 127) + +;; Types used for the parse tree - never returned by scanner. + +(defvar js2-BLOCK 128) ; statement block +(defvar js2-LABEL 129) ; label +(defvar js2-TARGET 130) +(defvar js2-LOOP 131) +(defvar js2-EXPR_VOID 132) ; expression statement in functions +(defvar js2-EXPR_RESULT 133) ; expression statement in scripts +(defvar js2-JSR 134) +(defvar js2-SCRIPT 135) ; top-level node for entire script +(defvar js2-TYPEOFNAME 136) ; for typeof(simple-name) +(defvar js2-USE_STACK 137) +(defvar js2-SETPROP_OP 138) ; x.y op= something +(defvar js2-SETELEM_OP 139) ; x[y] op= something +(defvar js2-LOCAL_BLOCK 140) +(defvar js2-SET_REF_OP 141) ; *reference op= something + +;; For XML support: +(defvar js2-DOTDOT 142) ; member operator (..) +(defvar js2-COLONCOLON 143) ; namespace::name +(defvar js2-XML 144) ; XML type +(defvar js2-DOTQUERY 145) ; .() -- e.g., x.emps.emp.(name == "terry") +(defvar js2-XMLATTR 146) ; @ +(defvar js2-XMLEND 147) + +;; Optimizer-only tokens +(defvar js2-TO_OBJECT 148) +(defvar js2-TO_DOUBLE 149) + +(defvar js2-GET 150) ; JS 1.5 get pseudo keyword +(defvar js2-SET 151) ; JS 1.5 set pseudo keyword +(defvar js2-LET 152) ; JS 1.7 let pseudo keyword +(defvar js2-CONST 153) +(defvar js2-SETCONST 154) +(defvar js2-SETCONSTVAR 155) +(defvar js2-ARRAYCOMP 156) +(defvar js2-LETEXPR 157) +(defvar js2-WITHEXPR 158) +(defvar js2-DEBUGGER 159) + +(defvar js2-COMMENT 160) ; not yet in Rhino + +(defvar js2-num-tokens (1+ js2-COMMENT)) + +(defconst js2-debug-print-trees nil) + +;; Rhino accepts any string or stream as input. +;; Emacs character processing works best in buffers, so we'll +;; assume the input is a buffer. JavaScript strings can be +;; copied into temp buffers before scanning them. + +(defmacro deflocal (name value comment) + `(progn + (defvar ,name ,value ,comment) + (make-variable-buffer-local ',name))) + +;; Buffer-local variables yield much cleaner code than using `defstruct'. +;; They're the Emacs equivalent of instance variables, more or less. + +(deflocal js2-ts-dirty-line nil + "Token stream buffer-local variable. +Indicates stuff other than whitespace since start of line.") + +(deflocal js2-ts-regexp-flags nil + "Token stream buffer-local variable.") + +(deflocal js2-ts-string "" + "Token stream buffer-local variable. +Last string scanned.") + +(deflocal js2-ts-number nil + "Token stream buffer-local variable. +Last literal number scanned.") + +(deflocal js2-ts-hit-eof nil + "Token stream buffer-local variable.") + +(deflocal js2-ts-line-start 0 + "Token stream buffer-local variable.") + +(deflocal js2-ts-lineno 1 + "Token stream buffer-local variable.") + +(deflocal js2-ts-line-end-char -1 + "Token stream buffer-local variable.") + +(deflocal js2-ts-cursor 1 ; emacs buffers are 1-indexed + "Token stream buffer-local variable. +Current scan position.") + +(deflocal js2-ts-is-xml-attribute nil + "Token stream buffer-local variable.") + +(deflocal js2-ts-xml-is-tag-content nil + "Token stream buffer-local variable.") + +(deflocal js2-ts-xml-open-tags-count 0 + "Token stream buffer-local variable.") + +(deflocal js2-ts-string-buffer nil + "Token stream buffer-local variable. +List of chars built up while scanning various tokens.") + +(deflocal js2-ts-comment-type nil + "Token stream buffer-local variable.") + +;;; Parser variables + +(defvar js2-parsed-errors nil + "List of errors produced during scanning/parsing.") +(make-variable-buffer-local 'js2-parsed-errors) + +(defvar js2-parsed-warnings nil + "List of warnings produced during scanning/parsing.") +(make-variable-buffer-local 'js2-parsed-warnings) + +(defvar js2-recover-from-parse-errors t + "Non-nil to continue parsing after a syntax error. + +In recovery mode, the AST will be built in full, and any error +nodes will be flagged with appropriate error information. If +this flag is nil, a syntax error will result in an error being +signaled. + +The variable is automatically buffer-local, because different +modes that use the parser will need different settings.") +(make-variable-buffer-local 'js2-recover-from-parse-errors) + +(defvar js2-parse-hook nil + "List of callbacks for receiving parsing progress.") +(make-variable-buffer-local 'js2-parse-hook) + +(defvar js2-parse-finished-hook nil + "List of callbacks to notify when parsing finishes. +Not called if parsing was interrupted.") + +(defvar js2-is-eval-code nil + "True if we're evaluating code in a string. +If non-nil, the tokenizer will record the token text, and the AST nodes +will record their source text. Off by default for IDE modes, since the +text is available in the buffer.") +(make-variable-buffer-local 'js2-is-eval-code) + +(defvar js2-parse-ide-mode t + "Non-nil if the parser is being used for `js2-mode'. +If non-nil, the parser will set text properties for fontification +and the syntax-table. The value should be nil when using the +parser as a frontend to an interpreter or byte compiler.") + +;;; Parser instance variables (buffer-local vars for js2-parse) + +(defconst js2-clear-ti-mask #xFFFF + "Mask to clear token information bits.") + +(defconst js2-ti-after-eol (lsh 1 16) + "Flag: first token of the source line.") + +(defconst js2-ti-check-label (lsh 1 17) + "Flag: indicates to check for label.") + +;; Inline Rhino's CompilerEnvirons vars as buffer-locals. + +(defvar js2-compiler-generate-debug-info t) +(make-variable-buffer-local 'js2-compiler-generate-debug-info) + +(defvar js2-compiler-use-dynamic-scope nil) +(make-variable-buffer-local 'js2-compiler-use-dynamic-scope) + +(defvar js2-compiler-reserved-keywords-as-identifier nil) +(make-variable-buffer-local 'js2-compiler-reserved-keywords-as-identifier) + +(defvar js2-compiler-xml-available t) +(make-variable-buffer-local 'js2-compiler-xml-available) + +(defvar js2-compiler-optimization-level 0) +(make-variable-buffer-local 'js2-compiler-optimization-level) + +(defvar js2-compiler-generating-source t) +(make-variable-buffer-local 'js2-compiler-generating-source) + +(defvar js2-compiler-strict-mode nil) +(make-variable-buffer-local 'js2-compiler-strict-mode) + +(defvar js2-compiler-report-warning-as-error nil) +(make-variable-buffer-local 'js2-compiler-report-warning-as-error) + +(defvar js2-compiler-generate-observer-count nil) +(make-variable-buffer-local 'js2-compiler-generate-observer-count) + +(defvar js2-compiler-activation-names nil) +(make-variable-buffer-local 'js2-compiler-activation-names) + +;; SKIP: sourceURI + +;; There's a compileFunction method in Context.java - may need it. +(defvar js2-called-by-compile-function nil + "True if `js2-parse' was called by `js2-compile-function'. +Will only be used when we finish implementing the interpreter.") +(make-variable-buffer-local 'js2-called-by-compile-function) + +;; SKIP: ts (we just call `js2-init-scanner' and use its vars) + +(defvar js2-current-flagged-token js2-EOF) +(make-variable-buffer-local 'js2-current-flagged-token) + +(defvar js2-current-token js2-EOF) +(make-variable-buffer-local 'js2-current-token) + +;; SKIP: node factory - we're going to just call functions directly, +;; and eventually go to a unified AST format. + +(defvar js2-nesting-of-function 0) +(make-variable-buffer-local 'js2-nesting-of-function) + +(defvar js2-recorded-assignments nil) +(make-variable-buffer-local 'js2-assignments-from-parse) + +;; SKIP: decompiler +;; SKIP: encoded-source + +;;; These variables are per-function and should be saved/restored +;;; during function parsing. + +(defvar js2-current-script-or-fn nil) +(make-variable-buffer-local 'js2-current-script-or-fn) + +(defvar js2-current-scope nil) +(make-variable-buffer-local 'js2-current-scope) + +(defvar js2-nesting-of-with 0) +(make-variable-buffer-local 'js2-nesting-of-with) + +(defvar js2-label-set nil + "An alist mapping label names to nodes.") +(make-variable-buffer-local 'js2-label-set) + +(defvar js2-loop-set nil) +(make-variable-buffer-local 'js2-loop-set) + +(defvar js2-loop-and-switch-set nil) +(make-variable-buffer-local 'js2-loop-and-switch-set) + +(defvar js2-has-return-value nil) +(make-variable-buffer-local 'js2-has-return-value) + +(defvar js2-end-flags 0) +(make-variable-buffer-local 'js2-end-flags) + +;;; end of per function variables + +;; Without 2-token lookahead, labels are a problem. +;; These vars store the token info of the last matched name, +;; iff it wasn't the last matched token. Only valid in some contexts. +(defvar js2-prev-name-token-start nil) +(defvar js2-prev-name-token-string nil) + +(defsubst js2-save-name-token-data (pos name) + (setq js2-prev-name-token-start pos + js2-prev-name-token-string name)) + +;; These flags enumerate the possible ways a statement/function can +;; terminate. These flags are used by endCheck() and by the Parser to +;; detect inconsistent return usage. +;; +;; END_UNREACHED is reserved for code paths that are assumed to always be +;; able to execute (example: throw, continue) +;; +;; END_DROPS_OFF indicates if the statement can transfer control to the +;; next one. Statement such as return dont. A compound statement may have +;; some branch that drops off control to the next statement. +;; +;; END_RETURNS indicates that the statement can return (without arguments) +;; END_RETURNS_VALUE indicates that the statement can return a value. +;; +;; A compound statement such as +;; if (condition) { +;; return value; +;; } +;; Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck() + +(defconst js2-end-unreached #x0) +(defconst js2-end-drops-off #x1) +(defconst js2-end-returns #x2) +(defconst js2-end-returns-value #x4) +(defconst js2-end-yields #x8) + +;; Rhino awkwardly passes a statementLabel parameter to the +;; statementHelper() function, the main statement parser, which +;; is then used by quite a few of the sub-parsers. We just make +;; it a buffer-local variable and make sure it's cleaned up properly. +(defvar js2-labeled-stmt nil) ; type `js2-labeled-stmt-node' +(make-variable-buffer-local 'js2-labeled-stmt) + +;; Similarly, Rhino passes an inForInit boolean through about half +;; the expression parsers. We use a dynamically-scoped variable, +;; which makes it easier to funcall the parsers individually without +;; worrying about whether they take the parameter or not. +(defvar js2-in-for-init nil) +(make-variable-buffer-local 'js2-in-for-init) + +(defvar js2-temp-name-counter 0) +(make-variable-buffer-local 'js2-temp-name-counter) + +(defvar js2-parse-stmt-count 0) +(make-variable-buffer-local 'js2-parse-stmt-count) + +(defsubst js2-get-next-temp-name () + (format "$%d" (incf js2-temp-name-counter))) + +(defvar js2-parse-interruptable-p t + "Set this to nil to force parse to continue until finished. +This will mostly be useful for interpreters.") + +(defvar js2-statements-per-pause 50 + "Pause after this many statements to check for user input. +If user input is pending, stop the parse and discard the tree. +This makes for a smoother user experience for large files. +You may have to wait a second or two before the highlighting +and error-reporting appear, but you can always type ahead if +you wish. This appears to be more or less how Eclipse, IntelliJ +and other editors work.") + +(defvar js2-record-comments t + "Instructs the scanner to record comments in `js2-scanned-comments'.") +(make-variable-buffer-local 'js2-record-comments) + +(defvar js2-scanned-comments nil + "List of all comments from the current parse.") +(make-variable-buffer-local 'js2-scanned-comments) + +(defun js2-underline-color (color) + "Return a legal value for the :underline face attribute based on COLOR." + ;; In XEmacs the :underline attribute can only be a boolean. + ;; In GNU it can be the name of a colour. + (if (featurep 'xemacs) + (if color t nil) + color)) + +(defcustom js2-mode-indent-inhibit-undo nil + "Non-nil to disable collection of Undo information when indenting lines. +Some users have requested this behavior. It's nil by default because +other Emacs modes don't work this way." + :type 'boolean + :group 'js2-mode) + +(defcustom js2-mode-indent-ignore-first-tab nil + "If non-nil, ignore first TAB keypress if we look indented properly. +It's fairly common for users to navigate to an already-indented line +and press TAB for reassurance that it's been indented. For this class +of users, we want the first TAB press on a line to be ignored if the +line is already indented to one of the precomputed alternatives. + +This behavior is only partly implemented. If you TAB-indent a line, +navigate to another line, and then navigate back, it fails to clear +the last-indented variable, so it thinks you've already hit TAB once, +and performs the indent. A full solution would involve getting on the +point-motion hooks for the entire buffer. If we come across another +use cases that requires watching point motion, I'll consider doing it. + +If you set this variable to nil, then the TAB key will always change +the indentation of the current line, if more than one alternative +indentation spot exists." + :type 'boolean + :group 'js2-mode) + +(defvar js2-indent-hook nil + "A hook for user-defined indentation rules. + +Functions on this hook should expect two arguments: (LIST INDEX) +The LIST argument is the list of computed indentation points for +the current line. INDEX is the list index of the indentation point +that `js2-bounce-indent' plans to use. If INDEX is nil, then the +indent function is not going to change the current line indentation. + +If a hook function on this list returns a non-nil value, then +`js2-bounce-indent' assumes the hook function has performed its own +indentation, and will do nothing. If all hook functions on the list +return nil, then `js2-bounce-indent' will use its computed indentation +and reindent the line. + +When hook functions on this hook list are called, the variable +`js2-mode-ast' may or may not be set, depending on whether the +parse tree is available. If the variable is nil, you can pass a +callback to `js2-mode-wait-for-parse', and your callback will be +called after the new parse tree is built. This can take some time +in large files.") + +(defface js2-warning-face + `((((class color) (background light)) + (:underline ,(js2-underline-color "orange"))) + (((class color) (background dark)) + (:underline ,(js2-underline-color "orange"))) + (t (:underline t))) + "Face for JavaScript warnings." + :group 'js2-mode) + +(defface js2-error-face + `((((class color) (background light)) + (:foreground "red")) + (((class color) (background dark)) + (:foreground "red")) + (t (:foreground "red"))) + "Face for JavaScript errors." + :group 'js2-mode) + +(defface js2-jsdoc-tag-face + '((t :foreground "SlateGray")) + "Face used to highlight @whatever tags in jsdoc comments." + :group 'js2-mode) + +(defface js2-jsdoc-type-face + '((t :foreground "SteelBlue")) + "Face used to highlight {FooBar} types in jsdoc comments." + :group 'js2-mode) + +(defface js2-jsdoc-value-face + '((t :foreground "PeachPuff3")) + "Face used to highlight tag values in jsdoc comments." + :group 'js2-mode) + +(defface js2-function-param-face + '((t :foreground "SeaGreen")) + "Face used to highlight function parameters in javascript." + :group 'js2-mode) + +(defface js2-instance-member-face + '((t :foreground "DarkOrchid")) + "Face used to highlight instance variables in javascript. +Not currently used." + :group 'js2-mode) + +(defface js2-private-member-face + '((t :foreground "PeachPuff3")) + "Face used to highlight calls to private methods in javascript. +Not currently used." + :group 'js2-mode) + +(defface js2-private-function-call-face + '((t :foreground "goldenrod")) + "Face used to highlight calls to private functions in javascript. +Not currently used." + :group 'js2-mode) + +(defface js2-jsdoc-html-tag-name-face + (if js2-emacs22 + '((((class color) (min-colors 88) (background light)) + (:foreground "rosybrown")) + (((class color) (min-colors 8) (background dark)) + (:foreground "yellow")) + (((class color) (min-colors 8) (background light)) + (:foreground "magenta"))) + '((((type tty pc) (class color) (background light)) + (:foreground "magenta")) + (((type tty pc) (class color) (background dark)) + (:foreground "yellow")) + (t (:foreground "RosyBrown")))) + "Face used to highlight jsdoc html tag names" + :group 'js2-mode) + +(defface js2-jsdoc-html-tag-delimiter-face + (if js2-emacs22 + '((((class color) (min-colors 88) (background light)) + (:foreground "dark khaki")) + (((class color) (min-colors 8) (background dark)) + (:foreground "green")) + (((class color) (min-colors 8) (background light)) + (:foreground "green"))) + '((((type tty pc) (class color) (background light)) + (:foreground "green")) + (((type tty pc) (class color) (background dark)) + (:foreground "green")) + (t (:foreground "dark khaki")))) + "Face used to highlight brackets in jsdoc html tags." + :group 'js2-mode) + +(defface js2-external-variable-face + '((t :foreground "orange")) + "Face used to highlight assignments to undeclared variables. +An undeclared variable is any variable not declared with var or let +in the current scope or any lexically enclosing scope. If you assign +to such a variable, then you are either expecting it to originate from +another file, or you've got a potential bug." + :group 'js2-mode) + +(defcustom js2-highlight-external-variables t + "Non-nil to higlight assignments to undeclared variables." + :type 'boolean + :group 'js2-mode) + +(defvar js2-mode-map + (let ((map (make-sparse-keymap)) + keys) + (define-key map [mouse-1] #'js2-mode-show-node) + (define-key map "\C-m" #'js2-enter-key) + (when js2-rebind-eol-bol-keys + (define-key map "\C-a" #'js2-beginning-of-line) + (define-key map "\C-e" #'js2-end-of-line)) + (define-key map "\C-c\C-e" #'js2-mode-hide-element) + (define-key map "\C-c\C-s" #'js2-mode-show-element) + (define-key map "\C-c\C-a" #'js2-mode-show-all) + (define-key map "\C-c\C-f" #'js2-mode-toggle-hide-functions) + (define-key map "\C-c\C-t" #'js2-mode-toggle-hide-comments) + (define-key map "\C-c\C-o" #'js2-mode-toggle-element) + (define-key map "\C-c\C-w" #'js2-mode-toggle-warnings-and-errors) + (define-key map (kbd "C-c C-'") #'js2-next-error) + ;; also define user's preference for next-error, if available + (if (setq keys (where-is-internal #'next-error)) + (define-key map (car keys) #'js2-next-error)) + (define-key map (or (car (where-is-internal #'mark-defun)) + (kbd "M-C-h")) + #'js2-mark-defun) + (define-key map (or (car (where-is-internal #'narrow-to-defun)) + (kbd "C-x nd")) + #'js2-narrow-to-defun) + (define-key map [down-mouse-3] #'js2-mouse-3) + (when js2-auto-indent-flag + (mapc (lambda (key) + (define-key map key #'js2-insert-and-indent)) + js2-electric-keys)) + + (define-key map [menu-bar javascript] + (cons "JavaScript" (make-sparse-keymap "JavaScript"))) + + (define-key map [menu-bar javascript customize-js2-mode] + '(menu-item "Customize js2-mode" js2-mode-customize + :help "Customize the behavior of this mode")) + + (define-key map [menu-bar javascript js2-force-refresh] + '(menu-item "Force buffer refresh" js2-mode-reset + :help "Re-parse the buffer from scratch")) + + (define-key map [menu-bar javascript separator-2] + '("--")) + + (define-key map [menu-bar javascript next-error] + '(menu-item "Next warning or error" js2-next-error + :enabled (and js2-mode-ast + (or (js2-ast-root-errors js2-mode-ast) + (js2-ast-root-warnings js2-mode-ast))) + :help "Move to next warning or error")) + + (define-key map [menu-bar javascript display-errors] + '(menu-item "Show errors and warnings" js2-mode-display-warnings-and-errors + :visible (not js2-mode-show-parse-errors) + :help "Turn on display of warnings and errors")) + + (define-key map [menu-bar javascript hide-errors] + '(menu-item "Hide errors and warnings" js2-mode-hide-warnings-and-errors + :visible js2-mode-show-parse-errors + :help "Turn off display of warnings and errors")) + + (define-key map [menu-bar javascript separator-1] + '("--")) + + (define-key map [menu-bar javascript js2-toggle-function] + '(menu-item "Show/collapse element" js2-mode-toggle-element + :help "Hide or show function body or comment")) + + (define-key map [menu-bar javascript show-comments] + '(menu-item "Show block comments" js2-mode-toggle-hide-comments + :visible js2-mode-comments-hidden + :help "Expand all hidden block comments")) + + (define-key map [menu-bar javascript hide-comments] + '(menu-item "Hide block comments" js2-mode-toggle-hide-comments + :visible (not js2-mode-comments-hidden) + :help "Show block comments as /*...*/")) + + (define-key map [menu-bar javascript show-all-functions] + '(menu-item "Show function bodies" js2-mode-toggle-hide-functions + :visible js2-mode-functions-hidden + :help "Expand all hidden function bodies")) + + (define-key map [menu-bar javascript hide-all-functions] + '(menu-item "Hide function bodies" js2-mode-toggle-hide-functions + :visible (not js2-mode-functions-hidden) + :help "Show {...} for all top-level function bodies")) + + map) + "Keymap used in `js2-mode' buffers.") + +(defconst js2-mode-identifier-re "[a-zA-Z_$][a-zA-Z0-9_$]*") + +(defvar js2-mode-//-comment-re "^\\(\\s-*\\)//.+" + "Matches a //-comment line. Must be first non-whitespace on line. +First match-group is the leading whitespace.") + +(defvar js2-mode-ast nil "Private variable.") +(make-variable-buffer-local 'js2-mode-ast) + +(defvar js2-mode-hook nil) + +(defvar js2-mode-parse-timer nil "Private variable.") +(make-variable-buffer-local 'js2-mode-parse-timer) + +(defvar js2-mode-buffer-dirty-p nil "Private variable.") +(make-variable-buffer-local 'js2-mode-buffer-dirty-p) + +(defvar js2-mode-parsing nil "Private variable.") +(make-variable-buffer-local 'js2-mode-parsing) + +(defvar js2-mode-node-overlay nil) +(make-variable-buffer-local 'js2-mode-node-overlay) + +(defvar js2-mode-show-overlay js2-mode-dev-mode-p + "Debug: Non-nil to highlight AST nodes on mouse-down.") + +(defvar js2-mode-fontifications nil "Private variable") +(make-variable-buffer-local 'js2-mode-fontifications) + +(defvar js2-mode-deferred-properties nil "Private variable") +(make-variable-buffer-local 'js2-mode-deferred-properties) + +(defvar js2-imenu-recorder nil "Private variable") +(make-variable-buffer-local 'js2-imenu-recorder) + +(defvar js2-imenu-function-map nil "Private variable") +(make-variable-buffer-local 'js2-imenu-function-map) + +(defvar js2-paragraph-start + "\\(@[a-zA-Z]+\\>\\|$\\)") + +;; Note that we also set a 'c-in-sws text property in html comments, +;; so that `c-forward-sws' and `c-backward-sws' work properly. +(defvar js2-syntactic-ws-start + "\\s \\|/[*/]\\|[\n\r]\\|\\\\[\n\r]\\|\\s!\\|<!--\\|^\\s-*-->") + +(defvar js2-syntactic-ws-end + "\\s \\|[\n\r/]\\|\\s!") + +(defvar js2-syntactic-eol + (concat "\\s *\\(/\\*[^*\n\r]*" + "\\(\\*+[^*\n\r/][^*\n\r]*\\)*" + "\\*+/\\s *\\)*" + "\\(//\\|/\\*[^*\n\r]*" + "\\(\\*+[^*\n\r/][^*\n\r]*\\)*$" + "\\|\\\\$\\|$\\)") + "Copied from java-mode. Needed for some cc-engine functions.") + +(defvar js2-comment-prefix-regexp + "//+\\|\\**") + +(defvar js2-comment-start-skip + "\\(//+\\|/\\*+\\)\\s *") + +(defvar js2-mode-verbose-parse-p js2-mode-dev-mode-p + "Non-nil to emit status messages during parsing.") + +(defvar js2-mode-functions-hidden nil "private variable") +(defvar js2-mode-comments-hidden nil "private variable") + +(defvar js2-mode-syntax-table + (let ((table (make-syntax-table))) + (c-populate-syntax-table table) + table) + "Syntax table used in js2-mode buffers.") + +(defvar js2-mode-abbrev-table nil + "Abbrev table in use in `js2-mode' buffers.") +(define-abbrev-table 'js2-mode-abbrev-table ()) + +(defvar js2-mode-must-byte-compile (not js2-mode-dev-mode-p) + "Non-nil to have `js2-mode' signal an error if not byte-compiled.") + +(defvar js2-mode-pending-parse-callbacks nil + "List of functions waiting to be notified that parse is finished.") + +(defvar js2-mode-last-indented-line -1) + +(eval-when-compile + (defvar c-paragraph-start nil) + (defvar c-paragraph-separate nil) + (defvar c-syntactic-ws-start nil) + (defvar c-syntactic-ws-end nil) + (defvar c-syntactic-eol nil) + (defvar running-xemacs nil) + (defvar font-lock-mode nil) + (defvar font-lock-keywords nil)) + +(eval-when-compile + (if (< emacs-major-version 22) + (defun c-setup-paragraph-variables () nil))) + +(provide 'js2-vars) + +;;; js2-vars.el ends here +;;; js2-util.el -- JavaScript utilities + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Code + +(eval-when-compile + (require 'cl)) + + +;; Emacs21 compatibility, plus some stuff to avoid runtime dependency on CL + +(unless (fboundp #'looking-back) + (defun looking-back (regexp &optional limit greedy) + "Return non-nil if text before point matches regular expression REGEXP. +Like `looking-at' except matches before point, and is slower. +LIMIT if non-nil speeds up the search by specifying a minimum +starting position, to avoid checking matches that would start +before LIMIT. + +If GREEDY is non-nil, extend the match backwards as far as possible, +stopping when a single additional previous character cannot be part +of a match for REGEXP." + (let ((start (point)) + (pos + (save-excursion + (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t) + (point))))) + (if (and greedy pos) + (save-restriction + (narrow-to-region (point-min) start) + (while (and (> pos (point-min)) + (save-excursion + (goto-char pos) + (backward-char 1) + (looking-at (concat "\\(?:" regexp "\\)\\'")))) + (setq pos (1- pos))) + (save-excursion + (goto-char pos) + (looking-at (concat "\\(?:" regexp "\\)\\'"))))) + (not (null pos))))) + +(unless (fboundp #'copy-overlay) + (defun copy-overlay (o) + "Return a copy of overlay O." + (let ((o1 (make-overlay (overlay-start o) (overlay-end o) + ;; FIXME: there's no easy way to find the + ;; insertion-type of the two markers. + (overlay-buffer o))) + (props (overlay-properties o))) + (while props + (overlay-put o1 (pop props) (pop props))) + o1))) + +(unless (fboundp #'remove-overlays) + (defun remove-overlays (&optional beg end name val) + "Clear BEG and END of overlays whose property NAME has value VAL. +Overlays might be moved and/or split. +BEG and END default respectively to the beginning and end of buffer." + (unless beg (setq beg (point-min))) + (unless end (setq end (point-max))) + (if (< end beg) + (setq beg (prog1 end (setq end beg)))) + (save-excursion + (dolist (o (overlays-in beg end)) + (when (eq (overlay-get o name) val) + ;; Either push this overlay outside beg...end + ;; or split it to exclude beg...end + ;; or delete it entirely (if it is contained in beg...end). + (if (< (overlay-start o) beg) + (if (> (overlay-end o) end) + (progn + (move-overlay (copy-overlay o) + (overlay-start o) beg) + (move-overlay o end (overlay-end o))) + (move-overlay o (overlay-start o) beg)) + (if (> (overlay-end o) end) + (move-overlay o end (overlay-end o)) + (delete-overlay o)))))))) + +;; we don't want a runtime dependency on the CL package, so define +;; our own versions of these functions. + +(defun js2-delete-if (predicate list) + "Remove all items satisfying PREDICATE in LIST." + (loop for item in list + if (not (funcall predicate item)) + collect item)) + +(defun js2-position (element list) + "Find 0-indexed position of ELEMENT in LIST comparing with `eq'. +Returns nil if element is not found in the list." + (let ((count 0) + found) + (while (and list (not found)) + (if (eq element (car list)) + (setq found t) + (setq count (1+ count) + list (cdr list)))) + (if found count))) + +(defun js2-find-if (predicate list) + "Find first item satisfying PREDICATE in LIST." + (let (result) + (while (and list (not result)) + (if (funcall predicate (car list)) + (setq result (car list))) + (setq list (cdr list))) + result)) + +;;; end Emacs 21 compat + +(defmacro js2-time (form) + "Evaluate FORM, discard result, and return elapsed time in sec" + (let ((beg (make-symbol "--js2-time-beg--")) + (delta (make-symbol "--js2-time-end--"))) + `(let ((,beg (current-time)) + ,delta) + ,form + (/ (truncate (* (- (float-time (current-time)) + (float-time ,beg))) + 10000) + 10000.0)))) + +(def-edebug-spec js2-time t) + +(defsubst neq (expr1 expr2) + "Return (not (eq expr1 expr2))." + (not (eq expr1 expr2))) + +(defsubst js2-same-line (pos) + "Return t if POS is on the same line as current point." + (and (>= pos (point-at-bol)) + (<= pos (point-at-eol)))) + +(defsubst js2-same-line-2 (p1 p2) + "Return t if p1 is on the same line as p2." + (save-excursion + (goto-char p1) + (js2-same-line p2))) + +(defun js2-code-bug () + "Signal an error when we encounter an unexpected code path." + (error "failed assertion")) + +;; I'd like to associate errors with nodes, but for now the +;; easiest thing to do is get the context info from the last token. +(defsubst js2-record-parse-error (msg &optional arg pos len) + (push (list (list msg arg) + (or pos js2-token-beg) + (or len (- js2-token-end js2-token-beg))) + js2-parsed-errors)) + +(defsubst js2-report-error (msg &optional msg-arg pos len) + "Signal a syntax error or record a parse error." + (if js2-recover-from-parse-errors + (js2-record-parse-error msg msg-arg pos len) + (signal 'js2-syntax-error + (list msg + js2-ts-lineno + (save-excursion + (goto-char js2-ts-cursor) + (current-column)) + js2-ts-hit-eof)))) + +(defsubst js2-report-warning (msg &optional msg-arg pos len) + (if js2-compiler-report-warning-as-error + (js2-report-error msg msg-arg pos len) + (push (list (list msg msg-arg) + (or pos js2-token-beg) + (or len (- js2-token-end js2-token-beg))) + js2-parsed-warnings))) + +(defsubst js2-add-strict-warning (msg-id &optional msg-arg beg end) + (if js2-compiler-strict-mode + (js2-report-warning msg-id msg-arg beg + (and beg end (- end beg))))) + +(put 'js2-syntax-error 'error-conditions + '(error syntax-error js2-syntax-error)) +(put 'js2-syntax-error 'error-message "Syntax error") + +(put 'js2-parse-error 'error-conditions + '(error parse-error js2-parse-error)) +(put 'js2-parse-error 'error-message "Parse error") + +(defmacro js2-clear-flag (flags flag) + `(setq ,flags (logand ,flags (lognot ,flag)))) + +(defmacro js2-set-flag (flags flag) + "Logical-or FLAG into FLAGS." + `(setq ,flags (logior ,flags ,flag))) + +(defsubst js2-flag-set-p (flags flag) + (/= 0 (logand flags flag))) + +(defsubst js2-flag-not-set-p (flags flag) + (zerop (logand flags flag))) + +;; Stolen shamelessly from James Clark's nxml-mode. +(defmacro js2-with-unmodifying-text-property-changes (&rest body) + "Evaluate BODY without any text property changes modifying the buffer. +Any text properties changes happen as usual but the changes are not treated as +modifications to the buffer." + (let ((modified (make-symbol "modified"))) + `(let ((,modified (buffer-modified-p)) + (inhibit-read-only t) + (inhibit-modification-hooks t) + (buffer-undo-list t) + (deactivate-mark nil) + ;; Apparently these avoid file locking problems. + (buffer-file-name nil) + (buffer-file-truename nil)) + (unwind-protect + (progn ,@body) + (unless ,modified + (restore-buffer-modified-p nil)))))) + +(put 'js2-with-unmodifying-text-property-changes 'lisp-indent-function 0) +(def-edebug-spec js2-with-unmodifying-text-property-changes t) + +(defmacro js2-with-underscore-as-word-syntax (&rest body) + "Evaluate BODY with the _ character set to be word-syntax." + (let ((old-syntax (make-symbol "old-syntax"))) + `(let ((,old-syntax (string (char-syntax ?_)))) + (unwind-protect + (progn + (modify-syntax-entry ?_ "w" js2-mode-syntax-table) + ,@body) + (modify-syntax-entry ?_ ,old-syntax js2-mode-syntax-table))))) + +(put 'js2-with-underscore-as-word-syntax 'lisp-indent-function 0) +(def-edebug-spec js2-with-underscore-as-word-syntax t) + +(defmacro with-buffer (buf form) + "Executes FORM in buffer BUF. +BUF can be a buffer name or a buffer object. +If the buffer doesn't exist, it's created." + `(let ((buffer (gentemp))) + (setq buffer + (if (stringp ,buf) + (get-buffer-create ,buf) + ,buf)) + (save-excursion + (set-buffer buffer) + ,form))) + +(defsubst char-is-uppercase (c) + "Return t if C is an uppercase character. +Handles unicode and latin chars properly." + (/= c (downcase c))) + +(defsubst char-is-lowercase (c) + "Return t if C is an uppercase character. +Handles unicode and latin chars properly." + (/= c (upcase c))) + +(put 'with-buffer 'lisp-indent-function 1) +(def-edebug-spec with-buffer t) + +(provide 'js2-util) + +;;; js2-util.el ends here +;;; js2-scan.el --- JavaScript scanner + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Commentary: + +;; A port of Mozilla Rhino's scanner. +;; Corresponds to Rhino files Token.java and TokenStream.java. + +;;; Code: + + +(eval-when-compile + (require 'cl)) + +(defvar js2-tokens nil + "List of all defined token names.") ; intialized below + +(defvar js2-token-names + (let* ((names (make-vector js2-num-tokens -1)) + (case-fold-search nil) ; only match js2-UPPER_CASE + (syms (apropos-internal "^js2-\\(?:[A-Z_]+\\)"))) + (loop for sym in syms + for i from 0 + do + (unless (or (memq sym '(js2-EOF_CHAR js2-ERROR)) + (not (boundp sym))) + (aset names (symbol-value sym) ; code, e.g. 152 + (substring (symbol-name sym) 4)) ; name, e.g. "LET" + (push sym js2-tokens))) + names) + "Vector mapping int values to token string names, sans `js2-' prefix.") + +(defun js2-token-name (tok) + "Return a string name for TOK, a token symbol or code. +Signals an error if it's not a recognized token." + (let ((code tok)) + (if (symbolp tok) + (setq code (symbol-value tok))) + (if (eq code -1) + "ERROR" + (if (and (numberp code) + (not (minusp code)) + (< code js2-num-tokens)) + (aref js2-token-names code) + (error "Invalid token: %s" code))))) + +(defsubst js2-token-sym (tok) + "Return symbol for TOK given its code, e.g. 'js2-LP for code 86." + (intern (js2-token-name tok))) + +(defvar js2-token-codes + (let ((table (make-hash-table :test 'eq :size 256))) + (loop for name across js2-token-names + for sym = (intern (concat "js2-" name)) + do + (puthash sym (symbol-value sym) table)) + ;; clean up a few that are "wrong" in Rhino's token codes + (puthash 'js2-DELETE js2-DELPROP table) + table) + "Hashtable mapping token symbols to their bytecodes.") + +(defsubst js2-token-code (sym) + "Return code for token symbol SYM, e.g. 86 for 'js2-LP." + (or (gethash sym js2-token-codes) + (error "Invalid token symbol: %s " sym))) ; signal code bug + +(defsubst js2-report-scan-error (msg &optional no-throw beg len) + (setq js2-token-end js2-ts-cursor) + (js2-report-error msg nil + (or beg js2-token-beg) + (or len (- js2-token-end js2-token-beg))) + (unless no-throw + (throw 'return js2-ERROR))) + +(defsubst js2-get-string-from-buffer () + "Reverse the char accumulator and return it as a string." + (setq js2-token-end js2-ts-cursor) + (if js2-ts-string-buffer + (apply #'string (nreverse js2-ts-string-buffer)) + "")) + +;; TODO: could potentially avoid a lot of consing by allocating a +;; char buffer the way Rhino does. +(defsubst js2-add-to-string (c) + (push c js2-ts-string-buffer)) + +;; Note that when we "read" the end-of-file, we advance js2-ts-cursor +;; to (1+ (point-max)), which lets the scanner treat end-of-file like +;; any other character: when it's not part of the current token, we +;; unget it, allowing it to be read again by the following call. +(defsubst js2-unget-char () + (decf js2-ts-cursor)) + +;; Rhino distinguishes \r and \n line endings. We don't need to +;; because we only scan from Emacs buffers, which always use \n. +(defsubst js2-get-char () + "Read and return the next character from the input buffer. +Increments `js2-ts-lineno' if the return value is a newline char. +Updates `js2-ts-cursor' to the point after the returned char. +Returns `js2-EOF_CHAR' if we hit the end of the buffer. +Also updates `js2-ts-hit-eof' and `js2-ts-line-start' as needed." + (let (c) + ;; check for end of buffer + (if (>= js2-ts-cursor (point-max)) + (setq js2-ts-hit-eof t + js2-ts-cursor (1+ js2-ts-cursor) + c js2-EOF_CHAR) ; return value + + ;; otherwise read next char + (setq c (char-before (incf js2-ts-cursor))) + + ;; if we read a newline, update counters + (if (= c ?\n) + (setq js2-ts-line-start js2-ts-cursor + js2-ts-lineno (1+ js2-ts-lineno))) + + ;; TODO: skip over format characters + c))) + +(defsubst js2-read-unicode-escape () + "Read a \\uNNNN sequence from the input. +Assumes the ?\ and ?u have already been read. +Returns the unicode character, or nil if it wasn't a valid character. +Doesn't change the values of any scanner variables." + ;; I really wish I knew a better way to do this, but I can't + ;; find the Emacs function that takes a 16-bit int and converts + ;; it to a Unicode/utf-8 character. So I basically eval it with (read). + ;; Have to first check that it's 4 hex characters or it may stop + ;; the read early. + (ignore-errors + (let ((s (buffer-substring-no-properties js2-ts-cursor + (+ 4 js2-ts-cursor)))) + (if (string-match "[a-zA-Z0-9]\\{4\\}" s) + (read (concat "?\\u" s)))))) + +(defsubst js2-match-char (test) + "Consume and return next character if it matches TEST, a character. +Returns nil and consumes nothing if TEST is not the next character." + (let ((c (js2-get-char))) + (if (eq c test) + t + (js2-unget-char) + nil))) + +(defsubst js2-peek-char () + (prog1 + (js2-get-char) + (js2-unget-char))) + +(defsubst js2-java-identifier-start-p (c) + (or + (memq c '(?$ ?_)) + (char-is-uppercase c) + (char-is-lowercase c))) + +(defsubst js2-java-identifier-part-p (c) + "Implementation of java.lang.Character.isJavaIdentifierPart()" + ;; TODO: make me Unicode-friendly. See comments above. + (or + (memq c '(?$ ?_)) + (char-is-uppercase c) + (char-is-lowercase c) + (and (>= c ?0) (<= c ?9)))) + +(defsubst js2-alpha-p (c) + ;; Use 'Z' < 'a' + (if (<= c ?Z) + (<= ?A c) + (and (<= ?a c) + (<= c ?z)))) + +(defsubst js2-digit-p (c) + (and (<= ?0 c) (<= c ?9))) + +(defsubst js2-js-space-p (c) + (if (<= c 127) + (memq c '(#x20 #x9 #xC #xB)) + (or + (eq c #xA0) + ;; TODO: change this nil to check for Unicode space character + nil))) + +(defsubst js2-skip-line () + "Skip to end of line" + (let (c) + (while (and (/= js2-EOF_CHAR (setq c (js2-get-char))) + (/= c ?\n))) + (js2-unget-char) + (setq js2-token-end js2-ts-cursor))) + +(defun js2-init-scanner (&optional buf line) + "Create token stream for BUF starting on LINE. +BUF defaults to current-buffer and line defaults to 1. + +A buffer can only have one scanner active at a time, which yields +dramatically simpler code than using a defstruct. If you need to +have simultaneous scanners in a buffer, copy the regions to scan +into temp buffers." + (save-excursion + (when buf + (set-buffer buf)) + (setq js2-ts-dirty-line nil + js2-ts-regexp-flags nil + js2-ts-string "" + js2-ts-number nil + js2-ts-hit-eof nil + js2-ts-line-start 0 + js2-ts-lineno (or line 1) + js2-ts-line-end-char -1 + js2-ts-cursor (point-min) + js2-ts-is-xml-attribute nil + js2-ts-xml-is-tag-content nil + js2-ts-xml-open-tags-count 0 + js2-ts-string-buffer nil))) + +;; This function uses the cached op, string and number fields in +;; TokenStream; if getToken has been called since the passed token +;; was scanned, the op or string printed may be incorrect. +(defun js2-token-to-string (token) + ;; Not sure where this function is used in Rhino. Not tested. + (if (not js2-debug-print-trees) + "" + (let ((name (js2-token-name token))) + (cond + ((memq token (list js2-STRING js2-REGEXP js2-NAME)) + (concat name " `" js2-ts-string "'")) + ((eq token js2-NUMBER) + (format "NUMBER %g" js2-ts-number)) + (t + name))))) + +(defconst js2-keywords + '(break + case catch const continue + debugger default delete do + else enum + false finally for function + if in instanceof import + let + new null + return + switch + this throw true try typeof + var void + while with + yield)) + +;; Token names aren't exactly the same as the keywords, unfortunately. +;; E.g. enum isn't in the tokens, and delete is js2-DELPROP. +(defconst js2-kwd-tokens + (let ((table (make-vector js2-num-tokens nil)) + (tokens + (list js2-BREAK + js2-CASE js2-CATCH js2-CONST js2-CONTINUE + js2-DEBUGGER js2-DEFAULT js2-DELPROP js2-DO + js2-ELSE + js2-FALSE js2-FINALLY js2-FOR js2-FUNCTION + js2-IF js2-IN js2-INSTANCEOF js2-IMPORT + js2-LET + js2-NEW js2-NULL + js2-RETURN + js2-SWITCH + js2-THIS js2-THROW js2-TRUE js2-TRY js2-TYPEOF + js2-VAR + js2-WHILE js2-WITH + js2-YIELD))) + (dolist (i tokens) + (aset table i 'font-lock-keyword-face)) + (aset table js2-STRING 'font-lock-string-face) + (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-VOID 'font-lock-constant-face) + (aset table js2-NULL 'font-lock-constant-face) + (aset table js2-TRUE 'font-lock-constant-face) + (aset table js2-FALSE 'font-lock-constant-face) + table) + "Vector whose values are non-nil for tokens that are keywords. +The values are default faces to use for highlighting the keywords.") + +(defconst js2-reserved-words + '(abstract + boolean byte + char class + double + enum extends + final float + goto + implements int interface + long + native + package private protected public + short static super synchronized + throws transient + volatile)) + +(defconst js2-keyword-names + (let ((table (make-hash-table :test 'equal))) + (loop for k in js2-keywords + do (puthash + (symbol-name k) ; instanceof + (intern (concat "js2-" + (upcase (symbol-name k)))) ; js2-INSTANCEOF + table)) + table) + "JavaScript keywords by name, mapped to their symbols.") + +(defconst js2-reserved-word-names + (let ((table (make-hash-table :test 'equal))) + (loop for k in js2-reserved-words + do + (puthash (symbol-name k) 'js2-RESERVED table)) + table) + "JavaScript reserved words by name, mapped to 'js2-RESERVED.") + +(defsubst js2-collect-string (buf) + "Convert BUF, a list of chars, to a string. +Reverses BUF before converting." + (cond + ((stringp buf) + buf) + ((null buf) ; for emacs21 compat + "") + (t + (if buf + (apply #'string (nreverse buf)) + "")))) + +(defun js2-string-to-keyword (s) + "Return token for S, a string, if S is a keyword or reserved word. +Returns a symbol such as 'js2-BREAK, or nil if not keyword/reserved." + (or (gethash s js2-keyword-names) + (gethash s js2-reserved-word-names))) + +(defsubst js2-ts-set-char-token-bounds () + "Used when next token is one character." + (setq js2-token-beg (1- js2-ts-cursor) + js2-token-end js2-ts-cursor)) + +(defsubst js2-ts-return (token) + "Return an N-character TOKEN from `js2-get-token'. +Updates `js2-token-end' accordingly." + (setq js2-token-end js2-ts-cursor) + (throw 'return token)) + +(defsubst js2-x-digit-to-int (c accumulator) + "Build up a hex number. +If C is a hexadecimal digit, return ACCUMULATOR * 16 plus +corresponding number. Otherwise return -1." + (catch 'return + (catch 'check + ;; Use 0..9 < A..Z < a..z + (cond + ((<= c ?9) + (decf c ?0) + (if (<= 0 c) + (throw 'check nil))) + ((<= c ?F) + (when (<= ?A c) + (decf c (- ?A 10)) + (throw 'check nil))) + ((<= c ?f) + (when (<= ?a c) + (decf c (- ?a 10)) + (throw 'check nil)))) + (throw 'return -1)) + (logior c (lsh accumulator 4)))) + +(defun js2-get-token () + "Return next JavaScript token, an int such as js2-RETURN." + (let (c + c1 + identifier-start + is-unicode-escape-start + contains-escape + escape-val + escape-start + str + result + base + is-integer + quote-char + val + look-for-slash + continue) + (catch 'return + (while t + ;; Eat whitespace, possibly sensitive to newlines. + (setq continue t) + (while continue + (setq c (js2-get-char)) + (cond + ((eq c js2-EOF_CHAR) + (js2-ts-set-char-token-bounds) + (throw 'return js2-EOF)) + ((eq c ?\n) + (js2-ts-set-char-token-bounds) + (setq js2-ts-dirty-line nil) + (throw 'return js2-EOL)) + ((not (js2-js-space-p c)) + (if (/= c ?-) ; in case end of HTML comment + (setq js2-ts-dirty-line t)) + (setq continue nil)))) + + ;; Assume the token will be 1 char - fixed up below. + (js2-ts-set-char-token-bounds) + + (when (eq c ?@) + (throw 'return js2-XMLATTR)) + + ;; identifier/keyword/instanceof? + ;; watch out for starting with a <backslash> + (cond + ((eq c ?\\) + (setq c (js2-get-char)) + (if (eq c ?u) + (setq identifier-start t + is-unicode-escape-start t + js2-ts-string-buffer nil) + (setq identifier-start nil) + (js2-unget-char) + (setq c ?\\))) + (t + (when (setq identifier-start (js2-java-identifier-start-p c)) + (setq js2-ts-string-buffer nil) + (js2-add-to-string c)))) + + (when identifier-start + (setq contains-escape is-unicode-escape-start) + (catch 'break + (while t + (if is-unicode-escape-start + ;; strictly speaking we should probably push-back + ;; all the bad characters if the <backslash>uXXXX + ;; sequence is malformed. But since there isn't a + ;; correct context(is there?) for a bad Unicode + ;; escape sequence in an identifier, we can report + ;; an error here. + (progn + (setq escape-val 0) + (dotimes (i 4) + (setq c (js2-get-char) + escape-val (js2-x-digit-to-int c escape-val)) + ;; Next check takes care of c < 0 and bad escape + (if (minusp escape-val) + (throw 'break nil))) + (if (minusp escape-val) + (js2-report-scan-error "msg.invalid.escape" t)) + (js2-add-to-string escape-val) + (setq is-unicode-escape-start nil)) + (setq c (js2-get-char)) + (cond + ((eq c ?\\) + (setq c (js2-get-char)) + (if (eq c ?u) + (setq is-unicode-escape-start t + contains-escape t) + (js2-report-scan-error "msg.illegal.character" t))) + (t + (if (or (eq c js2-EOF_CHAR) + (not (js2-java-identifier-part-p c))) + (throw 'break nil)) + (js2-add-to-string c)))))) + (js2-unget-char) + + (setq str (js2-get-string-from-buffer)) + (unless contains-escape + ;; OPT we shouldn't have to make a string (object!) to + ;; check if it's a keyword. + + ;; Return the corresponding token if it's a keyword + (when (setq result (js2-string-to-keyword str)) + (if (and (< js2-language-version 170) + (memq result '(js2-LET js2-YIELD))) + ;; LET and YIELD are tokens only in 1.7 and later + (setq result 'js2-NAME)) + (if (neq result js2-RESERVED) + (throw 'return (js2-token-code result))) + (js2-report-warning "msg.reserved.keyword" str))) + + ;; If we want to intern these as Rhino does, just use (intern str) + (setq js2-ts-string str) + (throw 'return js2-NAME)) ; end identifier/kwd check + + ;; is it a number? + (when (or (js2-digit-p c) + (and (eq c ?.) (js2-digit-p (js2-peek-char)))) + (setq js2-ts-string-buffer nil + base 10) + (when (eq c ?0) + (setq c (js2-get-char)) + (cond + ((or (eq c ?x) (eq c ?X)) + (setq base 16) + (setq c (js2-get-char))) + ((js2-digit-p c) + (setq base 8)) + (t + (js2-add-to-string ?0)))) + + (if (eq base 16) + (while (<= 0 (js2-x-digit-to-int c 0)) + (js2-add-to-string c) + (setq c (js2-get-char))) + (while (and (<= ?0 c) (<= c ?9)) + ;; We permit 08 and 09 as decimal numbers, which + ;; makes our behavior a superset of the ECMA + ;; numeric grammar. We might not always be so + ;; permissive, so we warn about it. + (when (and (eq base 8) (>= c ?8)) + (js2-report-warning "msg.bad.octal.literal" + (if (eq c ?8) "8" "9")) + (setq base 10)) + (js2-add-to-string c) + (setq c (js2-get-char)))) + + (setq is-integer t) + + (when (and (eq base 10) (memq c '(?. ?e ?E))) + (setq is-integer nil) + (when (eq c ?.) + (loop do + (js2-add-to-string c) + (setq c (js2-get-char)) + while (js2-digit-p c))) + (when (memq c '(?e ?E)) + (js2-add-to-string c) + (setq c (js2-get-char)) + (when (memq c '(?+ ?-)) + (js2-add-to-string c) + (setq c (js2-get-char))) + (unless (js2-digit-p c) + (js2-report-scan-error "msg.missing.exponent" t)) + (loop do + (js2-add-to-string c) + (setq c (js2-get-char)) + while (js2-digit-p c)))) + + (js2-unget-char) + (setq js2-ts-string (js2-get-string-from-buffer) + js2-ts-number + (if (and (eq base 10) (not is-integer)) + (string-to-number js2-ts-string) + ;; TODO: call runtime number-parser. Some of it is in + ;; js2-util.el, but I need to port ScriptRuntime.stringToNumber. + (string-to-number js2-ts-string))) + (throw 'return js2-NUMBER)) + + ;; is it a string? + (when (memq c '(?\" ?\')) + ;; We attempt to accumulate a string the fast way, by + ;; building it directly out of the reader. But if there + ;; are any escaped characters in the string, we revert to + ;; building it out of a string buffer. + (setq quote-char c + js2-ts-string-buffer nil + c (js2-get-char)) + (catch 'break + (while (/= c quote-char) + (catch 'continue + (when (or (eq c ?\n) (eq c js2-EOF_CHAR)) + (js2-unget-char) + (setq js2-token-end js2-ts-cursor) + (js2-report-error "msg.unterminated.string.lit") + (throw 'return js2-STRING)) + + (when (eq c ?\\) + ;; We've hit an escaped character + (setq c (js2-get-char)) + (case c + (?b (setq c ?\b)) + (?f (setq c ?\f)) + (?n (setq c ?\n)) + (?r (setq c ?\r)) + (?t (setq c ?\t)) + (?v (setq c ?\v)) + (?u + (setq c1 (js2-read-unicode-escape)) + (if js2-parse-ide-mode + (if c1 + (progn + ;; just copy the string in IDE-mode + (js2-add-to-string ?\\) + (js2-add-to-string ?u) + (dotimes (i 3) + (js2-add-to-string (js2-get-char))) + (setq c (js2-get-char))) ; added at end of loop + ;; flag it as an invalid escape + (js2-report-warning "msg.invalid.escape" + nil (- js2-ts-cursor 2) 6)) + ;; Get 4 hex digits; if the u escape is not + ;; followed by 4 hex digits, use 'u' + the + ;; literal character sequence that follows. + (js2-add-to-string ?u) + (setq escape-val 0) + (dotimes (i 4) + (setq c (js2-get-char) + escape-val (js2-x-digit-to-int c escape-val)) + (if (minusp escape-val) + (throw 'continue nil)) + (js2-add-to-string c)) + ;; prepare for replace of stored 'u' sequence by escape value + (setq js2-ts-string-buffer (nthcdr 5 js2-ts-string-buffer) + c escape-val))) + (?x + ;; Get 2 hex digits, defaulting to 'x'+literal + ;; sequence, as above. + (setq c (js2-get-char) + escape-val (js2-x-digit-to-int c 0)) + (if (minusp escape-val) + (progn + (js2-add-to-string ?x) + (throw 'continue nil)) + (setq c1 c + c (js2-get-char) + escape-val (js2-x-digit-to-int c escape-val)) + (if (minusp escape-val) + (progn + (js2-add-to-string ?x) + (js2-add-to-string c1) + (throw 'continue nil)) + ;; got 2 hex digits + (setq c escape-val)))) + (?\n + ;; Remove line terminator after escape to follow + ;; SpiderMonkey and C/C++ + (setq c (js2-get-char)) + (throw 'continue nil)) + (t + (when (and (<= ?0 c) (< c ?8)) + (setq val (- c ?0) + c (js2-get-char)) + (when (and (<= ?0 c) (< c ?8)) + (setq val (- (+ (* 8 val) c) ?0) + c (js2-get-char)) + (when (and (<= ?0 c) + (< c ?8) + (< val #o37)) + ;; c is 3rd char of octal sequence only + ;; if the resulting val <= 0377 + (setq val (- (+ (* 8 val) c) ?0) + c (js2-get-char)))) + (js2-unget-char) + (setq c val))))) + (js2-add-to-string c) + (setq c (js2-get-char))))) + (setq js2-ts-string (js2-get-string-from-buffer)) + (throw 'return js2-STRING)) + + (case c + (?\; + (throw 'return js2-SEMI)) + (?\[ + (throw 'return js2-LB)) + (?\] + (throw 'return js2-RB)) + (?{ + (throw 'return js2-LC)) + (?} + (throw 'return js2-RC)) + (?\( + (throw 'return js2-LP)) + (?\) + (throw 'return js2-RP)) + (?, + (throw 'return js2-COMMA)) + (?? + (throw 'return js2-HOOK)) + (?: + (if (js2-match-char ?:) + (js2-ts-return js2-COLONCOLON) + (throw 'return js2-COLON))) + (?. + (if (js2-match-char ?.) + (js2-ts-return js2-DOTDOT) + (if (js2-match-char ?\() + (js2-ts-return js2-DOTQUERY) + (throw 'return js2-DOT)))) + (?| + (if (js2-match-char ?|) + (throw 'return js2-OR) + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_BITOR) + (throw 'return js2-BITOR)))) + (?^ + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_BITOR) + (throw 'return js2-BITXOR))) + (?& + (if (js2-match-char ?&) + (throw 'return js2-AND) + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_BITAND) + (throw 'return js2-BITAND)))) + (?= + (if (js2-match-char ?=) + (if (js2-match-char ?=) + (js2-ts-return js2-SHEQ) + (throw 'return js2-EQ)) + (throw 'return js2-ASSIGN))) + (?! + (if (js2-match-char ?=) + (if (js2-match-char ?=) + (js2-ts-return js2-SHNE) + (js2-ts-return js2-NE)) + (throw 'return js2-NOT))) + (?< + ;; NB:treat HTML begin-comment as comment-till-eol + (when (js2-match-char ?!) + (when (js2-match-char ?-) + (when (js2-match-char ?-) + (js2-skip-line) + (setq js2-ts-comment-type 'html) + (throw 'return js2-COMMENT))) + (js2-unget-char)) + + (if (js2-match-char ?<) + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_LSH) + (js2-ts-return js2-LSH)) + (if (js2-match-char ?=) + (js2-ts-return js2-LE) + (throw 'return js2-LT)))) + (?> + (if (js2-match-char ?>) + (if (js2-match-char ?>) + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_URSH) + (js2-ts-return js2-URSH)) + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_RSH) + (js2-ts-return js2-RSH))) + (if (js2-match-char ?=) + (js2-ts-return js2-GE) + (throw 'return js2-GT)))) + (?* + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_MUL) + (throw 'return js2-MUL))) + + (?/ + ;; is it a // comment? + (when (js2-match-char ?/) + (setq js2-token-beg (- js2-ts-cursor 2)) + (js2-skip-line) + (setq js2-ts-comment-type 'line) + (throw 'return js2-COMMENT)) + + ;; is it a /* comment? + (when (js2-match-char ?*) + (setq look-for-slash nil + js2-token-beg (- js2-ts-cursor 2) + js2-ts-comment-type + (if (js2-match-char ?*) + (progn + (setq look-for-slash t) + 'jsdoc) + 'block)) + (while t + (setq c (js2-get-char)) + (cond + ((eq c js2-EOF_CHAR) + (setq js2-token-end (1- js2-ts-cursor)) + (js2-report-error "msg.unterminated.comment") + (throw 'return js2-COMMENT)) + ((eq c ?*) + (setq look-for-slash t)) + ((eq c ?/) + (if look-for-slash + (js2-ts-return js2-COMMENT))) + (t + (setq look-for-slash nil + js2-token-end js2-ts-cursor))))) + + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_DIV) + (throw 'return js2-DIV))) + + (?# + (when js2-skip-preprocessor-directives + (js2-skip-line) + (setq js2-ts-comment-type 'preprocessor + js2-token-end js2-ts-cursor) + (throw 'return js2-COMMENT)) + (throw 'return js2-ERROR)) + + (?% + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_MOD) + (throw 'return js2-MOD))) + (?~ + (throw 'return js2-BITNOT)) + (?+ + (if (js2-match-char ?=) + (js2-ts-return js2-ASSIGN_ADD) + (if (js2-match-char ?+) + (js2-ts-return js2-INC) + (throw 'return js2-ADD)))) + (?- + (cond + ((js2-match-char ?=) + (setq c js2-ASSIGN_SUB)) + ((js2-match-char ?-) + (unless js2-ts-dirty-line + ;; treat HTML end-comment after possible whitespace + ;; after line start as comment-until-eol + (when (js2-match-char ?>) + (js2-skip-line) + (setq js2-ts-comment-type 'html) + (throw 'return js2-COMMENT))) + (setq c js2-DEC)) + (t + (setq c js2-SUB))) + (setq js2-ts-dirty-line t) + (js2-ts-return c)) + + (otherwise + (js2-report-scan-error "msg.illegal.character"))))))) + +(defun js2-read-regexp (start-token) + "Called by parser when it gets / or /= in literal context." + (let (c + err + in-class ; inside a '[' .. ']' character-class + flags + (continue t)) + (setq js2-token-beg js2-ts-cursor + js2-ts-string-buffer nil + js2-ts-regexp-flags nil) + + (if (eq start-token js2-ASSIGN_DIV) + ;; mis-scanned /= + (js2-add-to-string ?=) + (if (neq start-token js2-DIV) + (error "failed assertion"))) + + (while (and (not err) + (or (/= (setq c (js2-get-char)) ?/) + in-class)) + (cond + ((or (= c ?\n) + (= c js2-EOF_CHAR)) + (setq js2-token-end (1- js2-ts-cursor) + err t + js2-ts-string (js2-collect-string js2-ts-string-buffer)) + (js2-report-error "msg.unterminated.re.lit")) + (t (cond + ((= c ?\\) + (js2-add-to-string c) + (setq c (js2-get-char))) + + ((= c ?\[) + (setq in-class t)) + + ((= c ?\]) + (setq in-class nil))) + (js2-add-to-string c)))) + + (unless err + (while continue + (cond + ((js2-match-char ?g) + (push ?g flags)) + ((js2-match-char ?i) + (push ?i flags)) + ((js2-match-char ?m) + (push ?m flags)) + (t + (setq continue nil)))) + (if (js2-alpha-p (js2-peek-char)) + (js2-report-scan-error "msg.invalid.re.flag" t + js2-ts-cursor 1)) + (setq js2-ts-string (js2-collect-string js2-ts-string-buffer) + js2-ts-regexp-flags (js2-collect-string flags) + js2-token-end js2-ts-cursor) + ;; tell `parse-partial-sexp' to ignore this range of chars + (put-text-property js2-token-beg js2-token-end 'syntax-class '(2))))) + +(defun js2-get-first-xml-token () + (setq js2-ts-xml-open-tags-count 0 + js2-ts-is-xml-attribute nil + js2-ts-xml-is-tag-content nil) + (js2-unget-char) + (js2-get-next-xml-token)) + +(defsubst js2-xml-discard-string () + "Throw away the string in progress and flag an XML parse error." + (setq js2-ts-string-buffer nil + js2-ts-string nil) + (js2-report-scan-error "msg.XML.bad.form" t)) + +(defun js2-get-next-xml-token () + (setq js2-ts-string-buffer nil ; for recording the XML + js2-token-beg js2-ts-cursor) + (let (c result) + (setq result + (catch 'return + (while t + (setq c (js2-get-char)) + (cond + ((= c js2-EOF_CHAR) + (throw 'return js2-ERROR)) + + (js2-ts-xml-is-tag-content + (case c + (?> + (js2-add-to-string c) + (setq js2-ts-xml-is-tag-content nil + js2-ts-is-xml-attribute nil)) + (?/ + (js2-add-to-string c) + (when (eq ?> (js2-peek-char)) + (setq c (js2-get-char)) + (js2-add-to-string c) + (setq js2-ts-xml-is-tag-content nil) + (decf js2-ts-xml-open-tags-count))) + (?{ + (js2-unget-char) + (setq js2-ts-string (js2-get-string-from-buffer)) + (throw 'return js2-XML)) + ((?\' ?\") + (js2-add-to-string c) + (unless (js2-read-quoted-string c) + (throw 'return js2-ERROR))) + (?= + (js2-add-to-string c) + (setq js2-ts-is-xml-attribute t)) + ((? ?\t ?\r ?\n) + (js2-add-to-string c)) + (t + (js2-add-to-string c) + (setq js2-ts-is-xml-attribute nil))) + (when (and (not js2-ts-xml-is-tag-content) + (zerop js2-ts-xml-open-tags-count)) + (setq js2-ts-string (js2-get-string-from-buffer)) + (throw 'return js2-XMLEND))) + + (t + ;; else not tag content + (case c + (?< + (js2-add-to-string c) + (setq c (js2-peek-char)) + (case c + (?! + (setq c (js2-get-char)) ;; skip ! + (js2-add-to-string c) + (setq c (js2-peek-char)) + (case c + (?- + (setq c (js2-get-char)) ;; skip - + (js2-add-to-string c) + (if (eq c ?-) + (progn + (js2-add-to-string c) + (unless (js2-read-xml-comment) + (throw 'return js2-ERROR))) + (js2-xml-discard-string) + (throw 'return js2-ERROR))) + (?\[ + (setq c (js2-get-char)) ;; skip [ + (js2-add-to-string c) + (if (and (= (js2-get-char) ?C) + (= (js2-get-char) ?D) + (= (js2-get-char) ?A) + (= (js2-get-char) ?T) + (= (js2-get-char) ?A) + (= (js2-get-char) ?\[)) + (progn + (js2-add-to-string ?C) + (js2-add-to-string ?D) + (js2-add-to-string ?A) + (js2-add-to-string ?T) + (js2-add-to-string ?A) + (js2-add-to-string ?\[) + (unless (js2-read-cdata) + (throw 'return js2-ERROR))) + (js2-xml-discard-string) + (throw 'return js2-ERROR))) + (t + (unless (js2-read-entity) + (throw 'return js2-ERROR))))) + (?? + (setq c (js2-get-char)) ;; skip ? + (js2-add-to-string c) + (unless (js2-read-PI) + (throw 'return js2-ERROR))) + (?/ + ;; end tag + (setq c (js2-get-char)) ;; skip / + (js2-add-to-string c) + (when (zerop js2-ts-xml-open-tags-count) + (js2-xml-discard-string) + (throw 'return js2-ERROR)) + (setq js2-ts-xml-is-tag-content t) + (decf js2-ts-xml-open-tags-count)) + (t + ;; start tag + (setq js2-ts-xml-is-tag-content t) + (incf js2-ts-xml-open-tags-count)))) + (?{ + (js2-unget-char) + (setq js2-ts-string (js2-get-string-from-buffer)) + (throw 'return js2-XML)) + (t + (js2-add-to-string c)))))))) + (setq js2-token-end js2-ts-cursor) + result)) + +(defun js2-read-quoted-string (quote) + (let (c) + (catch 'return + (while (/= (setq c (js2-get-char)) js2-EOF_CHAR) + (js2-add-to-string c) + (if (eq c quote) + (throw 'return t))) + (js2-xml-discard-string) ;; throw away string in progress + nil))) + +(defun js2-read-xml-comment () + (let ((c (js2-get-char))) + (catch 'return + (while (/= c js2-EOF_CHAR) + (catch 'continue + (js2-add-to-string c) + (when (and (eq c ?-) (eq ?- (js2-peek-char))) + (setq c (js2-get-char)) + (js2-add-to-string c) + (if (eq (js2-peek-char) ?>) + (progn + (setq c (js2-get-char)) ;; skip > + (js2-add-to-string c) + (throw 'return t)) + (throw 'continue nil))) + (setq c (js2-get-char)))) + (js2-xml-discard-string) + nil))) + +(defun js2-read-cdata () + (let ((c (js2-get-char))) + (catch 'return + (while (/= c js2-EOF_CHAR) + (catch 'continue + (js2-add-to-string c) + (when (and (eq c ?\]) (eq (js2-peek-char) ?\])) + (setq c (js2-get-char)) + (js2-add-to-string c) + (if (eq (js2-peek-char) ?>) + (progn + (setq c (js2-get-char)) ;; Skip > + (js2-add-to-string c) + (throw 'return t)) + (throw 'continue nil))) + (setq c (js2-get-char)))) + (js2-xml-discard-string) + nil))) + +(defun js2-read-entity () + (let ((decl-tags 1) + c) + (catch 'return + (while (/= js2-EOF_CHAR (setq c (js2-get-char))) + (js2-add-to-string c) + (case c + (?< + (incf decl-tags)) + (?> + (decf decl-tags) + (if (zerop decl-tags) + (throw 'return t))))) + (js2-xml-discard-string) + nil))) + +(defun js2-read-PI () + "Scan an XML processing instruction." + (let (c) + (catch 'return + (while (/= js2-EOF_CHAR (setq c (js2-get-char))) + (js2-add-to-string c) + (when (and (eq c ??) (eq (js2-peek-char) ?>)) + (setq c (js2-get-char)) ;; Skip > + (js2-add-to-string c) + (throw 'return t))) + (js2-xml-discard-string) + nil))) + +(defun js2-scanner-get-line () + "Return the text of the current scan line." + (buffer-substring (point-at-bol) (point-at-eol))) + +(provide 'js2-scan) + +;;; js2-scan.el ends here +;;; js2-messages: localizable messages for js2-mode + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Commentary: + +;; Messages are copied from Rhino's Messages.properties. +;; Many of the Java-specific messages have been elided. +;; Add any js2-specific ones at the end, so we can keep +;; this file synced with changes to Rhino's. +;; +;; TODO: +;; - move interpreter messages into separate file + +;;; Code: + +(defvar js2-message-table + (make-hash-table :test 'equal :size 250) + "Contains localized messages for js2-mode.") + +;; TODO: construct this hashtable at compile-time. +(defmacro js2-msg (key &rest strings) + `(puthash ,key (funcall #'concat ,@strings) + js2-message-table)) + +(defun js2-get-msg (msg-key) + "Look up a localized message. +MSG-KEY is a list of (MSG ARGS). If the message takes parameters, +the correct number of ARGS must be provided." + (let* ((key (if (listp msg-key) (car msg-key) msg-key)) + (args (if (listp msg-key) (cdr msg-key))) + (msg (gethash key js2-message-table))) + (if msg + (apply #'format msg args) + key))) ; default to showing the key + +(js2-msg "msg.dup.parms" + "Duplicate parameter name '%s'.") + +(js2-msg "msg.too.big.jump" + "Program too complex: jump offset too big.") + +(js2-msg "msg.too.big.index" + "Program too complex: internal index exceeds 64K limit.") + +(js2-msg "msg.while.compiling.fn" + "Encountered code generation error while compiling function '%s': %s") + +(js2-msg "msg.while.compiling.script" + "Encountered code generation error while compiling script: %s") + +;; Context +(js2-msg "msg.ctor.not.found" + "Constructor for '%s' not found.") + +(js2-msg "msg.not.ctor" + "'%s' is not a constructor.") + +;; FunctionObject +(js2-msg "msg.varargs.ctor" + "Method or constructor '%s' must be static " + "with the signature (Context cx, Object[] args, " + "Function ctorObj, boolean inNewExpr) " + "to define a variable arguments constructor.") + +(js2-msg "msg.varargs.fun" + "Method '%s' must be static with the signature " + "(Context cx, Scriptable thisObj, Object[] args, Function funObj) " + "to define a variable arguments function.") + +(js2-msg "msg.incompat.call" + "Method '%s' called on incompatible object.") + +(js2-msg "msg.bad.parms" + "Unsupported parameter type '%s' in method '%s'.") + +(js2-msg "msg.bad.method.return" + "Unsupported return type '%s' in method '%s'.") + +(js2-msg "msg.bad.ctor.return" + "Construction of objects of type '%s' is not supported.") + +(js2-msg "msg.no.overload" + "Method '%s' occurs multiple times in class '%s'.") + +(js2-msg "msg.method.not.found" + "Method '%s' not found in '%s'.") + +;; IRFactory + +(js2-msg "msg.bad.for.in.lhs" + "Invalid left-hand side of for..in loop.") + +(js2-msg "msg.mult.index" + "Only one variable allowed in for..in loop.") + +(js2-msg "msg.bad.for.in.destruct" + "Left hand side of for..in loop must be an array of " + "length 2 to accept key/value pair.") + +(js2-msg "msg.cant.convert" + "Can't convert to type '%s'.") + +(js2-msg "msg.bad.assign.left" + "Invalid assignment left-hand side.") + +(js2-msg "msg.bad.decr" + "Invalid decerement operand.") + +(js2-msg "msg.bad.incr" + "Invalid increment operand.") + +(js2-msg "msg.bad.yield" + "yield must be in a function.") + +(js2-msg "msg.yield.parenthesized" + "yield expression must be parenthesized.") + +;; NativeGlobal +(js2-msg "msg.cant.call.indirect" + "Function '%s' must be called directly, and not by way of a " + "function of another name.") + +(js2-msg "msg.eval.nonstring" + "Calling eval() with anything other than a primitive " + "string value will simply return the value. " + "Is this what you intended?") + +(js2-msg "msg.eval.nonstring.strict" + "Calling eval() with anything other than a primitive " + "string value is not allowed in strict mode.") + +(js2-msg "msg.bad.destruct.op" + "Invalid destructuring assignment operator") + +;; NativeCall +(js2-msg "msg.only.from.new" + "'%s' may only be invoked from a `new' expression.") + +(js2-msg "msg.deprec.ctor" + "The '%s' constructor is deprecated.") + +;; NativeFunction +(js2-msg "msg.no.function.ref.found" + "no source found to decompile function reference %s") + +(js2-msg "msg.arg.isnt.array" + "second argument to Function.prototype.apply must be an array") + +;; NativeGlobal +(js2-msg "msg.bad.esc.mask" + "invalid string escape mask") + +;; NativeRegExp +(js2-msg "msg.bad.quant" + "Invalid quantifier %s") + +(js2-msg "msg.overlarge.backref" + "Overly large back reference %s") + +(js2-msg "msg.overlarge.min" + "Overly large minimum %s") + +(js2-msg "msg.overlarge.max" + "Overly large maximum %s") + +(js2-msg "msg.zero.quant" + "Zero quantifier %s") + +(js2-msg "msg.max.lt.min" + "Maximum %s less than minimum") + +(js2-msg "msg.unterm.quant" + "Unterminated quantifier %s") + +(js2-msg "msg.unterm.paren" + "Unterminated parenthetical %s") + +(js2-msg "msg.unterm.class" + "Unterminated character class %s") + +(js2-msg "msg.bad.range" + "Invalid range in character class.") + +(js2-msg "msg.trail.backslash" + "Trailing \\ in regular expression.") + +(js2-msg "msg.re.unmatched.right.paren" + "unmatched ) in regular expression.") + +(js2-msg "msg.no.regexp" + "Regular expressions are not available.") + +(js2-msg "msg.bad.backref" + "back-reference exceeds number of capturing parentheses.") + +(js2-msg "msg.bad.regexp.compile" + "Only one argument may be specified if the first " + "argument to RegExp.prototype.compile is a RegExp object.") + +;; Parser +(js2-msg "msg.got.syntax.errors" + "Compilation produced %s syntax errors.") + +(js2-msg "msg.var.redecl" + "TypeError: redeclaration of var %s.") + +(js2-msg "msg.const.redecl" + "TypeError: redeclaration of const %s.") + +(js2-msg "msg.let.redecl" + "TypeError: redeclaration of variable %s.") + +(js2-msg "msg.parm.redecl" + "TypeError: redeclaration of formal parameter %s.") + +(js2-msg "msg.fn.redecl" + "TypeError: redeclaration of function %s.") + +(js2-msg "msg.let.decl.not.in.block" + "SyntaxError: let declaration not directly within block") + +;; NodeTransformer +(js2-msg "msg.dup.label" + "duplicated label") + +(js2-msg "msg.undef.label" + "undefined label") + +(js2-msg "msg.bad.break" + "unlabelled break must be inside loop or switch") + +(js2-msg "msg.continue.outside" + "continue must be inside loop") + +(js2-msg "msg.continue.nonloop" + "continue can only use labels of iteration statements") + +(js2-msg "msg.bad.throw.eol" + "Line terminator is not allowed between the throw " + "keyword and throw expression.") + +(js2-msg "msg.no.paren.parms" + "missing ( before function parameters.") + +(js2-msg "msg.no.parm" + "missing formal parameter") + +(js2-msg "msg.no.paren.after.parms" + "missing ) after formal parameters") + +(js2-msg "msg.no.brace.body" + "missing '{' before function body") + +(js2-msg "msg.no.brace.after.body" + "missing } after function body") + +(js2-msg "msg.no.paren.cond" + "missing ( before condition") + +(js2-msg "msg.no.paren.after.cond" + "missing ) after condition") + +(js2-msg "msg.no.semi.stmt" + "missing ; before statement") + +(js2-msg "msg.missing.semi" + "missing ; after statement") + +(js2-msg "msg.no.name.after.dot" + "missing name after . operator") + +(js2-msg "msg.no.name.after.coloncolon" + "missing name after :: operator") + +(js2-msg "msg.no.name.after.dotdot" + "missing name after .. operator") + +(js2-msg "msg.no.name.after.xmlAttr" + "missing name after .@") + +(js2-msg "msg.no.bracket.index" + "missing ] in index expression") + +(js2-msg "msg.no.paren.switch" + "missing ( before switch expression") + +(js2-msg "msg.no.paren.after.switch" + "missing ) after switch expression") + +(js2-msg "msg.no.brace.switch" + "missing '{' before switch body") + +(js2-msg "msg.bad.switch" + "invalid switch statement") + +(js2-msg "msg.no.colon.case" + "missing : after case expression") + +(js2-msg "msg.double.switch.default" + "double default label in the switch statement") + +(js2-msg "msg.no.while.do" + "missing while after do-loop body") + +(js2-msg "msg.no.paren.for" + "missing ( after for") + +(js2-msg "msg.no.semi.for" + "missing ; after for-loop initializer") + +(js2-msg "msg.no.semi.for.cond" + "missing ; after for-loop condition") + +(js2-msg "msg.in.after.for.name" + "missing in after for") + +(js2-msg "msg.no.paren.for.ctrl" + "missing ) after for-loop control") + +(js2-msg "msg.no.paren.with" + "missing ( before with-statement object") + +(js2-msg "msg.no.paren.after.with" + "missing ) after with-statement object") + +(js2-msg "msg.no.paren.after.let" + "missing ( after let") + +(js2-msg "msg.no.paren.let" + "missing ) after variable list") + +(js2-msg "msg.no.curly.let" + "missing } after let statement") + +(js2-msg "msg.bad.return" + "invalid return") + +(js2-msg "msg.no.brace.block" + "missing } in compound statement") + +(js2-msg "msg.bad.label" + "invalid label") + +(js2-msg "msg.bad.var" + "missing variable name") + +(js2-msg "msg.bad.var.init" + "invalid variable initialization") + +(js2-msg "msg.no.colon.cond" + "missing : in conditional expression") + +(js2-msg "msg.no.paren.arg" + "missing ) after argument list") + +(js2-msg "msg.no.bracket.arg" + "missing ] after element list") + +(js2-msg "msg.bad.prop" + "invalid property id") + +(js2-msg "msg.no.colon.prop" + "missing : after property id") + +(js2-msg "msg.no.brace.prop" + "missing } after property list") + +(js2-msg "msg.no.paren" + "missing ) in parenthetical") + +(js2-msg "msg.reserved.id" + "identifier is a reserved word") + +(js2-msg "msg.no.paren.catch" + "missing ( before catch-block condition") + +(js2-msg "msg.bad.catchcond" + "invalid catch block condition") + +(js2-msg "msg.catch.unreachable" + "any catch clauses following an unqualified catch are unreachable") + +(js2-msg "msg.no.brace.try" + "missing '{' before try block") + +(js2-msg "msg.no.brace.catchblock" + "missing '{' before catch-block body") + +(js2-msg "msg.try.no.catchfinally" + "'try' without 'catch' or 'finally'") + +(js2-msg "msg.no.return.value" + "function %s does not always return a value") + +(js2-msg "msg.anon.no.return.value" + "anonymous function does not always return a value") + +(js2-msg "msg.return.inconsistent" + "return statement is inconsistent with previous usage") + +(js2-msg "msg.generator.returns" + "TypeError: generator function '%s' returns a value") + +(js2-msg "msg.anon.generator.returns" + "TypeError: anonymous generator function returns a value") + +(js2-msg "msg.syntax" + "syntax error") + +(js2-msg "msg.unexpected.eof" + "Unexpected end of file") + +(js2-msg "msg.XML.bad.form" + "illegally formed XML syntax") + +(js2-msg "msg.XML.not.available" + "XML runtime not available") + +(js2-msg "msg.too.deep.parser.recursion" + "Too deep recursion while parsing") + +(js2-msg "msg.no.side.effects" + "Code has no side effects") + +(js2-msg "msg.extra.trailing.comma" + "Trailing comma is not legal in an ECMA-262 object initializer") + +(js2-msg "msg.array.trailing.comma" + "Trailing comma yields different behavior across browsers") + +(js2-msg "msg.equal.as.assign" + (concat "Test for equality (==) mistyped as assignment (=)?" + " (parenthesize to suppress warning)")) + +(js2-msg "msg.var.hides.arg" + "Variable %s hides argument") + +(js2-msg "msg.destruct.assign.no.init" + "Missing = in destructuring declaration") + +;; ScriptRuntime +(js2-msg "msg.no.properties" + "%s has no properties.") + +(js2-msg "msg.invalid.iterator" + "Invalid iterator value") + +(js2-msg "msg.iterator.primitive" + "__iterator__ returned a primitive value") + +(js2-msg "msg.assn.create.strict" + "Assignment to undeclared variable %s") + +(js2-msg "msg.ref.undefined.prop" + "Reference to undefined property '%s'") + +(js2-msg "msg.prop.not.found" + "Property %s not found.") + +(js2-msg "msg.invalid.type" + "Invalid JavaScript value of type %s") + +(js2-msg "msg.primitive.expected" + "Primitive type expected (had %s instead)") + +(js2-msg "msg.namespace.expected" + "Namespace object expected to left of :: (found %s instead)") + +(js2-msg "msg.null.to.object" + "Cannot convert null to an object.") + +(js2-msg "msg.undef.to.object" + "Cannot convert undefined to an object.") + +(js2-msg "msg.cyclic.value" + "Cyclic %s value not allowed.") + +(js2-msg "msg.is.not.defined" + "'%s' is not defined.") + +(js2-msg "msg.undef.prop.read" + "Cannot read property '%s' from %s") + +(js2-msg "msg.undef.prop.write" + "Cannot set property '%s' of %s to '%s'") + +(js2-msg "msg.undef.prop.delete" + "Cannot delete property '%s' of %s") + +(js2-msg "msg.undef.method.call" + "Cannot call method '%s' of %s") + +(js2-msg "msg.undef.with" + "Cannot apply 'with' to %s") + +(js2-msg "msg.isnt.function" + "%s is not a function, it is %s.") + +(js2-msg "msg.isnt.function.in" + "Cannot call property %s in object %s. " + "It is not a function, it is '%s'.") + +(js2-msg "msg.function.not.found" + "Cannot find function %s.") + +(js2-msg "msg.function.not.found.in" + "Cannot find function %s in object %s.") + +(js2-msg "msg.isnt.xml.object" + "%s is not an xml object.") + +(js2-msg "msg.no.ref.to.get" + "%s is not a reference to read reference value.") + +(js2-msg "msg.no.ref.to.set" + "%s is not a reference to set reference value to %s.") + +(js2-msg "msg.no.ref.from.function" + "Function %s can not be used as the left-hand " + "side of assignment or as an operand of ++ or -- operator.") + +(js2-msg "msg.bad.default.value" + "Object's getDefaultValue() method returned an object.") + +(js2-msg "msg.instanceof.not.object" + "Can't use instanceof on a non-object.") + +(js2-msg "msg.instanceof.bad.prototype" + "'prototype' property of %s is not an object.") + +(js2-msg "msg.bad.radix" + "illegal radix %s.") + +;; ScriptableObject +(js2-msg "msg.default.value" + "Cannot find default value for object.") + +(js2-msg "msg.zero.arg.ctor" + "Cannot load class '%s' which has no zero-parameter constructor.") + +(js2-msg "msg.ctor.multiple.parms" + "Can't define constructor or class %s since more than " + "one constructor has multiple parameters.") + +(js2-msg "msg.extend.scriptable" + "%s must extend ScriptableObject in order to define property %s.") + +(js2-msg "msg.bad.getter.parms" + "In order to define a property, getter %s must have zero " + "parameters or a single ScriptableObject parameter.") + +(js2-msg "msg.obj.getter.parms" + "Expected static or delegated getter %s to take " + "a ScriptableObject parameter.") + +(js2-msg "msg.getter.static" + "Getter and setter must both be static or neither be static.") + +(js2-msg "msg.setter.return" + "Setter must have void return type: %s") + +(js2-msg "msg.setter2.parms" + "Two-parameter setter must take a ScriptableObject as " + "its first parameter.") + +(js2-msg "msg.setter1.parms" + "Expected single parameter setter for %s") + +(js2-msg "msg.setter2.expected" + "Expected static or delegated setter %s to take two parameters.") + +(js2-msg "msg.setter.parms" + "Expected either one or two parameters for setter.") + +(js2-msg "msg.setter.bad.type" + "Unsupported parameter type '%s' in setter '%s'.") + +(js2-msg "msg.add.sealed" + "Cannot add a property to a sealed object: %s.") + +(js2-msg "msg.remove.sealed" + "Cannot remove a property from a sealed object: %s.") + +(js2-msg "msg.modify.sealed" + "Cannot modify a property of a sealed object: %s.") + +(js2-msg "msg.modify.readonly" + "Cannot modify readonly property: %s.") + +;; TokenStream +(js2-msg "msg.missing.exponent" + "missing exponent") + +(js2-msg "msg.caught.nfe" + "number format error") + +(js2-msg "msg.unterminated.string.lit" + "unterminated string literal") + +(js2-msg "msg.unterminated.comment" + "unterminated comment") + +(js2-msg "msg.unterminated.re.lit" + "unterminated regular expression literal") + +(js2-msg "msg.invalid.re.flag" + "invalid flag after regular expression") + +(js2-msg "msg.no.re.input.for" + "no input for %s") + +(js2-msg "msg.illegal.character" + "illegal character") + +(js2-msg "msg.invalid.escape" + "invalid Unicode escape sequence") + +(js2-msg "msg.bad.namespace" + "not a valid default namespace statement. " + "Syntax is: default xml namespace = EXPRESSION;") + +;; TokensStream warnings +(js2-msg "msg.bad.octal.literal" + "illegal octal literal digit %s; " + "interpreting it as a decimal digit") + +(js2-msg "msg.reserved.keyword" + "illegal usage of future reserved keyword %s; " + "interpreting it as ordinary identifier") + +(js2-msg "msg.script.is.not.constructor" + "Script objects are not constructors.") + +;; Arrays +(js2-msg "msg.arraylength.bad" + "Inappropriate array length.") + +;; Arrays +(js2-msg "msg.arraylength.too.big" + "Array length %s exceeds supported capacity limit.") + +;; URI +(js2-msg "msg.bad.uri" + "Malformed URI sequence.") + +;; Number +(js2-msg "msg.bad.precision" + "Precision %s out of range.") + +;; NativeGenerator +(js2-msg "msg.send.newborn" + "Attempt to send value to newborn generator") + +(js2-msg "msg.already.exec.gen" + "Already executing generator") + +(js2-msg "msg.StopIteration.invalid" + "StopIteration may not be changed to an arbitrary object.") + +;; Interpreter +(js2-msg "msg.yield.closing" + "Yield from closing generator") + +(provide 'js2-messages) +;;; js2-ast.el --- JavaScript syntax tree node definitions + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Code: + +(eval-and-compile + (require 'cl)) + + +;; flags for ast node property 'member-type (used for e4x operators) +(defvar js2-property-flag #x1 "property access: element is valid name") +(defvar js2-attribute-flag #x2 "x.@y or x..@y") +(defvar js2-descendants-flag #x4 "x..y or x..@i") + +(defsubst js2-relpos (pos anchor) + "Convert POS to be relative to ANCHOR. +If POS is nil, returns nil." + (and pos (- pos anchor))) + +(defsubst js2-make-pad (indent) + (if (zerop indent) + "" + (make-string (* indent js2-basic-offset) ? ))) + +(defsubst js2-visit-ast (node callback) + "Visit every node in ast NODE with visitor CALLBACK. + +CALLBACK is a function that takes two arguments: (NODE END-P). It is +called twice: once to visit the node, and again after all the node's +children have been processed. The END-P argument is nil on the first +call and non-nil on the second call. The return value of the callback +affects the traversal: if non-nil, the children of NODE are processed. +If the callback returns nil, or if the node has no children, then the +callback is called immediately with a non-nil END-P argument. + +The node traversal is approximately lexical-order, although there +are currently no guarantees around this." + (let ((vfunc (get (aref node 0) 'js2-visitor))) + ;; visit the node + (when (funcall callback node nil) + ;; visit the kids + (cond + ((eq vfunc 'js2-visit-none) + nil) ; don't even bother calling it + ;; Each AST node type has to define a `js2-visitor' function + ;; that takes a node and a callback, and calls `js2-visit-ast' + ;; on each child of the node. + (vfunc + (funcall vfunc node callback)) + (t + (error "%s does not define a visitor-traversal function" + (aref node 0))))) + ;; call the end-visit + (funcall callback node t))) + +(defstruct (js2-node + (:constructor nil)) ; abstract + "Base AST node type." + (type -1) ; token type + (pos -1) ; start position of this AST node in parsed input + (len 1) ; num characters spanned by the node + props ; optional node property list (an alist) + parent) ; link to parent node; null for root + +(defsubst js2-node-get-prop (node prop &optional default) + (or (cadr (assoc prop (js2-node-props node))) default)) + +(defsubst js2-node-set-prop (node prop value) + (setf (js2-node-props node) + (cons (list prop value) (js2-node-props node)))) + +(defsubst js2-fixup-starts (n nodes) + "Adjust the start positions of NODES to be relative to N. +Any node in the list may be nil, for convenience." + (dolist (node nodes) + (when node + (setf (js2-node-pos node) (- (js2-node-pos node) + (js2-node-pos n)))))) + +(defsubst js2-node-add-children (parent &rest nodes) + "Set parent node of NODES to PARENT, and return PARENT. +Does nothing if we're not recording parent links. +If any given node in NODES is nil, doesn't record that link." + (js2-fixup-starts parent nodes) + (dolist (node nodes) + (and node + (setf (js2-node-parent node) parent)))) + +;; Non-recursive since it's called a frightening number of times. +(defsubst js2-node-abs-pos (n) + (let ((pos (js2-node-pos n))) + (while (setq n (js2-node-parent n)) + (setq pos (+ pos (js2-node-pos n)))) + pos)) + +(defsubst js2-node-abs-end (n) + "Return absolute buffer position of end of N." + (+ (js2-node-abs-pos n) (js2-node-len n))) + +;; It's important to make sure block nodes have a lisp list for the +;; child nodes, to limit printing recursion depth in an AST that +;; otherwise consists of defstruct vectors. Emacs will crash printing +;; a sufficiently large vector tree. + +(defstruct (js2-block-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-block-node (&key (type js2-BLOCK) + (pos js2-token-beg) + len + props + kids))) + "A block of statements." + kids) ; a lisp list of the child statement nodes + +(put 'cl-struct-js2-block-node 'js2-visitor 'js2-visit-block) +(put 'cl-struct-js2-block-node 'js2-printer 'js2-print-block) + +(defsubst js2-visit-block (ast callback) + "Visit the `js2-block-node' children of AST." + (dolist (kid (js2-block-node-kids ast)) + (js2-visit-ast kid callback))) + +(defun js2-print-block (n i) + (let ((pad (js2-make-pad i))) + (insert pad "{\n") + (dolist (kid (js2-block-node-kids n)) + (js2-print-ast kid (1+ i))) + (insert pad "}"))) + +(defstruct (js2-scope + (:include js2-block-node) + (:constructor nil) + (:constructor make-js2-scope (&key (type js2-BLOCK) + (pos js2-token-beg) + len + kids))) + ;; The symbol-table is a LinkedHashMap<String,Symbol> in Rhino. + ;; I don't have one of those handy, so I'll use an alist for now. + ;; It's as fast as an emacs hashtable for up to about 50 elements, + ;; and is much lighter-weight to construct (both CPU and mem). + ;; The keys are interned strings (symbols) for faster lookup. + ;; Should switch to hybrid alist/hashtable eventually. + symbol-table ; an alist of (symbol . js2-symbol) + parent-scope ; a `js2-scope' + top) ; top-level `js2-scope' (script/function) + +(put 'cl-struct-js2-scope 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-scope 'js2-printer 'js2-print-none) + +(defun js2-scope-set-parent-scope (scope parent) + (setf (js2-scope-parent-scope scope) parent + (js2-scope-top scope) (if (null parent) + scope + (js2-scope-top parent)))) + +(defun js2-node-get-enclosing-scope (node) + "Return the innermost `js2-scope' node surrounding NODE. +Returns nil if there is no enclosing scope node." + (let ((parent (js2-node-parent node))) + (while (not (js2-scope-p parent)) + (setq parent (js2-node-parent parent))) + parent)) + +(defun js2-get-defining-scope (scope name) + "Search up scope chain from SCOPE looking for NAME, a string or symbol. +Returns `js2-scope' in which NAME is defined, or nil if not found." + (let ((sym (if (symbolp name) + name + (intern name))) + table + result + (continue t)) + (while (and scope continue) + (if (and (setq table (js2-scope-symbol-table scope)) + (assq sym table)) + (setq continue nil + result scope) + (setq scope (js2-scope-parent-scope scope)))) + result)) + +(defsubst js2-scope-get-symbol (scope name) + "Return symbol table entry for NAME in SCOPE. +NAME can be a string or symbol. Returns a `js2-symbol' or nil if not found." + (and (js2-scope-symbol-table scope) + (cdr (assq (if (symbolp name) + name + (intern name)) + (js2-scope-symbol-table scope))))) + +(defsubst js2-scope-put-symbol (scope name symbol) + "Enter SYMBOL into symbol-table for SCOPE under NAME. +NAME can be a lisp symbol or string. SYMBOL is a `js2-symbol'." + (let* ((table (js2-scope-symbol-table scope)) + (sym (if (symbolp name) name (intern name))) + (entry (assq sym table))) + (if entry + (setcdr entry symbol) + (push (cons sym symbol) + (js2-scope-symbol-table scope))))) + +(defstruct (js2-symbol + (:constructor nil) + (:constructor make-js2-symbol (decl-type name &optional ast-node))) + "A symbol table entry." + ;; One of js2-FUNCTION, js2-LP (for parameters), js2-VAR, + ;; js2-LET, or js2-CONST + decl-type + name ; string + ast-node) ; a `js2-node' + +(defstruct (js2-error-node + (:include js2-node) + (:constructor nil) ; silence emacs21 byte-compiler + (:constructor make-js2-error-node (&key (type js2-ERROR) + (pos js2-token-beg) + len))) + "AST node representing a parse error.") + +(put 'cl-struct-js2-error-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-error-node 'js2-printer 'js2-print-none) + +(defstruct (js2-script-node + (:include js2-scope) + (:constructor nil) + (:constructor make-js2-script-node (&key (type js2-SCRIPT) + (pos js2-token-beg) + len + var-decls + fun-decls))) + functions ; lisp list of nested functions + regexps ; lisp list of (string . flags) + symbols ; alist (every symbol gets unique index) + (param-count 0) + var-names ; vector of string names + consts ; bool-vector matching var-decls + (temp-number 0)) ; for generating temp variables + +(put 'cl-struct-js2-script-node 'js2-visitor 'js2-visit-block) +(put 'cl-struct-js2-script-node 'js2-printer 'js2-print-script) + +(defun js2-print-script (node indent) + (dolist (kid (js2-block-node-kids node)) + (js2-print-ast kid indent))) + +(defstruct (js2-ast-root + (:include js2-script-node) + (:constructor nil) + (:constructor make-js2-ast-root (&key (type js2-SCRIPT) + (pos js2-token-beg) + 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 + +(put 'cl-struct-js2-ast-root 'js2-visitor 'js2-visit-ast-root) +(put 'cl-struct-js2-ast-root 'js2-printer 'js2-print-script) + +(defun js2-visit-ast-root (ast callback) + (dolist (kid (js2-ast-root-kids ast)) + (js2-visit-ast kid callback)) + (dolist (comment (js2-ast-root-comments ast)) + (js2-visit-ast comment callback))) + +(defstruct (js2-comment-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-comment-node (&key (type js2-COMMENT) + (pos js2-token-beg) + len + (format js2-ts-comment-type)))) + format) ; 'line, 'block, 'jsdoc or 'html + +(put 'cl-struct-js2-comment-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-comment-node 'js2-printer 'js2-print-comment) + +(defun js2-print-comment (n i) + ;; We really ought to link end-of-line comments to their nodes. + ;; Or maybe we could add a new comment type, 'endline. + (insert (js2-make-pad i) + (js2-node-string n))) + +(defstruct (js2-expr-stmt-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-expr-stmt-node (&key (type js2-EXPR_VOID) + (pos js2-ts-cursor) + len + expr))) + "An expression statement." + expr) + +(defsubst js2-expr-stmt-node-set-has-result (node) + "Change the node type to `js2-EXPR_RESULT'. Used for code generation." + (setf (js2-node-type node) js2-EXPR_RESULT)) + +(put 'cl-struct-js2-expr-stmt-node 'js2-visitor 'js2-visit-expr-stmt-node) +(put 'cl-struct-js2-expr-stmt-node 'js2-printer 'js2-print-expr-stmt-node) + +(defun js2-visit-expr-stmt-node (n v) + (js2-visit-ast (js2-expr-stmt-node-expr n) v)) + +(defun js2-print-expr-stmt-node (n indent) + (js2-print-ast (js2-expr-stmt-node-expr n) indent) + (insert ";\n")) + +(defstruct (js2-loop-node + (:include js2-scope) + (:constructor nil)) + "Abstract supertype of loop nodes." + body ; a `js2-block-node' + lp ; position of left-paren, nil if omitted + rp) ; position of right-paren, nil if omitted + +(defstruct (js2-do-node + (:include js2-loop-node) + (:constructor nil) + (:constructor make-js2-do-node (&key (type js2-DO) + (pos js2-token-beg) + len + body + condition + while-pos + lp + rp))) + "AST node for do-loop." + condition ; while (expression) + while-pos) ; buffer position of 'while' keyword + +(put 'cl-struct-js2-do-node 'js2-visitor 'js2-visit-do-node) +(put 'cl-struct-js2-do-node 'js2-printer 'js2-print-do-node) + +(defun js2-visit-do-node (n v) + (js2-visit-ast (js2-do-node-body n) v) + (js2-visit-ast (js2-do-node-condition n) v)) + +(defun js2-print-do-node (n i) + (let ((pad (js2-make-pad i))) + (insert pad "do {\n") + (dolist (kid (js2-block-node-kids (js2-do-node-body n))) + (js2-print-ast kid (1+ i))) + (insert pad "} while (") + (js2-print-ast (js2-do-node-condition n) 0) + (insert ");\n"))) + +(defstruct (js2-while-node + (:include js2-loop-node) + (:constructor nil) + (:constructor make-js2-while-node (&key (type js2-WHILE) + (pos js2-token-beg) + len + body + condition + lp + rp))) + "AST node for while-loop." + condition) ; while-condition + +(put 'cl-struct-js2-while-node 'js2-visitor 'js2-visit-while-node) +(put 'cl-struct-js2-while-node 'js2-printer 'js2-print-while-node) + +(defun js2-visit-while-node (n v) + (js2-visit-ast (js2-while-node-condition n) v) + (js2-visit-ast (js2-while-node-body n) v)) + +(defun js2-print-while-node (n i) + (let ((pad (js2-make-pad i))) + (insert pad "while (") + (js2-print-ast (js2-while-node-condition n) 0) + (insert ") {\n") + (js2-print-body (js2-while-node-body n) (1+ i)) + (insert pad "}\n"))) + +(defstruct (js2-for-node + (:include js2-loop-node) + (:constructor nil) + (:constructor make-js2-for-node (&key (type js2-FOR) + (pos js2-ts-cursor) + len + body + init + condition + update + lp + rp))) + "AST node for a C-style for-loop." + init ; initialization expression + condition ; loop condition + update) ; update clause + +(put 'cl-struct-js2-for-node 'js2-visitor 'js2-visit-for-node) +(put 'cl-struct-js2-for-node 'js2-printer 'js2-print-for-node) + +(defun js2-visit-for-node (n v) + (js2-visit-ast (js2-for-node-init n) v) + (js2-visit-ast (js2-for-node-condition n) v) + (js2-visit-ast (js2-for-node-update n) v) + (js2-visit-ast (js2-for-node-body n) v)) + +(defun js2-print-for-node (n i) + (let ((pad (js2-make-pad i))) + (insert pad "for (") + (js2-print-ast (js2-for-node-init n) 0) + (insert "; ") + (js2-print-ast (js2-for-node-condition n) 0) + (insert "; ") + (js2-print-ast (js2-for-node-update n) 0) + (insert ") {\n") + (js2-print-body (js2-for-node-body n) (1+ i)) + (insert pad "}\n"))) + +(defstruct (js2-for-in-node + (:include js2-loop-node) + (:constructor nil) + (:constructor make-js2-for-in-node (&key (type js2-FOR) + (pos js2-ts-cursor) + len + body + iterator + object + in-pos + each-pos + foreach-p + lp + rp))) + "AST node for a for..in loop." + iterator ; [var] foo in ... + object ; object over which we're iterating + in-pos ; buffer position of 'in' keyword + each-pos ; buffer position of 'each' keyword, if foreach-p + foreach-p) ; t if it's a for-each loop + +(put 'cl-struct-js2-for-in-node 'js2-visitor 'js2-visit-for-in-node) +(put 'cl-struct-js2-for-in-node 'js2-printer 'js2-print-for-in-node) + +(defun js2-visit-for-in-node (n v) + (js2-visit-ast (js2-for-in-node-iterator n) v) + (js2-visit-ast (js2-for-in-node-object n) v) + (js2-visit-ast (js2-for-in-node-body n) v)) + +(defun js2-print-for-in-node (n i) + (let ((pad (js2-make-pad i)) + (foreach (js2-for-in-node-foreach-p n))) + (insert pad "for ") + (if foreach + (insert "each ")) + (insert "(") + (js2-print-ast (js2-for-in-node-iterator n) 0) + (insert " in ") + (js2-print-ast (js2-for-in-node-object n) 0) + (insert ") {\n") + (js2-print-body (js2-for-in-node-body n) (1+ i)) + (insert pad "}\n"))) + +(defstruct (js2-return-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-return-node (&key (type js2-RETURN) + (pos js2-ts-cursor) + len + retval))) + "AST node for a return statement." + retval) ; expression to return, or 'undefined + +(put 'cl-struct-js2-return-node 'js2-visitor 'js2-visit-return-node) +(put 'cl-struct-js2-return-node 'js2-printer 'js2-print-return-node) + +(defun js2-visit-return-node (n v) + (if (js2-return-node-retval n) + (js2-visit-ast (js2-return-node-retval n) v))) + +(defun js2-print-return-node (n i) + (insert (js2-make-pad i) "return") + (when (js2-return-node-retval n) + (insert " ") + (js2-print-ast (js2-return-node-retval n) 0)) + (insert ";\n")) + +(defstruct (js2-if-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-if-node (&key (type js2-IF) + (pos js2-ts-cursor) + len + condition + then-part + else-pos + else-part + lp + rp))) + "AST node for an if-statement." + condition ; expression + then-part ; statement or block + else-pos ; optional buffer position of 'else' keyword + else-part ; optional statement or block + lp ; position of left-paren, nil if omitted + rp) ; position of right-paren, nil if omitted + +(put 'cl-struct-js2-if-node 'js2-visitor 'js2-visit-if-node) +(put 'cl-struct-js2-if-node 'js2-printer 'js2-print-if-node) + +(defun js2-visit-if-node (n v) + (js2-visit-ast (js2-if-node-condition n) v) + (js2-visit-ast (js2-if-node-then-part n) v) + (if (js2-if-node-else-part n) + (js2-visit-ast (js2-if-node-else-part n) v))) + +(defun js2-print-if-node (n i) + (let ((pad (js2-make-pad i)) + (then-part (js2-if-node-then-part n)) + (else-part (js2-if-node-else-part n))) + (insert pad "if (") + (js2-print-ast (js2-if-node-condition n) 0) + (insert ") {\n") + (js2-print-body then-part (1+ i)) + (insert pad "}") + (cond + ((not else-part) + (insert "\n")) + ((js2-if-node-p else-part) + (insert " else ") + (js2-print-body else-part i)) + (t + (insert " else {\n") + (js2-print-body else-part (1+ i)) + (insert pad "}\n"))))) + +(defstruct (js2-try-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-try-node (&key (type js2-TRY) + (pos js2-ts-cursor) + len + try-block + catch-clauses + finally-block))) + "AST node for a try-statement." + try-block + catch-clauses ; a lisp list of `js2-catch-node' + finally-block) ; a `js2-finally-node' + +(put 'cl-struct-js2-try-node 'js2-visitor 'js2-visit-try-node) +(put 'cl-struct-js2-try-node 'js2-printer 'js2-print-try-node) + +(defun js2-visit-try-node (n v) + (js2-visit-ast (js2-try-node-try-block n) v) + (dolist (clause (js2-try-node-catch-clauses n)) + (js2-visit-ast clause v)) + (if (js2-try-node-finally-block n) + (js2-visit-ast (js2-try-node-finally-block n) v))) + +(defun js2-print-try-node (n i) + (let ((pad (js2-make-pad i)) + (catches (js2-try-node-catch-clauses n)) + (finally (js2-try-node-finally-block n))) + (insert pad "try {\n") + (js2-print-body (js2-try-node-try-block n) (1+ i)) + (insert pad "}") + (when catches + (dolist (catch catches) + (js2-print-ast catch i))) + (if finally + (js2-print-ast finally i) + (insert "\n")))) + +(defstruct (js2-catch-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-catch-node (&key (type js2-CATCH) + (pos js2-ts-cursor) + len + var-name + guard-kwd + guard-expr + block + lp + rp))) + "AST node for a catch clause." + var-name ; a `js2-name-node' + guard-kwd ; relative buffer position of "if" in "catch (x if ...)" + guard-expr ; catch condition, a `js2-node' + block ; statements, a `js2-block-node' + lp ; buffer position of left-paren, nil if omitted + rp) ; buffer position of right-paren, nil if omitted + +(put 'cl-struct-js2-catch-node 'js2-visitor 'js2-visit-catch-node) +(put 'cl-struct-js2-catch-node 'js2-printer 'js2-print-catch-node) + +(defun js2-visit-catch-node (n v) + (js2-visit-ast (js2-catch-node-var-name n) v) + (when (js2-catch-node-guard-kwd n) + (js2-visit-ast (js2-catch-node-guard-expr n) v)) + (js2-visit-ast (js2-catch-node-block n) v)) + +(defun js2-print-catch-node (n i) + (let ((pad (js2-make-pad i)) + (guard-kwd (js2-catch-node-guard-kwd n)) + (guard-expr (js2-catch-node-guard-expr n))) + (insert " catch (") + (js2-print-ast (js2-catch-node-var-name n) 0) + (when guard-kwd + (insert " if ") + (js2-print-ast guard-expr 0)) + (insert ") {\n") + (js2-print-body (js2-catch-node-block n) (1+ i)) + (insert pad "}"))) + +(defstruct (js2-finally-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-finally-node (&key (type js2-FINALLY) + (pos js2-ts-cursor) + len + body))) + "AST node for a finally clause." + body) ; a `js2-node', often but not always a block node + +(put 'cl-struct-js2-finally-node 'js2-visitor 'js2-visit-finally-node) +(put 'cl-struct-js2-finally-node 'js2-printer 'js2-print-finally-node) + +(defun js2-visit-finally-node (n v) + (js2-visit-ast (js2-finally-node-body n) v)) + +(defun js2-print-finally-node (n i) + (let ((pad (js2-make-pad i))) + (insert " finally {\n") + (js2-print-body (js2-finally-node-body n) (1+ i)) + (insert pad "}\n"))) + +(defstruct (js2-switch-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-switch-node (&key (type js2-SWITCH) + (pos js2-ts-cursor) + len + discriminant + cases + lp + rp))) + "AST node for a switch statement." + discriminant ; a `js2-node' (switch expression) + cases ; a lisp list of `js2-case-node' + lp ; position of open-paren for discriminant, nil if omitted + rp) ; position of close-paren for discriminant, nil if omitted + +(put 'cl-struct-js2-switch-node 'js2-visitor 'js2-visit-switch-node) +(put 'cl-struct-js2-switch-node 'js2-printer 'js2-print-switch-node) + +(defun js2-visit-switch-node (n v) + (js2-visit-ast (js2-switch-node-discriminant n) v) + (dolist (c (js2-switch-node-cases n)) + (js2-visit-ast c v))) + +(defun js2-print-switch-node (n i) + (let ((pad (js2-make-pad i)) + (cases (js2-switch-node-cases n))) + (insert pad "switch (") + (js2-print-ast (js2-switch-node-discriminant n) 0) + (insert ") {\n") + (dolist (case cases) + (js2-print-ast case i)) + (insert pad "}\n"))) + +(defstruct (js2-case-node + (:include js2-block-node) + (:constructor nil) + (:constructor make-js2-case-node (&key (type js2-CASE) + (pos js2-ts-cursor) + len + kids + expr))) + "AST node for a case clause of a switch statement." + expr) ; the case expression (nil for default) + +(put 'cl-struct-js2-case-node 'js2-visitor 'js2-visit-case-node) +(put 'cl-struct-js2-case-node 'js2-printer 'js2-print-case-node) + +(defun js2-visit-case-node (n v) + (if (js2-case-node-expr n) ; nil for default: case + (js2-visit-ast (js2-case-node-expr n) v)) + (js2-visit-block n v)) + +(defun js2-print-case-node (n i) + (let ((pad (js2-make-pad i)) + (expr (js2-case-node-expr n))) + (insert pad) + (if (null expr) + (insert "default:\n") + (insert "case ") + (js2-print-ast expr 0) + (insert ":\n")) + (dolist (kid (js2-case-node-kids n)) + (js2-print-ast kid (1+ i))))) + +(defstruct (js2-throw-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-throw-node (&key (type js2-THROW) + (pos js2-ts-cursor) + len + expr))) + "AST node for a throw statement." + expr) ; the expression to throw + +(put 'cl-struct-js2-throw-node 'js2-visitor 'js2-visit-throw-node) +(put 'cl-struct-js2-throw-node 'js2-printer 'js2-print-throw-node) + +(defun js2-visit-throw-node (n v) + (js2-visit-ast (js2-throw-node-expr n) v)) + +(defun js2-print-throw-node (n i) + (insert (js2-make-pad i) "throw ") + (js2-print-ast (js2-throw-node-expr n) 0) + (insert ";\n")) + +(defstruct (js2-with-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-with-node (&key (type js2-WITH) + (pos js2-ts-cursor) + len + object + body + lp + rp))) + "AST node for a with-statement." + object + body + lp ; buffer position of left-paren around object, nil if omitted + rp) ; buffer position of right-paren around object, nil if omitted + +(put 'cl-struct-js2-with-node 'js2-visitor 'js2-visit-with-node) +(put 'cl-struct-js2-with-node 'js2-printer 'js2-print-with-node) + +(defun js2-visit-with-node (n v) + (js2-visit-ast (js2-with-node-object n) v) + (js2-visit-ast (js2-with-node-body n) v)) + +(defun js2-print-with-node (n i) + (let ((pad (js2-make-pad i))) + (insert pad "with (") + (js2-print-ast (js2-with-node-object n) 0) + (insert ") {\n") + (js2-print-body (js2-with-node-body n) (1+ i)) + (insert pad "}\n"))) + +(defstruct (js2-label-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-label-node (&key (type js2-LABEL) + (pos js2-ts-cursor) + len + name))) + "AST node for a statement label or case label." + name ; a string + loop) ; for validating and code-generating continue-to-label + +(put 'cl-struct-js2-label-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-label-node 'js2-printer 'js2-print-label) + +(defun js2-print-label (n i) + (insert (js2-make-pad i) + (js2-label-node-name n) + ":\n")) + +(defstruct (js2-labeled-stmt-node + (:include js2-node) + (:constructor nil) + ;; type needs to be in `js2-side-effecting-tokens' to avoid spurious + ;; no-side-effects warnings, hence js2-EXPR_RESULT. + (:constructor make-js2-labeled-stmt-node (&key (type js2-EXPR_RESULT) + (pos js2-ts-cursor) + len + labels + stmt))) + "AST node for a statement with one or more labels. +Multiple labels for a statement are collapsed into the labels field." + labels ; lisp list of `js2-label-node' + stmt) ; the statement these labels are for + +(put 'cl-struct-js2-labeled-stmt-node 'js2-visitor 'js2-visit-labeled-stmt) +(put 'cl-struct-js2-labeled-stmt-node 'js2-printer 'js2-print-labeled-stmt) + +(defun js2-get-label-by-name (lbl-stmt name) + "Return a `js2-label-node' by NAME from LBL-STMT's labels list. +Returns nil if no such label is in the list." + (let ((label-list (js2-labeled-stmt-node-labels lbl-stmt)) + result) + (while (and label-list (not result)) + (if (string= (js2-label-node-name (car label-list)) name) + (setq result (car label-list)) + (setq label-list (cdr label-list)))) + result)) + +(defun js2-visit-labeled-stmt (n v) + (dolist (label (js2-labeled-stmt-node-labels n)) + (js2-visit-ast label v)) + (js2-visit-ast (js2-labeled-stmt-node-stmt n) v)) + +(defun js2-print-labeled-stmt (n i) + (dolist (label (js2-labeled-stmt-node-labels n)) + (js2-print-ast label i)) + (js2-print-ast (js2-labeled-stmt-node-stmt n) (1+ i))) + +(defun js2-labeled-stmt-node-contains (node label) + "Return t if NODE contains LABEL in its label set. +NODE is a `js2-labels-node'. LABEL is an identifier." + (loop for nl in (js2-labeled-stmt-node-labels node) + if (string= label (js2-label-node-name nl)) + return t + finally return nil)) + +(defsubst js2-labeled-stmt-node-add-label (node label) + "Add a `js2-label-node' to the label set for this statement." + (setf (js2-labeled-stmt-node-labels node) + (nconc (js2-labeled-stmt-node-labels node) (list label)))) + +(defstruct (js2-jump-node + (:include js2-node) + (:constructor nil)) + "Abstract supertype of break and continue nodes." + label ; `js2-name-node' for location of label identifier, if present + target) ; target js2-labels-node or loop/switch statement + +(defun js2-visit-jump-node (n v) + ;; we don't visit the target, since it's a back-link + (if (js2-jump-node-label n) + (js2-visit-ast (js2-jump-node-label n) v))) + +(defstruct (js2-break-node + (:include js2-jump-node) + (:constructor nil) + (:constructor make-js2-break-node (&key (type js2-BREAK) + (pos js2-ts-cursor) + len + label + target))) + "AST node for a break statement. +The label field is a `js2-name-node', possibly nil, for the named label +if provided. E.g. in 'break foo', it represents 'foo'. The target field +is the target of the break - a label node or enclosing loop/switch statement.") + +(put 'cl-struct-js2-break-node 'js2-visitor 'js2-visit-jump-node) +(put 'cl-struct-js2-break-node 'js2-printer 'js2-print-break-node) + +(defun js2-print-break-node (n i) + (insert (js2-make-pad i) "break") + (when (js2-break-node-label n) + (insert " ") + (js2-print-ast (js2-break-node-label n) 0)) + (insert ";\n")) + +(defstruct (js2-continue-node + (:include js2-jump-node) + (:constructor nil) + (:constructor make-js2-continue-node (&key (type js2-CONTINUE) + (pos js2-ts-cursor) + len + label + target))) + "AST node for a continue statement. +The label field is the user-supplied enclosing label name, a `js2-name-node'. +It is nil if continue specifies no label. The target field is the jump target: +a `js2-label-node' or the innermost enclosing loop.") + +(put 'cl-struct-js2-continue-node 'js2-visitor 'js2-visit-jump-node) +(put 'cl-struct-js2-continue-node 'js2-printer 'js2-print-continue-node) + +(defun js2-print-continue-node (n i) + (insert (js2-make-pad i) "continue") + (when (js2-continue-node-label n) + (insert " ") + (js2-print-ast (js2-continue-node-label n) 0)) + (insert ";\n")) + +(defstruct (js2-function-node + (:include js2-script-node) + (:constructor nil) + (:constructor make-js2-function-node (&key (type js2-FUNCTION) + (pos js2-ts-cursor) + len + (ftype 'FUNCTION) + (form 'FUNCTION_STATEMENT) + (name "") + params + body + lp + rp))) + "AST node for a function declaration. +The `params' field is a lisp list of nodes. Each node is either a simple +`js2-name-node', or if it's a destructuring-assignment parameter, a +`js2-array-node' or `js2-object-node'." + ftype ; FUNCTION, GETTER or SETTER + form ; FUNCTION_{STATEMENT|EXPRESSION|EXPRESSION_STATEMENT} + name ; function name (a `js2-name-node', or nil if anonymous) + params ; a lisp list of destructuring forms or simple name nodes + body ; a `js2-block-node' + lp ; position of arg-list open-paren, or nil if omitted + rp ; position of arg-list close-paren, or nil if omitted + ignore-dynamic ; ignore value of the dynamic-scope flag (interpreter only) + needs-activation ; t if we need an activation object for this frame + is-generator ; t if this function contains a yield + 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) + +(defun js2-visit-function-node (n v) + (if (js2-function-node-name n) + (js2-visit-ast (js2-function-node-name n) v)) + (dolist (p (js2-function-node-params n)) + (js2-visit-ast p v)) + (js2-visit-ast (js2-function-node-body n) v)) + +(defun js2-print-function-node (n i) + (let ((pad (js2-make-pad i)) + (getter (js2-node-get-prop n 'GETTER_SETTER)) + (name (js2-function-node-name n)) + (params (js2-function-node-params n)) + (body (js2-function-node-body n)) + (expr (eq (js2-function-node-form n) 'FUNCTION_EXPRESSION))) + (unless getter + (insert pad "function")) + (when name + (insert " ") + (js2-print-ast name 0)) + (insert "(") + (loop with len = (length params) + for param in params + for count from 1 + do + (js2-print-ast param 0) + (if (< count len) + (insert ", "))) + (insert ") {") + (unless expr + (insert "\n")) + ;; TODO: fix this to be smarter about indenting, etc. + (js2-print-body body (1+ i)) + (insert pad "}") + (unless expr + (insert "\n")))) + +(defsubst js2-function-name (node) + "Return function name for NODE, a `js2-function-node', or nil if anonymous." + (and (js2-function-node-name node) + (js2-name-node-name (js2-function-node-name node)))) + +;; Having this be an expression node makes it more flexible. +;; There are IDE contexts, such as indentation in a for-loop initializer, +;; that work better if you assume it's an expression. Whenever we have +;; a standalone var/const declaration, we just wrap with an expr stmt. +;; Eclipse apparently screwed this up and now has two versions, expr and stmt. +(defstruct (js2-var-decl-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-var-decl-node (&key (type js2-VAR) + (pos js2-token-beg) + len + kids + decl-type))) + "AST node for a variable declaration list (VAR, CONST or LET). +The node bounds differ depending on the declaration type. For VAR or +CONST declarations, the bounds include the var/const keyword. For LET +declarations, the node begins at the position of the first child." + kids ; a lisp list of `js2-var-init-node' structs. + decl-type) ; js2-VAR, js2-CONST or js2-LET + +(put 'cl-struct-js2-var-decl-node 'js2-visitor 'js2-visit-var-decl) +(put 'cl-struct-js2-var-decl-node 'js2-printer 'js2-print-var-decl) + +(defun js2-visit-var-decl (n v) + (dolist (kid (js2-var-decl-node-kids n)) + (js2-visit-ast kid v))) + +(defun js2-print-var-decl (n i) + (let ((pad (js2-make-pad i)) + (tt (js2-var-decl-node-decl-type n))) + (insert pad) + (insert (cond + ((= tt js2-VAR) "var ") + ((= tt js2-LET) "") ; handled by parent let-{expr/stmt} + ((= tt js2-CONST) "const ") + (t + (error "malformed var-decl node")))) + (loop with kids = (js2-var-decl-node-kids n) + with len = (length kids) + for kid in kids + for count from 1 + do + (js2-print-ast kid 0) + (if (< count len) + (insert ", "))))) + +(defstruct (js2-var-init-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-var-init-node (&key (type js2-VAR) + (pos js2-ts-cursor) + len + target + initializer))) + "AST node for a variable declaration. +The type field will be js2-CONST for a const decl." + target ; `js2-name-node', `js2-object-node', or `js2-array-node' + initializer) ; initializer expression, a `js2-node' + +(put 'cl-struct-js2-var-init-node 'js2-visitor 'js2-visit-var-init-node) +(put 'cl-struct-js2-var-init-node 'js2-printer 'js2-print-var-init-node) + +(defun js2-visit-var-init-node (n v) + (js2-visit-ast (js2-var-init-node-target n) v) + (if (js2-var-init-node-initializer n) + (js2-visit-ast (js2-var-init-node-initializer n) v))) + +(defun js2-print-var-init-node (n i) + (let ((pad (js2-make-pad i)) + (name (js2-var-init-node-target n)) + (init (js2-var-init-node-initializer n))) + (insert pad) + (js2-print-ast name 0) + (when init + (insert " = ") + (js2-print-ast init 0)))) + +(defstruct (js2-cond-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-cond-node (&key (type js2-HOOK) + (pos js2-ts-cursor) + len + test-expr + true-expr + false-expr + q-pos + c-pos))) + "AST node for the ternary operator" + test-expr + true-expr + false-expr + q-pos ; buffer position of ? + c-pos) ; buffer position of : + +(put 'cl-struct-js2-cond-node 'js2-visitor 'js2-visit-cond-node) +(put 'cl-struct-js2-cond-node 'js2-printer 'js2-print-cond-node) + +(defun js2-visit-cond-node (n v) + (js2-visit-ast (js2-cond-node-test-expr n) v) + (js2-visit-ast (js2-cond-node-true-expr n) v) + (js2-visit-ast (js2-cond-node-false-expr n) v)) + +(defun js2-print-cond-node (n i) + (let ((pad (js2-make-pad i))) + (insert pad) + (js2-print-ast (js2-cond-node-test-expr n) 0) + (insert " ? ") + (js2-print-ast (js2-cond-node-true-expr n) 0) + (insert " : ") + (js2-print-ast (js2-cond-node-false-expr n) 0))) + +(defstruct (js2-infix-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-infix-node (&key type + (pos js2-ts-cursor) + len + op-pos + left + right))) + "Represents infix expressions. +Includes assignment ops like `|=', and the comma operator. +The type field inherited from `js2-node' holds the operator." + op-pos ; buffer position where operator begins + left ; any `js2-node' + right) ; any `js2-node' + +(put 'cl-struct-js2-infix-node 'js2-visitor 'js2-visit-infix-node) +(put 'cl-struct-js2-infix-node 'js2-printer 'js2-print-infix-node) + +(defun js2-visit-infix-node (n v) + (when (js2-infix-node-left n) + (js2-visit-ast (js2-infix-node-left n) v)) + (when (js2-infix-node-right n) + (js2-visit-ast (js2-infix-node-right n) v))) + +(defconst js2-operator-tokens + (let ((table (make-hash-table :test 'eq)) + (tokens + (list (cons js2-IN "in") + (cons js2-TYPEOF "typeof") + (cons js2-INSTANCEOF "instanceof") + (cons js2-DELPROP "delete") + (cons js2-COMMA ",") + (cons js2-COLON ":") + (cons js2-OR "||") + (cons js2-AND "&&") + (cons js2-INC "++") + (cons js2-DEC "--") + (cons js2-BITOR "|") + (cons js2-BITXOR "^") + (cons js2-BITAND "&") + (cons js2-EQ "==") + (cons js2-NE "!=") + (cons js2-LT "<") + (cons js2-LE "<=") + (cons js2-GT ">") + (cons js2-GE ">=") + (cons js2-LSH "<<") + (cons js2-RSH ">>") + (cons js2-URSH ">>>") + (cons js2-ADD "+") ; infix plus + (cons js2-SUB "-") ; infix minus + (cons js2-MUL "*") + (cons js2-DIV "/") + (cons js2-MOD "%") + (cons js2-NOT "!") + (cons js2-BITNOT "~") + (cons js2-POS "+") ; unary plus + (cons js2-NEG "-") ; unary minus + (cons js2-SHEQ "===") ; shallow equality + (cons js2-SHNE "!==") ; shallow inequality + (cons js2-ASSIGN "=") + (cons js2-ASSIGN_BITOR "|=") + (cons js2-ASSIGN_BITXOR "^=") + (cons js2-ASSIGN_BITAND "&=") + (cons js2-ASSIGN_LSH "<<=") + (cons js2-ASSIGN_RSH ">>=") + (cons js2-ASSIGN_URSH ">>>=") + (cons js2-ASSIGN_ADD "+=") + (cons js2-ASSIGN_SUB "-=") + (cons js2-ASSIGN_MUL "*=") + (cons js2-ASSIGN_DIV "/=") + (cons js2-ASSIGN_MOD "%=")))) + (loop for (k . v) in tokens do + (puthash k v table)) + table)) + +(defun js2-print-infix-node (n i) + (let* ((tt (js2-node-type n)) + (op (gethash tt js2-operator-tokens))) + (unless op + (error "unrecognized infix operator %s" (js2-node-type n))) + (insert (js2-make-pad i)) + (js2-print-ast (js2-infix-node-left n) 0) + (unless (= tt js2-COMMA) + (insert " ")) + (insert op) + (insert " ") + (js2-print-ast (js2-infix-node-right n) 0))) + +(defstruct (js2-assign-node + (:include js2-infix-node) + (:constructor nil) + (:constructor make-js2-assign-node (&key type + (pos js2-ts-cursor) + len + op-pos + left + right))) + "Represents any assignment. +The type field holds the actual assignment operator.") + +(put 'cl-struct-js2-assign-node 'js2-visitor 'js2-visit-infix-node) +(put 'cl-struct-js2-assign-node 'js2-printer 'js2-print-infix-node) + +(defstruct (js2-unary-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-unary-node (&key type ; required + (pos js2-ts-cursor) + len + operand))) + "AST node type for unary operator nodes. +The type field can be NOT, BITNOT, POS, NEG, INC, DEC, +TYPEOF, or DELPROP. For INC or DEC, a 'postfix node +property is added if the operator follows the operand." + operand) ; a `js2-node' expression + +(put 'cl-struct-js2-unary-node 'js2-visitor 'js2-visit-unary-node) +(put 'cl-struct-js2-unary-node 'js2-printer 'js2-print-unary-node) + +(defun js2-visit-unary-node (n v) + (js2-visit-ast (js2-unary-node-operand n) v)) + +(defun js2-print-unary-node (n i) + (let* ((tt (js2-node-type n)) + (op (gethash tt js2-operator-tokens)) + (postfix (js2-node-get-prop n 'postfix))) + (unless op + (error "unrecognized unary operator %s" tt)) + (insert (js2-make-pad i)) + (unless postfix + (insert op)) + (if (or (= tt js2-TYPEOF) + (= tt js2-DELPROP)) + (insert " ")) + (js2-print-ast (js2-unary-node-operand n) 0) + (when postfix + (insert op)))) + +(defstruct (js2-let-node + (:include js2-scope) + (:constructor nil) + (:constructor make-js2-let-node (&key (type js2-LETEXPR) + (pos js2-token-beg) + len + vars + body + lp + rp))) + "AST node for a let expression or a let statement. +Note that a let declaration such as let x=6, y=7 is a `js2-var-decl-node'." + vars ; a `js2-var-decl-node' + body ; a `js2-node' representing the expression or body block + lp + rp) + +(put 'cl-struct-js2-let-node 'js2-visitor 'js2-visit-let-node) +(put 'cl-struct-js2-let-node 'js2-printer 'js2-print-let-node) + +(defun js2-visit-let-node (n v) + (when (js2-let-node-vars n) + (js2-visit-ast (js2-let-node-vars n) v)) + (when (js2-let-node-body n) + (js2-visit-ast (js2-let-node-body n) v))) + +(defun js2-print-let-node (n i) + (insert (js2-make-pad i) "let (") + (js2-print-ast (js2-let-node-vars n) 0) + (insert ") ") + (js2-print-ast (js2-let-node-body n) i)) + +(defstruct (js2-keyword-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-keyword-node (&key type + (pos js2-token-beg) + (len (- js2-ts-cursor pos))))) + "AST node representing a literal keyword such as `null'. +Used for `null', `this', `true', `false' and `debugger'. +The node type is set to js2-NULL, js2-THIS, etc.") + +(put 'cl-struct-js2-keyword-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-keyword-node 'js2-printer 'js2-print-keyword-node) + +(defun js2-print-keyword-node (n i) + (insert (js2-make-pad i) + (let ((tt (js2-node-type n))) + (cond + ((= tt 'js2-THIS) "this") + ((= 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 this node is a `js2-literal-node' of type js2-THIS." + (eq (js2-node-type node) js2-THIS)) + +(defstruct (js2-new-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-new-node (&key (type js2-NEW) + (pos js2-token-beg) + len + target + args + initializer + lp + rp))) + "AST node for new-expression such as new Foo()." + target ; an identifier or reference + args ; a lisp list of argument nodes + lp ; position of left-paren, nil if omitted + rp ; position of right-paren, nil if omitted + initializer) ; experimental Rhino syntax: optional `js2-object-node' + +(put 'cl-struct-js2-new-node 'js2-visitor 'js2-visit-new-node) +(put 'cl-struct-js2-new-node 'js2-printer 'js2-print-new-node) + +(defun js2-visit-new-node (n v) + (js2-visit-ast (js2-new-node-target n) v) + (dolist (arg (js2-new-node-args n)) + (js2-visit-ast arg v)) + (when (js2-new-node-initializer n) + (js2-visit-ast (js2-new-node-initializer n) v))) + +(defun js2-print-new-node (n i) + (insert (js2-make-pad i) "new ") + (js2-print-ast (js2-new-node-target n)) + (insert "(") + (js2-print-list (js2-new-node-args n)) + (insert ")") + (when (js2-new-node-initializer n) + (insert " ") + (js2-print-ast (js2-new-node-initializer n)))) + +(defstruct (js2-name-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-name-node (&key (type js2-NAME) + (pos js2-token-beg) + (len (- js2-ts-cursor + js2-token-beg)) + (name js2-ts-string)))) + "AST node for a JavaScript identifier" + name ; a string + scope) ; a `js2-scope' (optional, used for codegen) + +(put 'cl-struct-js2-name-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-name-node 'js2-printer 'js2-print-name-node) + +(defun js2-print-name-node (n i) + (insert (js2-make-pad i) + (js2-name-node-name n))) + +(defsubst js2-name-node-length (node) + "Return identifier length of NODE, a `js2-name-node'. +Returns 0 if NODE is nil or its identifier field is nil." + (if node + (length (js2-name-node-name node)) + 0)) + +(defstruct (js2-number-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-number-node (&key (type js2-NUMBER) + (pos js2-token-beg) + (len (- js2-ts-cursor + js2-token-beg)) + (value js2-ts-string) + (num-value js2-ts-number)))) + "AST node for a number literal." + value ; the original string, e.g. "6.02e23" + num-value) ; the parsed number value + +(put 'cl-struct-js2-number-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-number-node 'js2-printer 'js2-print-number-node) + +(defun js2-print-number-node (n i) + (insert (js2-make-pad i) + (number-to-string (js2-number-node-value n)))) + +(defstruct (js2-regexp-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-regexp-node (&key (type js2-REGEXP) + (pos js2-token-beg) + (len (- js2-ts-cursor + js2-token-beg)) + value + flags))) + "AST node for a regular expression literal." + value ; the regexp string, without // delimiters + flags) ; a string of flags, e.g. `mi'. + +(put 'cl-struct-js2-regexp-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-regexp-node 'js2-printer 'js2-print-regexp) + +(defun js2-print-regexp (n i) + (insert (js2-make-pad i) + "/" + (js2-regexp-node-value n) + "/") + (if (js2-regexp-node-flags n) + (insert (js2-regexp-node-flags n)))) + +(defstruct (js2-string-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-string-node (&key (type js2-STRING) + (pos js2-token-beg) + (len (- js2-ts-cursor + js2-token-beg)) + (value js2-ts-string)))) + "String literal. +Escape characters are not evaluated; e.g. \n is 2 chars in value field. +You can tell the quote type by looking at the first character." + value) ; the characters of the string, including the quotes + +(put 'cl-struct-js2-string-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-string-node 'js2-printer 'js2-print-string-node) + +(defun js2-print-string-node (n i) + (insert (js2-make-pad i) + (js2-node-string n))) + +(defstruct (js2-array-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-array-node (&key (type js2-ARRAYLIT) + (pos js2-ts-cursor) + len + elems))) + "AST node for an array literal." + elems) ; list of expressions. [foo,,bar] yields a nil middle element. + +(put 'cl-struct-js2-array-node 'js2-visitor 'js2-visit-array-node) +(put 'cl-struct-js2-array-node 'js2-printer 'js2-print-array-node) + +(defun js2-visit-array-node (n v) + (dolist (e (js2-array-node-elems n)) + (when e ; can be nil, e.g. [a, ,b] + (js2-visit-ast e v)))) + +(defun js2-print-array-node (n i) + (insert (js2-make-pad i) "[") + (js2-print-list (js2-array-node-elems n)) + (insert "]")) + +(defstruct (js2-object-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-object-node (&key (type js2-OBJECTLIT) + (pos js2-ts-cursor) + len + elems))) + "AST node for an object literal expression." + elems) ; a lisp list of `js2-object-prop-node' + +(put 'cl-struct-js2-object-node 'js2-visitor 'js2-visit-object-node) +(put 'cl-struct-js2-object-node 'js2-printer 'js2-print-object-node) + +(defun js2-visit-object-node (n v) + (dolist (e (js2-object-node-elems n)) + (js2-visit-ast e v))) + +(defun js2-print-object-node (n i) + (insert (js2-make-pad i) "{") + (js2-print-list (js2-object-node-elems n)) + (insert "}")) + +(defstruct (js2-object-prop-node + (:include js2-infix-node) + (:constructor nil) + (:constructor make-js2-object-prop-node (&key (type js2-COLON) + (pos js2-ts-cursor) + len + left + right + op-pos))) + "AST node for an object literal prop:value entry. +The `left' field is the property: a name node, string node or number node. +The `right' field is a `js2-node' representing the initializer value.") + +(put 'cl-struct-js2-object-prop-node 'js2-visitor 'js2-visit-infix-node) +(put 'cl-struct-js2-object-prop-node 'js2-printer 'js2-print-object-prop-node) + +(defun js2-print-object-prop-node (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-object-prop-node-left n) 0) + (insert ":") + (js2-print-ast (js2-object-prop-node-right n) 0)) + +(defstruct (js2-getter-setter-node + (:include js2-infix-node) + (:constructor nil) + (:constructor make-js2-getter-setter-node (&key type ; GET or SET + (pos js2-ts-cursor) + len + left + right))) + "AST node for a getter/setter property in an object literal. +The `left' field is the `js2-name-node' naming the getter/setter prop. +The `right' field is always an anonymous `js2-function-node' with a node +property `GETTER_SETTER' set to js2-GET or js2-SET. ") + +(put 'cl-struct-js2-getter-setter-node 'js2-visitor 'js2-visit-infix-node) +(put 'cl-struct-js2-getter-setter-node 'js2-printer 'js2-print-getter-setter) + +(defun js2-print-getter-setter (n i) + (let ((pad (js2-make-pad i)) + (left (js2-getter-setter-node-left n)) + (right (js2-getter-setter-node-right n))) + (insert pad) + (insert (if (= (js2-node-type n) js2-GET) "get " "set ")) + (js2-print-ast left 0) + (js2-print-ast right 0))) + +(defstruct (js2-prop-get-node + (:include js2-infix-node) + (:constructor nil) + (:constructor make-js2-prop-get-node (&key (type js2-GETPROP) + (pos js2-ts-cursor) + len + left + right))) + "AST node for a dotted property reference, e.g. foo.bar or foo().bar") + +(put 'cl-struct-js2-prop-get-node 'js2-visitor 'js2-visit-prop-get-node) +(put 'cl-struct-js2-prop-get-node 'js2-printer 'js2-print-prop-get-node) + +(defun js2-visit-prop-get-node (n v) + (when (js2-prop-get-node-left n) + (js2-visit-ast (js2-prop-get-node-left n) v)) + (when (js2-prop-get-node-right n) + (js2-visit-ast (js2-prop-get-node-right n) v))) + +(defun js2-print-prop-get-node (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-prop-get-node-left n) 0) + (insert ".") + (js2-print-ast (js2-prop-get-node-right n) 0)) + +(defstruct (js2-elem-get-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-elem-get-node (&key (type js2-GETELEM) + (pos js2-ts-cursor) + len + target + element + lb + rb))) + "AST node for an array index expression such as foo[bar]." + target ; a `js2-node' - the expression preceding the "." + element ; a `js2-node' - the expression in brackets + lb ; position of left-bracket, nil if omitted + rb) ; position of right-bracket, nil if omitted + +(put 'cl-struct-js2-elem-get-node 'js2-visitor 'js2-visit-elem-get-node) +(put 'cl-struct-js2-elem-get-node 'js2-printer 'js2-print-elem-get-node) + +(defun js2-visit-elem-get-node (n v) + (when (js2-elem-get-node-target n) + (js2-visit-ast (js2-elem-get-node-target n) v)) + (when (js2-elem-get-node-element n) + (js2-visit-ast (js2-elem-get-node-element n) v))) + +(defun js2-print-elem-get-node (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-elem-get-node-target n) 0) + (insert "[") + (js2-print-ast (js2-elem-get-node-element n) 0) + (insert "]")) + +(defstruct (js2-call-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-call-node (&key (type js2-CALL) + (pos js2-ts-cursor) + len + target + args + lp + rp))) + "AST node for a JavaScript function call." + target ; a `js2-node' evaluating to the function to call + args ; a lisp list of `js2-node' arguments + lp ; position of open-paren, or nil if missing + rp) ; position of close-paren, or nil if missing + +(put 'cl-struct-js2-call-node 'js2-visitor 'js2-visit-call-node) +(put 'cl-struct-js2-call-node 'js2-printer 'js2-print-call-node) + +(defun js2-visit-call-node (n v) + (js2-visit-ast (js2-call-node-target n) v) + (dolist (arg (js2-call-node-args n)) + (js2-visit-ast arg v))) + +(defun js2-print-call-node (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-call-node-target n) 0) + (insert "(") + (js2-print-list (js2-call-node-args n)) + (insert ")")) + +(defstruct (js2-yield-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-yield-node (&key (type js2-YIELD) + (pos js2-ts-cursor) + len + value))) + "AST node for yield statement or expression." + value) ; optional: value to be yielded + +(put 'cl-struct-js2-yield-node 'js2-visitor 'js2-visit-yield-node) +(put 'cl-struct-js2-yield-node 'js2-printer 'js2-print-yield-node) + +(defun js2-visit-yield-node (n v) + (js2-visit-ast (js2-yield-node-value n) v)) + +(defun js2-print-yield-node (n i) + (insert (js2-make-pad i)) + (insert "yield") + (when (js2-yield-node-value n) + (insert " ") + (js2-print-ast (js2-yield-node-value n) 0))) + +(defstruct (js2-paren-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-paren-node (&key (type js2-LP) + (pos js2-ts-cursor) + len + expr))) + "AST node for a parenthesized expression. +In particular, used when the parens are syntactically optional, +as opposed to required parens such as those enclosing an if-conditional." + expr) ; `js2-node' + +(put 'cl-struct-js2-paren-node 'js2-visitor 'js2-visit-paren-node) +(put 'cl-struct-js2-paren-node 'js2-printer 'js2-print-paren-node) + +(defun js2-visit-paren-node (n v) + (js2-visit-ast (js2-paren-node-expr n) v)) + +(defun js2-print-paren-node (n i) + (insert (js2-make-pad i)) + (insert "(") + (js2-print-ast (js2-paren-node-expr n) 0) + (insert ")")) + +(defstruct (js2-array-comp-node + (:include js2-scope) + (:constructor nil) + (:constructor make-js2-array-comp-node (&key (type js2-ARRAYCOMP) + (pos js2-ts-cursor) + len + result + loops + filter + if-pos + lp + rp))) + "AST node for an Array comprehension such as [[x,y] for (x in foo) for (y in bar)]." + result ; result expression (just after left-bracket) + loops ; a lisp list of `js2-array-comp-loop-node' + filter ; guard/filter expression + if-pos ; buffer pos of 'if' keyword, if present, else nil + lp ; buffer position of if-guard left-paren, or nil if not present + rp) ; buffer position of if-guard right-paren, or nil if not present + +(put 'cl-struct-js2-array-comp-node 'js2-visitor 'js2-visit-array-comp-node) +(put 'cl-struct-js2-array-comp-node 'js2-printer 'js2-print-array-comp-node) + +(defun js2-visit-array-comp-node (n v) + (js2-visit-ast (js2-array-comp-node-result n) v) + (dolist (l (js2-array-comp-node-loops n)) + (js2-visit-ast l v)) + (if (js2-array-comp-node-filter n) + (js2-visit-ast (js2-array-comp-node-filter n) v))) + +(defun js2-print-array-comp-node (n i) + (let ((pad (js2-make-pad i)) + (result (js2-array-comp-node-result n)) + (loops (js2-array-comp-node-loops n)) + (filter (js2-array-comp-node-filter n))) + (insert pad "[") + (js2-print-ast result 0) + (dolist (l loops) + (insert " ") + (js2-print-ast l 0)) + (when filter + (insert " if (") + (js2-print-ast filter 0)) + (insert ")]"))) + +(defstruct (js2-array-comp-loop-node + (:include js2-for-in-node) + (:constructor nil) + (:constructor make-js2-array-comp-loop-node (&key (type js2-FOR) + (pos js2-ts-cursor) + len + iterator + object + in-pos + foreach-p + each-pos + lp + rp))) + "AST subtree for each 'for (foo in bar)' loop in an array comprehension.") + +(put 'cl-struct-js2-array-comp-loop-node 'js2-visitor 'js2-visit-array-comp-loop) +(put 'cl-struct-js2-array-comp-loop-node 'js2-printer 'js2-print-array-comp-loop) + +(defun js2-visit-array-comp-loop (n v) + (js2-visit-ast (js2-array-comp-loop-node-iterator n) v) + (js2-visit-ast (js2-array-comp-loop-node-object n) v)) + +(defun js2-print-array-comp-loop (n i) + (insert "for (") + (js2-print-ast (js2-array-comp-loop-node-iterator n) 0) + (insert " in ") + (js2-print-ast (js2-array-comp-loop-node-object n) 0) + (insert ")")) + +(defstruct (js2-empty-expr-node + (:include js2-node) + (:constructor nil) + (:constructor make-js2-empty-expr-node (&key (type js2-EMPTY) + (pos js2-token-beg) + len))) + "AST node for an empty expression.") + +(put 'cl-struct-js2-empty-expr-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-empty-expr-node 'js2-printer 'js2-print-none) + +(defstruct (js2-xml-node + (:include js2-block-node) + (:constructor nil) + (:constructor make-js2-xml-node (&key (type js2-XML) + (pos js2-token-beg) + len + kids))) + "AST node for initial parse of E4X literals. +The kids field is a list of XML fragments, each a `js2-string-node' or +a `js2-xml-js-expr-node'. Equivalent to Rhino's XmlLiteral node.") + +(put 'cl-struct-js2-xml-node 'js2-visitor 'js2-visit-block) +(put 'cl-struct-js2-xml-node 'js2-printer 'js2-print-xml-node) + +(defun js2-print-xml-node (n i) + (dolist (kid (js2-xml-node-kids n)) + (js2-print-ast kid i))) + +(defstruct (js2-xml-js-expr-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-js-expr-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + expr))) + "AST node for an embedded JavaScript {expression} in an E4X literal. +The start and end fields correspond to the curly-braces." + expr) ; a `js2-expr-node' of some sort + +(put 'cl-struct-js2-xml-js-expr-node 'js2-visitor 'js2-visit-xml-js-expr) +(put 'cl-struct-js2-xml-js-expr-node 'js2-printer 'js2-print-xml-js-expr) + +(defun js2-visit-xml-js-expr (n v) + (js2-visit-ast (js2-xml-js-expr-node-expr n) v)) + +(defun js2-print-xml-js-expr (n i) + (insert (js2-make-pad i)) + (insert "{") + (js2-print-ast (js2-xml-js-expr-node-expr n) 0) + (insert "}")) + +(defstruct (js2-xml-dot-query-node + (:include js2-infix-node) + (:constructor nil) + (:constructor make-js2-xml-dot-query-node (&key (type js2-DOTQUERY) + (pos js2-ts-cursor) + op-pos + len + left + right + rp))) + "AST node for an E4X foo.(bar) filter expression. +Note that the left-paren is automatically the character immediately +following the dot (.) in the operator. No whitespace is permitted +between the dot and the lp by the scanner." + rp) + +(put 'cl-struct-js2-xml-dot-query-node 'js2-visitor 'js2-visit-infix-node) +(put 'cl-struct-js2-xml-dot-query-node 'js2-printer 'js2-print-xml-dot-query) + +(defun js2-print-xml-dot-query (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-xml-dot-query-node-left n) 0) + (insert ".(") + (js2-print-ast (js2-xml-dot-query-node-right n) 0) + (insert ")")) + +(defstruct (js2-xml-ref-node + (:include js2-node) + (:constructor nil)) ; abstract + "Base type for E4X XML attribute-access or property-get expressions. +Such expressions can take a variety of forms. The general syntax has +three parts: + + - (optional) an @ (specifying an attribute access) + - (optional) a namespace (a `js2-name-node') and double-colon + - (required) either a `js2-name-node' or a bracketed [expression] + +The property-name expressions (examples: ns::name, @name) are +represented as `js2-xml-prop-ref' nodes. The bracketed-expression +versions (examples: ns::[name], @[name]) become `js2-xml-elem-ref' nodes. + +This node type (or more specifically, its subclasses) will sometimes +be the right-hand child of a `js2-prop-get-node' or a +`js2-infix-node' of type `js2-DOTDOT', the .. xml-descendants operator. +The `js2-xml-ref-node' may also be a standalone primary expression with +no explicit target, which is valid in certain expression contexts such as + + company..employee.(@id < 100) + +in this case, the @id is a `js2-xml-ref' that is part of an infix '<' +expression whose parent is a `js2-xml-dot-query-node'." + namespace + at-pos + colon-pos) + +(defsubst js2-xml-ref-node-attr-access-p (node) + "Return non-nil if this expression began with an @-token." + (and (numberp (js2-xml-ref-node-at-pos node)) + (plusp (js2-xml-ref-node-at-pos node)))) + +(defstruct (js2-xml-prop-ref-node + (:include js2-xml-ref-node) + (:constructor nil) + (:constructor make-js2-xml-prop-ref-node (&key (type js2-REF_NAME) + (pos js2-token-beg) + len + propname + namespace + at-pos + colon-pos))) + "AST node for an E4X XML [expr] property-ref expression. +The JavaScript syntax is an optional @, an optional ns::, and a name. + + [ '@' ] [ name '::' ] name + +Examples include name, ns::name, ns::*, *::name, *::*, @attr, @ns::attr, +@ns::*, @*::attr, @*::*, and @*. + +The node starts at the @ token, if present. Otherwise it starts at the +namespace name. The node bounds extend through the closing right-bracket, +or if it is missing due to a syntax error, through the end of the index +expression." + propname) + +(put 'cl-struct-js2-xml-prop-ref-node 'js2-visitor 'js2-visit-xml-prop-ref-node) +(put 'cl-struct-js2-xml-prop-ref-node 'js2-printer 'js2-print-xml-prop-ref-node) + +(defun js2-visit-xml-prop-ref-node (n v) + (if (js2-xml-prop-ref-node-namespace n) + (js2-visit-ast (js2-xml-prop-ref-node-namespace n) v)) + (if (js2-xml-prop-ref-node-propname n) + (js2-visit-ast (js2-xml-prop-ref-node-propname n) v))) + +(defun js2-print-xml-prop-ref-node (n i) + (insert (js2-make-pad i)) + (if (js2-xml-ref-node-attr-access-p n) + (insert "@")) + (when (js2-xml-prop-ref-node-namespace n) + (js2-print-ast (js2-xml-prop-ref-node-namespace n) 0) + (insert "::")) + (if (js2-xml-prop-ref-node-propname n) + (js2-print-ast (js2-xml-prop-ref-node-propname n) 0))) + +(defstruct (js2-xml-elem-ref-node + (:include js2-xml-ref-node) + (:constructor nil) + (:constructor make-js2-xml-elem-ref-node (&key (type js2-REF_MEMBER) + (pos js2-token-beg) + len + expr + lb + rb + namespace + at-pos + colon-pos))) + "AST node for an E4X XML [expr] member-ref expression. +Syntax: + + [ '@' ] [ name '::' ] '[' expr ']' + +Examples include ns::[expr], @ns::[expr], @[expr], *::[expr] and @*::[expr]. + +Note that the form [expr] (i.e. no namespace or attribute-qualifier) +is not a legal E4X XML element-ref expression, since it's already used +for standard JavaScript element-get array indexing. Hence, a +`js2-xml-elem-ref-node' always has either the attribute-qualifier, a +non-nil namespace node, or both. + +The node starts at the @ token, if present. Otherwise it starts +at the namespace name. The node bounds extend through the closing +right-bracket, or if it is missing due to a syntax error, through the +end of the index expression." + expr ; the bracketed index expression + lb + rb) + +(put 'cl-struct-js2-xml-elem-ref-node 'js2-visitor 'js2-visit-xml-elem-ref-node) +(put 'cl-struct-js2-xml-elem-ref-node 'js2-printer 'js2-print-xml-elem-ref-node) + +(defun js2-visit-xml-elem-ref-node (n v) + (if (js2-xml-elem-ref-node-namespace n) + (js2-visit-ast (js2-xml-elem-ref-node-namespace n) v)) + (if (js2-xml-elem-ref-node-expr n) + (js2-visit-ast (js2-xml-elem-ref-node-expr n) v))) + +(defun js2-print-xml-elem-ref-node (n i) + (insert (js2-make-pad i)) + (if (js2-xml-ref-node-attr-access-p n) + (insert "@")) + (when (js2-xml-elem-ref-node-namespace n) + (js2-print-ast (js2-xml-elem-ref-node-namespace n) 0) + (insert "::")) + (insert "[") + (if (js2-xml-elem-ref-node-expr n) + (js2-print-ast (js2-xml-elem-ref-node-expr n) 0)) + (insert "]")) + +;;; Placeholder nodes for when we try parsing the XML literals structurally. + +(defstruct (js2-xml-start-tag-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-start-tag-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + name + attrs + kids + empty-p))) + "AST node for an XML start-tag. Not currently used. +The `kids' field is a lisp list of child content nodes." + name ; a `js2-xml-name-node' + attrs ; a lisp list of `js2-xml-attr-node' + empty-p) ; t if this is an empty element such as <foo bar="baz"/> + +(put 'cl-struct-js2-xml-start-tag-node 'js2-visitor 'js2-visit-xml-start-tag) +(put 'cl-struct-js2-xml-start-tag-node 'js2-printer 'js2-print-xml-start-tag) + +(defun js2-visit-xml-start-tag (n v) + (js2-visit-ast (js2-xml-start-tag-node-name n) v) + (dolist (attr (js2-xml-start-tag-node-attrs n)) + (js2-visit-ast attr v)) + (js2-visit-block n v)) + +(defun js2-print-xml-start-tag (n i) + (insert (js2-make-pad i) "<") + (js2-print-ast (js2-xml-start-tag-node-name n) 0) + (when (js2-xml-start-tag-node-attrs n) + (insert " ") + (js2-print-list (js2-xml-start-tag-node-attrs n) " ")) + (insert ">")) + +;; I -think- I'm going to make the parent node the corresponding start-tag, +;; and add the end-tag to the kids list of the parent as well. +(defstruct (js2-xml-end-tag-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-end-tag-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + name))) + "AST node for an XML end-tag. Not currently used." + name) ; a `js2-xml-name-node' + +(put 'cl-struct-js2-xml-end-tag-node 'js2-visitor 'js2-visit-xml-end-tag) +(put 'cl-struct-js2-xml-end-tag-node 'js2-printer 'js2-print-xml-end-tag) + +(defun js2-visit-xml-end-tag (n v) + (js2-visit-ast (js2-xml-end-tag-node-name n) v)) + +(defun js2-print-xml-end-tag (n i) + (insert (js2-make-pad i)) + (insert "</") + (js2-print-ast (js2-xml-end-tag-node-name n) 0) + (insert ">")) + +(defstruct (js2-xml-name-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-name-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + namespace + kids))) + "AST node for an E4X XML name. Not currently used. +Any XML name can be qualified with a namespace, hence the namespace field. +Further, any E4X name can be comprised of arbitrary JavaScript {} expressions. +The kids field is a list of `js2-name-node' and `js2-xml-js-expr-node'. +For a simple name, the kids list has exactly one node, a `js2-name-node'." + namespace) ; a `js2-string-node' + +(put 'cl-struct-js2-xml-name-node 'js2-visitor 'js2-visit-xml-name-node) +(put 'cl-struct-js2-xml-name-node 'js2-printer 'js2-print-xml-name-node) + +(defun js2-visit-xml-name-node (n v) + (js2-visit-ast (js2-xml-name-node-namespace n) v)) + +(defun js2-print-xml-name-node (n i) + (insert (js2-make-pad i)) + (when (js2-xml-name-node-namespace n) + (js2-print-ast (js2-xml-name-node-namespace n) 0) + (insert "::")) + (dolist (kid (js2-xml-name-node-kids n)) + (js2-print-ast kid 0))) + +(defstruct (js2-xml-pi-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-pi-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + name + attrs))) + "AST node for an E4X XML processing instruction. Not currently used." + name ; a `js2-xml-name-node' + attrs) ; a list of `js2-xml-attr-node' + +(put 'cl-struct-js2-xml-pi-node 'js2-visitor 'js2-visit-xml-pi-node) +(put 'cl-struct-js2-xml-pi-node 'js2-printer 'js2-print-xml-pi-node) + +(defun js2-visit-xml-pi-node (n v) + (js2-visit-ast (js2-xml-pi-node-name n) v) + (dolist (attr (js2-xml-pi-node-attrs n)) + (js2-visit-ast attr v))) + +(defun js2-print-xml-pi-node (n i) + (insert (js2-make-pad i) "<?") + (js2-print-ast (js2-xml-pi-node-name n)) + (when (js2-xml-pi-node-attrs n) + (insert " ") + (js2-print-list (js2-xml-pi-node-attrs n))) + (insert "?>")) + +(defstruct (js2-xml-cdata-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-cdata-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + content))) + "AST node for a CDATA escape section. Not currently used." + content) ; a `js2-string-node' with node-property 'quote-type 'cdata + +(put 'cl-struct-js2-xml-cdata-node 'js2-visitor 'js2-visit-xml-cdata-node) +(put 'cl-struct-js2-xml-cdata-node 'js2-printer 'js2-print-xml-cdata-node) + +(defun js2-visit-xml-cdata-node (n v) + (js2-visit-ast (js2-xml-cdata-node-content n) v)) + +(defun js2-print-xml-cdata-node (n i) + (insert (js2-make-pad i)) + (js2-print-ast (js2-xml-cdata-node-content n))) + +(defstruct (js2-xml-attr-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-attr-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + name + value + eq-pos + quote-type))) + "AST node representing a foo='bar' XML attribute value. Not yet used." + name ; a `js2-xml-name-node' + value ; a `js2-xml-name-node' + eq-pos ; buffer position of "=" sign + quote-type) ; 'single or 'double + +(put 'cl-struct-js2-xml-attr-node 'js2-visitor 'js2-visit-xml-attr-node) +(put 'cl-struct-js2-xml-attr-node 'js2-printer 'js2-print-xml-attr-node) + +(defun js2-visit-xml-attr-node (n v) + (js2-visit-ast (js2-xml-attr-node-name n) v) + (js2-visit-ast (js2-xml-attr-node-value n) v)) + +(defun js2-print-xml-attr-node (n i) + (let ((quote (if (eq (js2-xml-attr-node-quote-type n) 'single) + "'" + "\""))) + (insert (js2-make-pad i)) + (js2-print-ast (js2-xml-attr-node-name n) 0) + (insert "=" quote) + (js2-print-ast (js2-xml-attr-node-value n) 0) + (insert quote))) + +(defstruct (js2-xml-text-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-text-node (&key (type js2-XML) + (pos js2-ts-cursor) + len + content))) + "AST node for an E4X XML text node. Not currently used." + content) ; a lisp list of `js2-string-node' and `js2-xml-js-expr-node' + +(put 'cl-struct-js2-xml-text-node 'js2-visitor 'js2-visit-xml-text-node) +(put 'cl-struct-js2-xml-text-node 'js2-printer 'js2-print-xml-text-node) + +(defun js2-visit-xml-text-node (n v) + (js2-visit-ast (js2-xml-text-node-content n) v)) + +(defun js2-print-xml-text-node (n i) + (insert (js2-make-pad i)) + (dolist (kid (js2-xml-text-node-content n)) + (js2-print-ast kid))) + +(defstruct (js2-xml-comment-node + (:include js2-xml-node) + (:constructor nil) + (:constructor make-js2-xml-comment-node (&key (type js2-XML) + (pos js2-ts-cursor) + len))) + "AST node for E4X XML comment. Not currently used.") + +(put 'cl-struct-js2-xml-comment-node 'js2-visitor 'js2-visit-none) +(put 'cl-struct-js2-xml-comment-node 'js2-printer 'js2-print-xml-comment) + +(defun js2-print-xml-comment (n i) + (insert (js2-make-pad i) + (js2-node-string n))) + +;;; Node utilities + +(defsubst js2-node-line (n) + "Fetch the source line number at the start of node N. +This is O(n) in the length of the source buffer; use prudently." + (1+ (count-lines (point-min) (js2-node-abs-pos n)))) + +(defsubst js2-block-node-kid (n i) + "Return child I of node N, or nil if there aren't that many." + (nth i (js2-block-node-kids n))) + +(defsubst js2-block-node-first (n) + "Return first child of block node N, or nil if there is none." + (first (js2-block-node-kids n))) + +(defun js2-node-root (n) + "Return the root of the AST containing N. +If N has no parent pointer, returns N." + (let ((parent (js2-node-parent n))) + (if parent + (js2-node-root parent) + n))) + +(defun js2-node-position-in-parent (node &optional parent) + "Return the position of NODE in parent's block-kids list. +PARENT can be supplied if known. Positioned returned is zero-indexed. +Returns 0 if NODE is not a child of a block statement, or if NODE +is not a statement node." + (let ((p (or parent (js2-node-parent node))) + (i 0)) + (if (not (js2-block-node-p p)) + i + (or (js2-position node (js2-block-node-kids p)) + 0)))) + +(defsubst js2-node-short-name (n) + "Return the short name of node N as a string, e.g. `js2-if-node'." + (substring (symbol-name (aref n 0)) + (length "cl-struct-"))) + +(defsubst js2-node-child-list (node) + "Return the child list for NODE, a lisp list of nodes. +Works for block nodes, array nodes, obj literals, funarg lists, +var decls and try nodes (for catch clauses). Note that you should call +`js2-block-node-kids' on the function body for the body statements. +Returns nil for zero-length child lists or unsupported nodes." + (cond + ((js2-function-node-p node) + (js2-function-node-params node)) + ((js2-block-node-p node) + (js2-block-node-kids node)) + ((js2-try-node-p node) + (js2-try-node-catch-clauses node)) + ((js2-array-node-p node) + (js2-array-node-elems node)) + ((js2-object-node-p node) + (js2-object-node-elems node)) + ((js2-call-node-p node) + (js2-call-node-args node)) + ((js2-new-node-p node) + (js2-new-node-args node)) + ((js2-var-decl-node-p node) + (js2-var-decl-node-kids node)) + (t + nil))) + +(defsubst js2-node-set-child-list (node kids) + "Set the child list for NODE to KIDS." + (cond + ((js2-function-node-p node) + (setf (js2-function-node-params node) kids)) + ((js2-block-node-p node) + (setf (js2-block-node-kids node) kids)) + ((js2-try-node-p node) + (setf (js2-try-node-catch-clauses node) kids)) + ((js2-array-node-p node) + (setf (js2-array-node-elems node) kids)) + ((js2-object-node-p node) + (setf (js2-object-node-elems node) kids)) + ((js2-call-node-p node) + (setf (js2-call-node-args node) kids)) + ((js2-new-node-p node) + (setf (js2-new-node-args node) kids)) + ((js2-var-decl-node-p node) + (setf (js2-var-decl-node-kids node) kids)) + (t + (error "Unsupported node type: %s" (js2-node-short-name node)))) + kids) + +;; All because Common Lisp doesn't support multiple inheritance for defstructs. +(defconst js2-paren-expr-nodes + '(cl-struct-js2-array-comp-loop-node + cl-struct-js2-array-comp-node + cl-struct-js2-call-node + cl-struct-js2-catch-node + cl-struct-js2-do-node + cl-struct-js2-elem-get-node + cl-struct-js2-for-in-node + cl-struct-js2-for-node + cl-struct-js2-function-node + cl-struct-js2-if-node + cl-struct-js2-let-node + cl-struct-js2-new-node + cl-struct-js2-paren-node + cl-struct-js2-switch-node + cl-struct-js2-while-node + cl-struct-js2-with-node + cl-struct-js2-xml-dot-query-node) + "Node types that can have a parenthesized child expression. +In particular, nodes that respond to `js2-node-lp' and `js2-node-rp'.") + +(defsubst js2-paren-expr-node-p (node) + "Return t for nodes that typically have a parenthesized child expression. +Useful for computing the indentation anchors for arg-lists and conditions. +Note that it may return a false positive, for instance when NODE is +a `js2-new-node' and there are no arguments or parentheses." + (memq (aref node 0) js2-paren-expr-nodes)) + +;; Fake polymorphism... yech. +(defsubst js2-node-lp (node) + "Return relative left-paren position for NODE, if applicable. +For `js2-elem-get-node' structs, returns left-bracket position. +Note that the position may be nil in the case of a parse error." + (cond + ((js2-elem-get-node-p node) + (js2-elem-get-node-lb node)) + ((js2-loop-node-p node) + (js2-loop-node-lp node)) + ((js2-function-node-p node) + (js2-function-node-lp node)) + ((js2-if-node-p node) + (js2-if-node-lp node)) + ((js2-new-node-p node) + (js2-new-node-lp node)) + ((js2-call-node-p node) + (js2-call-node-lp node)) + ((js2-paren-node-p node) + (js2-node-pos node)) + ((js2-switch-node-p node) + (js2-switch-node-lp node)) + ((js2-catch-node-p node) + (js2-catch-node-lp node)) + ((js2-let-node-p node) + (js2-let-node-lp node)) + ((js2-array-comp-node-p node) + (js2-array-comp-node-lp node)) + ((js2-with-node-p node) + (js2-with-node-lp node)) + ((js2-xml-dot-query-node-p node) + (1+ (js2-infix-node-op-pos node))) + (t + (error "Unsupported node type: %s" (js2-node-short-name node))))) + +;; Fake polymorphism... blech. +(defsubst js2-node-rp (node) + "Return relative right-paren position for NODE, if applicable. +For `js2-elem-get-node' structs, returns right-bracket position. +Note that the position may be nil in the case of a parse error." + (cond + ((js2-elem-get-node-p node) + (js2-elem-get-node-lb node)) + ((js2-loop-node-p node) + (js2-loop-node-rp node)) + ((js2-function-node-p node) + (js2-function-node-rp node)) + ((js2-if-node-p node) + (js2-if-node-rp node)) + ((js2-new-node-p node) + (js2-new-node-rp node)) + ((js2-call-node-p node) + (js2-call-node-rp node)) + ((js2-paren-node-p node) + (+ (js2-node-pos node) (js2-node-len node))) + ((js2-switch-node-p node) + (js2-switch-node-rp node)) + ((js2-catch-node-p node) + (js2-catch-node-rp node)) + ((js2-let-node-p node) + (js2-let-node-rp node)) + ((js2-array-comp-node-p node) + (js2-array-comp-node-rp node)) + ((js2-with-node-p node) + (js2-with-node-rp node)) + ((js2-xml-dot-query-node-p node) + (1+ (js2-xml-dot-query-node-rp node))) + (t + (error "Unsupported node type: %s" (js2-node-short-name node))))) + +(defsubst js2-node-first-child (node) + "Returns the first element of `js2-node-child-list' for NODE." + (car (js2-node-child-list node))) + +(defsubst js2-node-last-child (node) + "Returns the last element of `js2-node-last-child' for NODE." + (car (last (js2-node-child-list node)))) + +(defun js2-node-prev-sibling (node) + "Return the previous statement in parent. +Works for parents supported by `js2-node-child-list'. +Returns nil if NODE is not in the parent, or PARENT is +not a supported node, or if NODE is the first child." + (let* ((p (js2-node-parent node)) + (kids (js2-node-child-list p)) + (sib (car kids))) + (while (and kids + (neq node (cadr kids))) + (setq kids (cdr kids) + sib (car kids))) + sib)) + +(defun js2-node-next-sibling (node) + "Return the next statement in parent block. +Returns nil if NODE is not in the block, or PARENT is not +a block node, or if NODE is the last statement." + (let* ((p (js2-node-parent node)) + (kids (js2-node-child-list p))) + (while (and kids + (neq node (car kids))) + (setq kids (cdr kids))) + (cadr kids))) + +(defun js2-node-find-child-before (pos parent &optional after) + "Find the last child that starts before POS in parent. +If AFTER is non-nil, returns first child starting after POS. +POS is an absolute buffer position. PARENT is any node +supported by `js2-node-child-list'. +Returns nil if no applicable child is found." + (let ((kids (if (js2-function-node-p parent) + (js2-block-node-kids (js2-function-node-body parent)) + (js2-node-child-list parent))) + (beg (if (js2-function-node-p parent) + (js2-node-abs-pos (js2-function-node-body parent)) + (js2-node-abs-pos parent))) + kid + result + fn + (continue t)) + (setq fn (if after '> '<)) + (while (and kids continue) + (setq kid (car kids)) + (if (funcall fn (+ beg (js2-node-pos kid)) pos) + (setq result kid + continue (if after nil t)) + (setq continue (if after t nil))) + (setq kids (cdr kids))) + result)) + +(defun js2-node-find-child-after (pos parent) + "Find first child that starts after POS in parent. +POS is an absolute buffer position. PARENT is any node +supported by `js2-node-child-list'. +Returns nil if no applicable child is found." + (js2-node-find-child-before pos parent 'after)) + +(defun js2-node-replace-child (pos parent new-node) + "Replace node at index POS in PARENT with NEW-NODE. +Only works for parents supported by `js2-node-child-list'." + (let ((kids (js2-node-child-list parent)) + (i 0)) + (while (< i pos) + (setq kids (cdr kids) + i (1+ i))) + (setcar kids new-node) + (js2-node-add-children parent new-node))) + +(defun js2-node-buffer (n) + "Return the buffer associated with AST N. +Returns nil if the buffer is not set as a property on the root +node, or if parent links were not recorded during parsing." + (let ((root (js2-node-root n))) + (and root + (js2-ast-root-p root) + (js2-ast-root-buffer root)))) + +(defsubst js2-block-node-push (n kid) + "Push js2-node KID onto the end of js2-block-node N's child list. +KID is always added to the -end- of the kids list. +Function also calls `js2-node-add-children' to add the parent link." + (let ((kids (js2-node-child-list n))) + (if kids + (setcdr kids (nconc (cdr kids) (list kid))) + (js2-node-set-child-list n (list kid))) + (js2-node-add-children n kid))) + +(defun js2-node-string (node) + (let ((buf (js2-node-buffer node)) + pos) + (unless buf + (error "No buffer available for node %s" node)) + (save-excursion + (set-buffer buf) + (buffer-substring-no-properties (setq pos (js2-node-abs-pos node)) + (+ pos (js2-node-len node)))))) + +;; Container for storing the node we're looking for in a traversal. +(defvar js2-discovered-node nil) +(make-variable-buffer-local 'js2-discovered-node) + +;; Keep track of absolute node position during traversals. +(defvar js2-visitor-offset nil) +(make-variable-buffer-local 'js2-visitor-offset) + +(defvar js2-node-search-point nil) +(make-variable-buffer-local 'js2-node-search-point) + +(when js2-mode-dev-mode-p + (defun js2-find-node-at-point () + (interactive) + (let ((node (js2-node-at-point))) + (message "%s" (or node "No node found at point")))) + (defun js2-node-name-at-point () + (interactive) + (let ((node (js2-node-at-point))) + (message "%s" (if node + (js2-node-short-name node) + "No node found at point."))))) + +(defun js2-node-at-point (&optional pos skip-comments) + "Return AST node at POS, a buffer position, defaulting to current point. +The `js2-mode-ast' variable must be set to the current parse tree. +Signals an error if the AST (`js2-mode-ast') is nil. +Always returns a node - if it can't find one, it returns the root. +If SKIP-COMMENTS is non-nil, comment nodes are ignored." + (let ((ast js2-mode-ast) + result) + (unless ast + (error "No JavaScript AST available")) + ;; Look through comments first, since they may be inside nodes that + ;; would otherwise report a match. + (setq pos (or pos (point)) + result (if (> pos (js2-node-abs-end ast)) + ast + (if (not skip-comments) + (js2-comment-at-point pos)))) + (unless result + (setq js2-discovered-node nil + js2-visitor-offset 0 + js2-node-search-point pos) + (unwind-protect + (catch 'js2-visit-done + (js2-visit-ast ast #'js2-node-at-point-visitor)) + (setq js2-visitor-offset nil + js2-node-search-point nil)) + (setq result js2-discovered-node)) + ;; may have found a comment beyond end of last child node, + ;; since visiting the ast-root looks at the comment-list last. + (if (and skip-comments + (js2-comment-node-p result)) + (setq result nil)) + (or result js2-mode-ast))) + +(defun js2-node-at-point-visitor (node end-p) + (let ((rel-pos (js2-node-pos node)) + abs-pos + abs-end + (point js2-node-search-point)) + (cond + (end-p + ;; this evaluates to a non-nil return value, even if it's zero + (decf js2-visitor-offset rel-pos)) + ;; we already looked for comments before visiting, and don't want them now + ((js2-comment-node-p node) + nil) + (t + (setq abs-pos (incf js2-visitor-offset rel-pos) + ;; we only want to use the node if the point is before + ;; the last character position in the node, so we decrement + ;; the absolute end by 1. + abs-end (+ abs-pos (js2-node-len node) -1)) + (cond + ;; If this node starts after search-point, stop the search. + ((> abs-pos point) + (throw 'js2-visit-done nil)) + ;; If this node ends before the search-point, don't check kids. + ((> point abs-end) + nil) + (t + ;; Otherwise point is within this node, possibly in a child. + (setq js2-discovered-node node) + t)))))) ; keep processing kids to look for more specific match + +(defsubst js2-block-comment-p (node) + "Return non-nil if NODE is a comment node of format `jsdoc' or `block'." + (and (js2-comment-node-p node) + (memq (js2-comment-node-format node) '(jsdoc block)))) + +;; TODO: put the comments in a vector and binary-search them instead +(defun js2-comment-at-point (&optional pos) + "Look through scanned comment nodes for one containing POS. +POS is a buffer position that defaults to current point. +Function returns nil if POS was not in any comment node." + (let ((ast js2-mode-ast) + (x (or pos (point))) + beg + end) + (unless ast + (error "No JavaScript AST available")) + (catch 'done + ;; Comments are stored in lexical order. + (dolist (comment (js2-ast-root-comments ast) nil) + (setq beg (js2-node-abs-pos comment) + end (+ beg (js2-node-len comment))) + (if (and (>= x beg) + (<= x end)) + (throw 'done comment)))))) + +(defun js2-mode-find-parent-fn (node) + "Find function enclosing NODE. +Returns nil if NODE is not inside a function." + (setq node (js2-node-parent node)) + (while (and node (not (js2-function-node-p node))) + (setq node (js2-node-parent node))) + (and (js2-function-node-p node) node)) + +(defun js2-mode-find-enclosing-fn (node) + "Find function or root enclosing NODE." + (if (js2-ast-root-p node) + node + (setq node (js2-node-parent node)) + (while (not (or (js2-ast-root-p node) + (js2-function-node-p node))) + (setq node (js2-node-parent node))) + node)) + +(defun js2-mode-find-enclosing-node (beg end) + "Find script or function fully enclosing BEG and END." + (let ((node (js2-node-at-point beg)) + pos + (continue t)) + (while continue + (if (or (js2-ast-root-p node) + (and (js2-function-node-p node) + (<= (setq pos (js2-node-abs-pos node)) beg) + (>= (+ pos (js2-node-len node)) end))) + (setq continue nil) + (setq node (js2-node-parent node)))) + node)) + +(defun js2-node-parent-script-or-fn (node) + "Find script or function immediately enclosing NODE. +If NODE is the ast-root, returns nil." + (if (js2-ast-root-p node) + nil + (setq node (js2-node-parent node)) + (while (and node (not (or (js2-function-node-p node) + (js2-script-node-p node)))) + (setq node (js2-node-parent node))) + node)) + +(defsubst js2-nested-function-p (node) + "Return t if NODE is a nested function, or is inside a nested function." + (js2-function-node-p (if (js2-function-node-p node) + (js2-node-parent-script-or-fn node) + (js2-node-parent-script-or-fn + (js2-node-parent-script-or-fn node))))) + +(defsubst js2-mode-shift-kids (kids start offset) + (dolist (kid kids) + (if (> (js2-node-pos kid) start) + (incf (js2-node-pos kid) offset)))) + +(defsubst js2-mode-shift-children (parent start offset) + "Update start-positions of all children of PARENT beyond START." + (let ((root (js2-node-root parent))) + (js2-mode-shift-kids (js2-node-child-list parent) start offset) + (js2-mode-shift-kids (js2-ast-root-comments root) start offset))) + +(defsubst js2-node-is-descendant (node ancestor) + "Return t if NODE is a descendant of ANCESTOR." + (while (and node + (neq node ancestor)) + (setq node (js2-node-parent node))) + node) + +;;; visitor infrastructure + +(defun js2-visit-none (node callback) + "Visitor for AST node that have no node children." + nil) + +(defun js2-print-none (node indent) + "Visitor for AST node with no printed representation.") + +(defun js2-print-body (node indent) + "Print a statement, or a block without braces." + (if (js2-block-node-p node) + (dolist (kid (js2-block-node-kids node)) + (js2-print-ast kid indent)) + (js2-print-ast node indent))) + +(defun js2-print-list (args &optional delimiter) + (loop with len = (length args) + for arg in args + for count from 1 + do + (js2-print-ast arg 0) + (if (< count len) + (insert (or delimiter ", "))))) + +(defun js2-print-tree (ast) + "Prints an AST to the current buffer. +Makes `js2-ast-parent-nodes' available to the printer functions." + (let ((max-lisp-eval-depth (max max-lisp-eval-depth 1500))) + (js2-print-ast ast))) + +(defun js2-print-ast (node &optional indent) + "Helper function for printing AST nodes. +Requires `js2-ast-parent-nodes' to be non-nil. +You should use `js2-print-tree' instead of this function." + (let ((printer (get (aref node 0) 'js2-printer)) + (i (or indent 0)) + (pos (js2-node-abs-pos node))) + ;; TODO: wedge comments in here somewhere + (if printer + (funcall printer node i)))) + +(defconst js2-side-effecting-tokens + (let ((tokens (make-bool-vector js2-num-tokens nil))) + (dolist (tt (list js2-ASSIGN + js2-ASSIGN_ADD + js2-ASSIGN_BITAND + js2-ASSIGN_BITOR + js2-ASSIGN_BITXOR + js2-ASSIGN_DIV + js2-ASSIGN_LSH + js2-ASSIGN_MOD + js2-ASSIGN_MUL + js2-ASSIGN_RSH + js2-ASSIGN_SUB + js2-ASSIGN_URSH + js2-BLOCK + js2-BREAK + js2-CALL + js2-CATCH + js2-CATCH_SCOPE + js2-CONST + js2-CONTINUE + js2-DEBUGGER + js2-DEC + js2-DELPROP + js2-DEL_REF + js2-DO + js2-ELSE + js2-EMPTY + js2-ENTERWITH + js2-EXPORT + js2-EXPR_RESULT + js2-FINALLY + js2-FOR + js2-FUNCTION + js2-GOTO + js2-IF + js2-IFEQ + js2-IFNE + js2-IMPORT + js2-INC + js2-JSR + js2-LABEL + js2-LEAVEWITH + js2-LET + js2-LETEXPR + js2-LOCAL_BLOCK + js2-LOOP + js2-NEW + js2-REF_CALL + js2-RETHROW + js2-RETURN + js2-RETURN_RESULT + js2-SEMI + js2-SETELEM + js2-SETELEM_OP + js2-SETNAME + js2-SETPROP + js2-SETPROP_OP + js2-SETVAR + js2-SET_REF + js2-SET_REF_OP + js2-SWITCH + js2-TARGET + js2-THROW + js2-TRY + js2-VAR + js2-WHILE + js2-WITH + js2-WITHEXPR + js2-YIELD)) + (aset tokens tt t)) + (if js2-instanceof-has-side-effects + (aset tokens js2-INSTANCEOF t)) + tokens)) + +(defun js2-node-has-side-effects (node) + "Return t if NODE has side effects." + (when node ; makes it easier to handle malformed expressions + (let ((tt (js2-node-type node))) + (cond + ;; This doubtless needs some work, since EXPR_VOID is used + ;; in several ways in Rhino, and I may not have caught them all. + ;; I'll wait for people to notice incorrect warnings. + ((and (= tt js2-EXPR_VOID) + (js2-expr-stmt-node-p node)) ; but not if EXPR_RESULT + (js2-node-has-side-effects (js2-expr-stmt-node-expr node))) + + ((= tt js2-COMMA) + (js2-node-has-side-effects (js2-infix-node-right node))) + + ((or (= tt js2-AND) + (= tt js2-OR)) + (or (js2-node-has-side-effects (js2-infix-node-right node)) + (js2-node-has-side-effects (js2-infix-node-left node)))) + + ((= tt js2-HOOK) + (and (js2-node-has-side-effects (js2-cond-node-true-expr node)) + (js2-node-has-side-effects (js2-cond-node-false-expr node)))) + + ((js2-paren-node-p node) + (js2-node-has-side-effects (js2-paren-node-expr node))) + + ((= tt js2-ERROR) ; avoid cascaded error messages + nil) + (t + (aref js2-side-effecting-tokens tt)))))) + +(defun js2-member-expr-leftmost-name (node) + "For an expr such as foo.bar.baz, return leftmost node foo. +NODE is any `js2-node' object. If it represents a member expression, +which is any sequence of property gets, element-gets, function calls, +or xml descendants/filter operators, then we look at the lexically +leftmost (first) node in the chain. If it is a name-node we return it. +Note that NODE can be a raw name-node and it will be returned as well. +If NODE is not a name-node or member expression, or if it is a member +expression whose leftmost target is not a name node, returns nil." + (let ((continue t) + result) + (while (and continue (not result)) + (cond + ((js2-name-node-p node) + (setq result node)) + ((js2-prop-get-node-p node) + (setq node (js2-prop-get-node-left node))) + ;; TODO: handle call-nodes, xml-nodes, others? + (t + (setq continue nil)))) + result)) + +(defconst js2-stmt-node-types + (list js2-BLOCK + js2-BREAK + js2-CONTINUE + js2-DEFAULT ; e4x "default xml namespace" statement + js2-DO + js2-EXPR_RESULT + js2-EXPR_VOID + js2-FOR + js2-IF + js2-RETURN + js2-SWITCH + js2-THROW + js2-TRY + js2-WHILE + js2-WITH) + "Node types that only appear in statement contexts. +The list does not include nodes that always appear as the child +of another specific statement type, such as switch-cases, +catch and finally blocks, and else-clauses. The list also excludes +nodes like yield, let and var, which may appear in either expression +or statement context, and in the latter context always have a +`js2-expr-stmt-node' parent. Finally, the list does not include +functions or scripts, which are treated separately from statements +by the JavaScript parser and runtime.") + +(defun js2-stmt-node-p (node) + "Heuristic for figuring out if NODE is a statement. +Some node types can appear in either an expression context or a +statement context, e.g. let-nodes, yield-nodes, and var-decl nodes. +For these node types in a statement context, the parent will be a +`js2-expr-stmt-node'. +Functions aren't included in the check." + (memq (js2-node-type node) js2-stmt-node-types)) + +(defsubst js2-mode-find-first-stmt (node) + "Search upward starting from NODE looking for a statement. +For purposes of this function, a `js2-function-node' counts." + (while (not (or (js2-stmt-node-p node) + (js2-function-node-p node))) + (setq node (js2-node-parent node))) + node) + +(defun js2-node-parent-stmt (node) + "Return the node's first ancestor that is a statement. +Returns nil if NODE is a `js2-ast-root'. Note that any expression +appearing in a statement context will have a parent that is a +`js2-expr-stmt-node' that will be returned by this function." + (let ((parent (js2-node-parent node))) + (if (or (null parent) + (js2-stmt-node-p parent) + (and (js2-function-node-p parent) + (neq (js2-function-node-form parent) 'FUNCTION_EXPRESSION))) + parent + (js2-node-parent-stmt parent)))) + +;; Roshan James writes: +;; Does consistent-return analysis on the function body when strict mode is +;; enabled. +;; +;; function (x) { return (x+1) } +;; +;; is ok, but +;; +;; function (x) { if (x < 0) return (x+1); } +;; +;; is not because the function can potentially return a value when the +;; condition is satisfied and if not, the function does not explicitly +;; return a value. +;; +;; This extends to checking mismatches such as "return" and "return <value>" +;; used in the same function. Warnings are not emitted if inconsistent +;; returns exist in code that can be statically shown to be unreachable. +;; Ex. +;; function (x) { while (true) { ... if (..) { return value } ... } } +;; +;; emits no warning. However if the loop had a break statement, then a +;; warning would be emitted. +;; +;; The consistency analysis looks at control structures such as loops, ifs, +;; switch, try-catch-finally blocks, examines the reachable code paths and +;; warns the user about an inconsistent set of termination possibilities. +;; +;; These flags enumerate the possible ways a statement/function can +;; terminate. These flags are used by endCheck() and by the Parser to +;; detect inconsistent return usage. +;; +;; END_UNREACHED is reserved for code paths that are assumed to always be +;; able to execute (example: throw, continue) +;; +;; END_DROPS_OFF indicates if the statement can transfer control to the +;; next one. Statement such as return dont. A compound statement may have +;; some branch that drops off control to the next statement. +;; +;; END_RETURNS indicates that the statement can return with no value. +;; END_RETURNS_VALUE indicates that the statement can return a value. +;; +;; A compound statement such as +;; if (condition) { +;; return value; +;; } +;; Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck() + +(defconst js2-END_UNREACHED 0) +(defconst js2-END_DROPS_OFF 1) +(defconst js2-END_RETURNS 2) +(defconst js2-END_RETURNS_VALUE 4) +(defconst js2-END_YIELDS 8) + +(defun js2-has-consistent-return-usage (node) + "Check that every return usage in a function body is consistent. +Returns t if the function satisfies strict mode requirement." + (let ((n (js2-end-check node))) + ;; either it doesn't return a value in any branch... + (or (js2-flag-not-set-p n js2-END_RETURNS_VALUE) + ;; or it returns a value (or is unreached) at every branch + (js2-flag-not-set-p n (logior js2-END_DROPS_OFF + js2-END_RETURNS + js2-END_YIELDS))))) + +(defun js2-end-check-if (node) + "Returns in the then and else blocks must be consistent with each other. +If there is no else block, then the return statement can fall through. +Returns logical OR of END_* flags" + (let ((th (js2-if-node-then-part node)) + (el (js2-if-node-else-part node))) + (if (null th) + js2-END_UNREACHED + (logior (js2-end-check th) (if el + (js2-end-check el) + js2-END_DROPS_OFF))))) + +(defun js2-end-check-switch (node) + "Consistency of return statements is checked between the case statements. +If there is no default, then the switch can fall through. If there is a +default, we check to see if all code paths in the default return or if +there is a code path that can fall through. +Returns logical OR of END_* flags." + (let ((rv js2-END_UNREACHED) + default-case) + ;; examine the cases + (catch 'break + (dolist (c (js2-switch-node-cases node)) + (if (js2-case-node-expr c) + (js2-set-flag rv (js2-end-check-block c)) + (setq default-case c) + (throw 'break nil)))) + + ;; we don't care how the cases drop into each other + (js2-clear-flag rv js2-END_DROPS_OFF) + + ;; examine the default + (js2-set-flag rv (if default-case + (js2-end-check default-case) + js2-END_DROPS_OFF)) + rv)) + +(defun js2-end-check-try (node) + "If the block has a finally, return consistency is checked in the +finally block. If all code paths in the finally return, then the +returns in the try-catch blocks don't matter. If there is a code path +that does not return or if there is no finally block, the returns +of the try and catch blocks are checked for mismatch. +Returns logical OR of END_* flags." + (let ((finally (js2-try-node-finally-block node)) + rv) + ;; check the finally if it exists + (setq rv (if finally + (js2-end-check (js2-finally-node-body finally)) + js2-END_DROPS_OFF)) + + ;; If the finally block always returns, then none of the returns + ;; in the try or catch blocks matter. + (when (js2-flag-set-p rv js2-END_DROPS_OFF) + (js2-clear-flag rv js2-END_DROPS_OFF) + + ;; examine the try block + (js2-set-flag rv (js2-end-check (js2-try-node-try-block node))) + + ;; check each catch block + (dolist (cb (js2-try-node-catch-clauses node)) + (js2-set-flag rv (js2-end-check (js2-catch-node-block cb))))) + rv)) + +(defun js2-end-check-loop (node) + "Return statement in the loop body must be consistent. The default +assumption for any kind of a loop is that it will eventually terminate. +The only exception is a loop with a constant true condition. Code that +follows such a loop is examined only if one can statically determine +that there is a break out of the loop. + + for(... ; ... ; ...) {} + for(... in ... ) {} + while(...) { } + do { } while(...) + +Returns logical OR of END_* flags." + (let ((rv (js2-end-check (js2-loop-node-body node))) + (condition (cond + ((js2-while-node-p node) + (js2-while-node-condition node)) + ((js2-do-node-p node) + (js2-do-node-condition node)) + ((js2-for-node-p node) + (js2-for-node-condition node))))) + + ;; check to see if the loop condition is always true + (if (and condition + (eq (js2-always-defined-boolean-p condition) 'ALWAYS_TRUE)) + (js2-clear-flag rv js2-END_DROPS_OFF)) + + ;; look for effect of breaks + (js2-set-flag rv (js2-node-get-prop node + 'CONTROL_BLOCK_PROP + js2-END_UNREACHED)) + rv)) + +(defun js2-end-check-block (node) + "A general block of code is examined statement by statement. +If any statement (even a compound one) returns in all branches, then +subsequent statements are not examined. +Returns logical OR of END_* flags." + (let* ((rv js2-END_DROPS_OFF) + (kids (js2-block-node-kids node)) + (n (car kids))) + ;; Check each statment. If the statement can continue onto the next + ;; one (i.e. END_DROPS_OFF is set), then check the next statement. + (while (and n (js2-flag-set-p rv js2-END_DROPS_OFF)) + (js2-clear-flag rv js2-END_DROPS_OFF) + (js2-set-flag rv (js2-end-check n)) + (setq kids (cdr kids) + n (car kids))) + rv)) + +(defun js2-end-check-label (node) + "A labeled statement implies that there may be a break to the label. +The function processes the labeled statement and then checks the +CONTROL_BLOCK_PROP property to see if there is ever a break to the +particular label. +Returns logical OR of END_* flags." + (let ((rv (js2-end-check (js2-labeled-stmt-node-stmt node)))) + (logior rv (js2-node-get-prop node + 'CONTROL_BLOCK_PROP + js2-END_UNREACHED)))) + +(defun js2-end-check-break (node) + "When a break is encountered annotate the statement being broken +out of by setting its CONTROL_BLOCK_PROP property. +Returns logical OR of END_* flags." + (and (js2-break-node-target node) + (js2-node-set-prop (js2-break-node-target node) + 'CONTROL_BLOCK_PROP + js2-END_DROPS_OFF)) + js2-END_UNREACHED) + +(defun js2-end-check (node) + "Examine the body of a function, doing a basic reachability analysis. +Returns a combination of flags END_* flags that indicate +how the function execution can terminate. These constitute only the +pessimistic set of termination conditions. It is possible that at +runtime certain code paths will never be actually taken. Hence this +analysis will flag errors in cases where there may not be errors. +Returns logical OR of END_* flags" + (let (kid) + (cond + ((js2-break-node-p node) + (js2-end-check-break node)) + + ((js2-expr-stmt-node-p node) + (if (setq kid (js2-expr-stmt-node-expr node)) + (js2-end-check kid) + js2-END_DROPS_OFF)) + + ((or (js2-continue-node-p node) + (js2-throw-node-p node)) + js2-END_UNREACHED) + + ((js2-return-node-p node) + (if (setq kid (js2-return-node-retval node)) + js2-END_RETURNS_VALUE + js2-END_RETURNS)) + + ((js2-loop-node-p node) + (js2-end-check-loop node)) + + ((js2-switch-node-p node) + (js2-end-check-switch node)) + + ((js2-labeled-stmt-node-p node) + (js2-end-check-label node)) + + ((js2-if-node-p node) + (js2-end-check-if node)) + + ((js2-try-node-p node) + (js2-end-check-try node)) + + ((js2-block-node-p node) + (if (null (js2-block-node-kids node)) + js2-END_DROPS_OFF + (js2-end-check-block node))) + + ((js2-yield-node-p node) + js2-END_YIELDS) + + (t + js2-END_DROPS_OFF)))) + +(defun js2-always-defined-boolean-p (node) + "Check if NODE always evaluates to true or false in boolean context. +Returns 'ALWAYS_TRUE, 'ALWAYS_FALSE, or nil if it's neither always true +nor always false." + (let ((tt (js2-node-type node)) + num) + (cond + ((or (= tt js2-FALSE) (= tt js2-NULL)) + 'ALWAYS_FALSE) + ((= tt js2-TRUE) + 'ALWAYS_TRUE) + ((= tt js2-NUMBER) + (setq num (js2-number-node-num-value node)) + (if (and (not (eq num 0.0e+NaN)) + (not (zerop num))) + 'ALWAYS_TRUE + 'ALWAYS_FALSE)) + (t + nil)))) + +(provide 'js2-ast) + +;;; js2-ast.el ends here +;;; js2-highlight.el --- JavaScript syntax coloring support + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;;; Code: + + +(defsubst js2-set-face (beg end face &optional record) + "Fontify a region. If RECORD is non-nil, record for later." + (when (plusp js2-highlight-level) + (setq beg (min (point-max) beg) + beg (max (point-min) beg) + end (min (point-max) end) + end (max (point-min) end)) + (if record + (push (list beg end face) js2-mode-fontifications) + (put-text-property beg end 'face face)))) + +(defsubst js2-set-kid-face (pos kid len face) + "Set-face on a child node. +POS is absolute buffer position of parent. +KID is the child node. +LEN is the length to fontify. +FACE is the face to fontify with." + (js2-set-face (+ pos (js2-node-pos kid)) + (+ pos (js2-node-pos kid) (js2-node-len kid)) + face)) + +(defsubst js2-fontify-kwd (start length) + (js2-set-face start (+ start length) 'font-lock-keyword-face)) + +(defsubst js2-clear-face (beg end) + (remove-text-properties beg end '(face nil + help-echo nil + point-entered nil + c-in-sws nil))) + +(defsubst js2-record-text-property (beg end prop value) + "Record a text property to set when parsing finishes." + (push (list beg end prop value) js2-mode-deferred-properties)) + +(defconst js2-ecma-global-props + (concat "^" + (regexp-opt + '("Infinity" "NaN" "undefined" "arguments") t) + "$") + "Value properties of the Ecma-262 Global Object. +Shown at or above `js2-highlight-level' 2.") + +;; might want to add the name "arguments" to this list? +(defconst js2-ecma-object-props + (concat "^" + (regexp-opt + '("prototype" "__proto__" "__parent__") t) + "$") + "Value properties of the Ecma-262 Object constructor. +Shown at or above `js2-highlight-level' 2.") + +(defconst js2-ecma-global-funcs + (concat + "^" + (regexp-opt + '("decodeURI" "decodeURIComponent" "encodeURI" "encodeURIComponent" + "eval" "isFinite" "isNaN" "parseFloat" "parseInt") t) + "$") + "Function properties of the Ecma-262 Global object. +Shown at or above `js2-highlight-level' 2.") + +(defconst js2-ecma-number-props + (concat "^" + (regexp-opt '("MAX_VALUE" "MIN_VALUE" "NaN" + "NEGATIVE_INFINITY" + "POSITIVE_INFINITY") t) + "$") + "Properties of the Ecma-262 Number constructor. +Shown at or above `js2-highlight-level' 2.") + +(defconst js2-ecma-date-props "^\\(parse\\|UTC\\)$" + "Properties of the Ecma-262 Date constructor. +Shown at or above `js2-highlight-level' 2.") + + +(defconst js2-ecma-math-props + (concat "^" + (regexp-opt + '("E" "LN10" "LN2" "LOG2E" "LOG10E" "PI" "SQRT1_2" "SQRT2") + t) + "$") + "Properties of the Ecma-262 Math object. +Shown at or above `js2-highlight-level' 2.") + + +(defconst js2-ecma-math-funcs + (concat "^" + (regexp-opt + '("abs" "acos" "asin" "atan" "atan2" "ceil" "cos" "exp" "floor" + "log" "max" "min" "pow" "random" "round" "sin" "sqrt" "tan") t) + "$") + "Function properties of the Ecma-262 Math object. +Shown at or above `js2-highlight-level' 2.") + +(defconst js2-ecma-function-props + (concat + "^" + (regexp-opt + '(;; properties of the Object prototype object + "hasOwnProperty" "isPrototypeOf" "propertyIsEnumerable" + "toLocaleString" "toString" "valueOf" + ;; properties of the Function prototype object + "apply" "call" + ;; properties of the Array prototype object + "concat" "join" "pop" "push" "reverse" "shift" "slice" "sort" + "splice" "unshift" + ;; properties of the String prototype object + "charAt" "charCodeAt" "fromCharCode" "indexOf" "lastIndexOf" + "localeCompare" "match" "replace" "search" "split" "substring" + "toLocaleLowerCase" "toLocaleUpperCase" "toLowerCase" + "toUpperCase" + ;; properties of the Number prototype object + "toExponential" "toFixed" "toPrecision" + ;; properties of the Date prototype object + "getDate" "getDay" "getFullYear" "getHours" "getMilliseconds" + "getMinutes" "getMonth" "getSeconds" "getTime" + "getTimezoneOffset" "getUTCDate" "getUTCDay" "getUTCFullYear" + "getUTCHours" "getUTCMilliseconds" "getUTCMinutes" "getUTCMonth" + "getUTCSeconds" "setDate" "setFullYear" "setHours" + "setMilliseconds" "setMinutes" "setMonth" "setSeconds" "setTime" + "setUTCDate" "setUTCFullYear" "setUTCHours" "setUTCMilliseconds" + "setUTCMinutes" "setUTCMonth" "setUTCSeconds" "toDateString" + "toLocaleDateString" "toLocaleString" "toLocaleTimeString" + "toTimeString" "toUTCString" + ;; properties of the RegExp prototype object + "exec" "test" + ;; SpiderMonkey/Rhino extensions, versions 1.5+ + "toSource" "__defineGetter__" "__defineSetter__" + "__lookupGetter__" "__lookupSetter__" "__noSuchMethod__" + "every" "filter" "forEach" "lastIndexOf" "map" "some") + t) + "$") + "Built-in functions defined by Ecma-262 and SpiderMonkey extensions. +Shown at or above `js2-highlight-level' 3.") + +(defsubst js2-parse-highlight-prop-get (parent target prop call-p) + (let ((target-name (and target + (js2-name-node-p target) + (js2-name-node-name target))) + (prop-name (if prop (js2-name-node-name prop))) + (level1 (>= js2-highlight-level 1)) + (level2 (>= js2-highlight-level 2)) + (level3 (>= js2-highlight-level 3)) + pos + face) + (when level2 + (if call-p + (cond + ((and target prop) + (cond + ((and level3 (string-match js2-ecma-function-props prop-name)) + (setq face 'font-lock-builtin-face)) + ((and target-name prop) + (cond + ((string= target-name "Date") + (if (string-match js2-ecma-date-props prop-name) + (setq face 'font-lock-builtin-face))) + ((string= target-name "Math") + (if (string-match js2-ecma-math-funcs prop-name) + (setq face 'font-lock-builtin-face))))))) + (prop + (if (string-match js2-ecma-global-funcs prop-name) + (setq face 'font-lock-builtin-face)))) + (cond + ((and target prop) + (cond + ((string= target-name "Number") + (if (string-match js2-ecma-number-props prop-name) + (setq face 'font-lock-constant-face))) + ((string= target-name "Math") + (if (string-match js2-ecma-math-props prop-name) + (setq face 'font-lock-constant-face))))) + (prop + (if (string-match js2-ecma-object-props prop-name) + (setq face 'font-lock-constant-face))))) + (when face + (js2-set-face (setq pos (+ (js2-node-pos parent) ; absolute + (js2-node-pos prop))) ; relative + (+ pos (js2-node-len prop)) + face))))) + +(defun js2-parse-highlight-member-expr-node (node) + "Perform syntax highlighting of EcmaScript built-in properties. +The variable `js2-highlight-level' governs this highighting." + (let (face target prop name pos end parent call-p callee) + (cond + ;; case 1: simple name, e.g. foo + ((js2-name-node-p node) + (setq name (js2-name-node-name node)) + ;; possible for name to be nil in rare cases - saw it when + ;; running js2-mode on an elisp buffer. Might as well try to + ;; make it so js2-mode never barfs. + (when name + (setq face (if (string-match js2-ecma-global-props name) + 'font-lock-constant-face)) + (when face + (setq pos (js2-node-pos node) + end (+ pos (js2-node-len node))) + (js2-set-face pos end face)))) + + ;; case 2: property access or function call + ((or (js2-prop-get-node-p node) + ;; highlight function call if expr is a prop-get node + ;; or a plain name (i.e. unqualified function call) + (and (setq call-p (js2-call-node-p node)) + (setq callee (js2-call-node-target node)) ; separate setq! + (or (js2-prop-get-node-p callee) + (js2-name-node-p callee)))) + (setq parent node + node (if call-p callee node)) + (if (and call-p (js2-name-node-p callee)) + (setq prop callee) + (setq target (js2-prop-get-node-left node) + prop (js2-prop-get-node-right node))) + (cond + ((js2-name-node-p target) + (if (js2-name-node-p prop) + ;; case 2a: simple target, simple prop name, e.g. foo.bar + (js2-parse-highlight-prop-get parent target prop call-p) + ;; case 2b: simple target, complex name, e.g. foo.x[y] + (js2-parse-highlight-prop-get parent target nil call-p))) + ((js2-name-node-p prop) + ;; case 2c: complex target, simple name, e.g. x[y].bar + (js2-parse-highlight-prop-get parent target prop call-p))))))) + +(defun js2-parse-highlight-member-expr-fn-name (expr) + "Highlight the `baz' in function foo.bar.baz(args) {...}. +This is experimental Rhino syntax. EXPR is the foo.bar.baz member expr. +We currently only handle the case where the last component is a prop-get +of a simple name. Called before EXPR has a parent node." + (let (pos + (name (and (js2-prop-get-node-p expr) + (js2-prop-get-node-right expr)))) + (when (js2-name-node-p name) + (js2-set-face (setq pos (+ (js2-node-pos expr) ; parent is absolute + (js2-node-pos name))) + (+ pos (js2-node-len name)) + 'font-lock-function-name-face + 'record)))) + +;; source: http://jsdoc.sourceforge.net/ +;; Note - this syntax is for Google's enhanced jsdoc parser that +;; allows type specifications, and needs work before entering the wild. + +(defconst js2-jsdoc-param-tag-regexp + (concat "^\\s-*\\*+\\s-*\\(@" + "\\(?:param\\|argument\\)" + "\\)" + "\\s-*\\({[^}]+}\\)?" ; optional type + "\\s-*\\([a-zA-Z0-9_$]+\\)?" ; name + "\\>") + "Matches jsdoc tags with optional type and optional param name.") + +(defconst js2-jsdoc-typed-tag-regexp + (concat "^\\s-*\\*+\\s-*\\(@\\(?:" + (regexp-opt + '("requires" "return" "returns" "throw" "throws")) + "\\)\\)\\s-*\\({[^}]+}\\)?") + "Matches jsdoc tags with optional type.") + +(defconst js2-jsdoc-arg-tag-regexp + (concat "^\\s-*\\*+\\s-*\\(@\\(?:" + (regexp-opt + '("base" "extends" "member" "type" "version")) + "\\)\\)\\s-+\\([^ \t]+\\)") + "Matches jsdoc tags with a single argument.") + +(defconst js2-jsdoc-empty-tag-regexp + (concat "^\\s-*\\*+\\s-*\\(@\\(?:" + (regexp-opt + '("addon" "author" "class" "constructor" "deprecated" "exec" + "exception" "fileoverview" "final" "ignore" "private")) + "\\)\\)\\s-*") + "Matches empty jsdoc tags.") + +(defconst js2-jsdoc-link-tag-regexp + "{\\(@link\\)\\s-+\\([^#}\n]+\\)\\(#.+\\)?}" + "Matches a jsdoc link tag.") + +(defconst js2-jsdoc-see-tag-regexp + "^\\s-*\\*+\\s-*\\(@see\\)\\s-+\\([^#}\n]+\\)\\(#.+\\)?" + "Matches a jsdoc @see tag.") + +(defconst js2-jsdoc-html-tag-regexp + "\\(</?\\)\\([a-zA-Z]+\\)\\s-*\\(/?>\\)" + "Matches a simple (no attributes) html start- or end-tag.") + +(defsubst js2-jsdoc-highlight-helper () + (js2-set-face (match-beginning 1) + (match-end 1) + 'js2-jsdoc-tag-face) + (if (match-beginning 2) + (if (save-excursion + (goto-char (match-beginning 2)) + (= (char-after) ?{)) + (js2-set-face (1+ (match-beginning 2)) + (1- (match-end 2)) + 'js2-jsdoc-type-face) + (js2-set-face (match-beginning 2) + (match-end 2) + 'js2-jsdoc-value-face))) + (if (match-beginning 3) + (js2-set-face (match-beginning 3) + (match-end 3) + 'js2-jsdoc-value-face))) + +(defun js2-highlight-jsdoc (ast) + "Highlight doc comment tags." + (let ((comments (js2-ast-root-comments ast)) + beg end) + (save-excursion + (dolist (node comments) + (when (eq (js2-comment-node-format node) 'jsdoc) + (setq beg (js2-node-abs-pos node) + end (+ beg (js2-node-len node))) + (save-restriction + (narrow-to-region beg end) + (dolist (re (list js2-jsdoc-param-tag-regexp + js2-jsdoc-typed-tag-regexp + js2-jsdoc-arg-tag-regexp + js2-jsdoc-link-tag-regexp + js2-jsdoc-see-tag-regexp + js2-jsdoc-empty-tag-regexp)) + (goto-char beg) + (while (re-search-forward re nil t) + (js2-jsdoc-highlight-helper))) + ;; simple highlighting for html tags + (goto-char beg) + (while (re-search-forward js2-jsdoc-html-tag-regexp nil t) + (js2-set-face (match-beginning 1) + (match-end 1) + 'js2-jsdoc-html-tag-delimiter-face) + (js2-set-face (match-beginning 2) + (match-end 2) + 'js2-jsdoc-html-tag-name-face) + (js2-set-face (match-beginning 3) + (match-end 3) + 'js2-jsdoc-html-tag-delimiter-face)))))))) + +(defun js2-highlight-assign-targets (node left right) + "Highlight function properties and external variables." + (let (leftpos end name) + ;; highlight vars and props assigned function values + (when (js2-function-node-p right) + (cond + ;; var foo = function() {...} + ((js2-name-node-p left) + (setq name left)) + + ;; foo.bar.baz = function() {...} + ((and (js2-prop-get-node-p left) + (js2-name-node-p (js2-prop-get-node-right left))) + (setq name (js2-prop-get-node-right left)))) + + (when name + (js2-set-face (setq leftpos (js2-node-abs-pos name)) + (+ leftpos (js2-node-len name)) + 'font-lock-function-name-face + 'record))) + + ;; save variable assignments so we can check for undeclared later + ;; (can't do it here since var decls can come at end of script) + (when (and js2-highlight-external-variables + (setq name (js2-member-expr-leftmost-name left))) + (push (list name js2-current-scope + (setq leftpos (js2-node-abs-pos name)) + (setq end (+ leftpos (js2-node-len name)))) + js2-recorded-assignments)))) + +(defun js2-highlight-undeclared-vars () + "After entire parse is finished, look for undeclared variable assignments. +Have to wait until entire buffer is parsed, since JavaScript permits var +decls to occur after they're used. + +We currently use a simple heuristic to rule out complaining about built-ins: +if the name is capitalized we don't highlight it. This could be improved a +bit by declaring all the Ecma global object, constructor and function names +in a hashtable, but we'd still wind up complaining about all the DHTML +builtins, the Mozilla builtins, etc." + (let (name first-char) + (dolist (entry js2-recorded-assignments) + (destructuring-bind (name-node scope pos end) entry + (setq name (js2-name-node-name name-node) + first-char (aref name 0)) + (unless (or (and (>= first-char ?A) (<= first-char ?Z)) + (js2-get-defining-scope scope name)) + (js2-set-face pos end 'js2-external-variable-face 'record) + (js2-record-text-property pos end 'help-echo "Undeclared variable") + (js2-record-text-property pos end 'point-entered #'js2-echo-help)))) + (setq js2-recorded-assignments nil))) + +(provide 'js2-highlight) + +;;; js2-highlight.el ends here +;;; js2-browse.el --- browsing/hierarchy support for js2-mode + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;; Commentary: +;; +;; We currently only support imenu, but eventually should support speedbar and +;; possibly other browsing mechanisms. +;; +;; The basic strategy is to identify function assignment targets of the form +;; `foo.bar.baz', convert them to (list foo bar baz <position>), and push the +;; list into `js2-imenu-recorder'. The lists are merged into a trie-like tree +;; for imenu after parsing is finished. +;; +;; A `foo.bar.baz' assignment target may be expressed in many ways in +;; JavaScript, and the general problem is undecidable. However, several forms +;; are readily recognizable at parse-time; the forms we attempt to recognize +;; include: +;; +;; function foo() -- function declaration +;; foo = function() -- function expression assigned to variable +;; foo.bar.baz = function() -- function expr assigned to nested property-get +;; foo = {bar: function()} -- fun prop in object literal assigned to var +;; foo = {bar: {baz: function()}} -- inside nested object literal +;; foo.bar = {baz: function()}} -- obj lit assigned to nested prop get +;; a.b = {c: {d: function()}} -- nested obj lit assigned to nested prop get +;; foo = {get bar() {...}} -- getter/setter in obj literal +;; function foo() {function bar() {...}} -- nested function +;; foo['a'] = function() -- fun expr assigned to deterministic element-get +;; +;; This list boils down to a few forms that can be combined recursively. +;; Top-level named function declarations include both the left-hand (name) +;; and the right-hand (function value) expressions needed to produce an imenu +;; entry. The other "right-hand" forms we need to look for are: +;; - functions declared as props/getters/setters in object literals +;; - nested named function declarations +;; The "left-hand" expressions that functions can be assigned to include: +;; - local/global variables +;; - nested property-get expressions like a.b.c.d +;; - element gets like foo[10] or foo['bar'] where the index +;; expression can be trivially converted to a property name. They +;; effectively then become property gets. +;; +;; All the different definition types are canonicalized into the form +;; foo.bar.baz = position-of-function-keyword +;; +;; We need to build a trie-like structure for imenu. As an example, +;; consider the following JavaScript code: +;; +;; a = function() {...} // function at position 5 +;; b = function() {...} // function at position 25 +;; foo = function() {...} // function at position 100 +;; foo.bar = function() {...} // function at position 200 +;; foo.bar.baz = function() {...} // function at position 300 +;; foo.bar.zab = function() {...} // function at position 400 +;; +;; During parsing we accumulate an entry for each definition in +;; the variable `js2-imenu-recorder', like so: +;; +;; '((a 5) +;; (b 25) +;; (foo 100) +;; (foo bar 200) +;; (foo bar baz 300) +;; (foo bar zab 400)) +;; +;; After parsing these entries are merged into this alist-trie: +;; +;; '((a . 1) +;; (b . 2) +;; (foo (<definition> . 3) +;; (bar (<definition> . 6) +;; (baz . 100) +;; (zab . 200)))) +;; +;; Note the wacky need for a <definition> name. The token can be anything +;; that isn't a valid JavaScript identifier, because you might make foo +;; a function and then start setting properties on it that are also functions. + +;;; Code: + + +(defsubst js2-prop-node-name (node) + "Return the name of a node that may be a property-get/property-name. +If NODE is not a valid name-node, string-node or integral number-node, +returns nil. Otherwise returns the string name/value of the node." + (cond + ((js2-name-node-p node) + (js2-name-node-name node)) + ((js2-string-node-p node) + (js2-string-node-value 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"))) + +(defsubst js2-node-qname-component (node) + "Test function: return the name of this node, if it contributes to a qname. +Returns nil if the node doesn't contribute." + (copy-sequence + (or (js2-prop-node-name node) + (if (and (js2-function-node-p node) + (js2-function-node-name node)) + (js2-name-node-name (js2-function-node-name node)))))) + +(defsubst js2-record-function-qname (fn-node qname) + "Associate FN-NODE with its QNAME for later lookup. +This is used in postprocessing the chain list. When we find a chain +whose first element is a js2-THIS keyword node, we look up the parent +function and see (using this map) whether it is the tail of a chain. +If so, we replace the this-node with a copy of the parent's qname." + (unless js2-imenu-function-map + (setq js2-imenu-function-map (make-hash-table :test 'eq))) + (puthash fn-node qname js2-imenu-function-map)) + +(defun js2-record-imenu-functions (node &optional var) + "Record function definitions for imenu. +NODE is a function node or an object literal. +VAR, if non-nil, is the expression that NODE is being assigned to." + (when js2-parse-ide-mode + (let ((fun-p (js2-function-node-p node)) + qname left fname-node pos) + (cond + ;; non-anonymous function declaration? + ((and fun-p + (not var) + (setq fname-node (js2-function-node-name node))) + (push (setq qname (list fname-node (js2-node-pos node))) + js2-imenu-recorder) + (js2-record-function-qname node qname)) + + ;; for remaining forms, compute left-side tree branch first + ((and var (setq qname (js2-compute-nested-prop-get var))) + (cond + ;; foo.bar.baz = function + (fun-p + (push (nconc qname (list (js2-node-pos node))) + js2-imenu-recorder) + (js2-record-function-qname node qname)) + ;; foo.bar.baz = object-literal + ;; look for nested functions: {a: {b: function() {...} }} + ((js2-object-node-p node) + (js2-record-object-literal node qname)))))))) + +(defun js2-compute-nested-prop-get (node) + "If NODE is of form foo.bar.baz, return component nodes as a list. +Otherwise returns nil. Element-gets can be treated as property-gets +if the index expression is a name, a string, or a positive integer." + (let (left right head) + (cond + ((or (js2-name-node-p node) + (js2-this-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) ; includes elem-get nodes + (setq left (js2-prop-get-node-left node) + right (js2-prop-get-node-right node)) + (if (and (or (js2-prop-get-node-p left) ; left == foo.bar + (js2-name-node-p left) + (js2-this-node-p left)) ; or left == foo + (or (js2-name-node-p right) ; .bar + (js2-string-node-p right) ; ['bar'] + (and (js2-number-node-p right) ; [10] + (string-match "^[0-9]+$" + (js2-number-node-value right))))) + (if (setq head (js2-compute-nested-prop-get left)) + (nconc head (list right)))))))) + +(defun js2-record-object-literal (node qname) + "Recursively process an object literal looking for functions. +NODE is an object literal that is the right-hand child of an assignment +expression. QNAME is a list of nodes representing the assignment target, +e.g. for foo.bar.baz = {...}, QNAME is (foo-node bar-node baz-node). +We do a depth-first traversal of NODE. Any functions we find are prefixed +with QNAME plus the property name of the function and appended to the +variable `js2-imenu-recorder'." + ;; Elements are relative to parent position, which is still absolute, + ;; since the parser passes the assignment target and value expressions + ;; to us before they are added as children of the assignment node. + (let ((pos (js2-node-pos node)) + left right) + (dolist (e (js2-object-node-elems node)) ; e is a `js2-object-prop-node' + (setq left (js2-infix-node-left e)) + (cond + ;; foo: function() {...} + ((js2-function-node-p (setq right (js2-infix-node-right e))) + (when (js2-prop-node-name left) + ;; As a policy decision, we record the position of the property, + ;; not the position of the `function' keyword, since the property + ;; is effectively the name of the function. + (push (append qname (list left) (list (+ pos (js2-node-pos e)))) + js2-imenu-recorder) + (js2-record-function-qname right qname))) + ;; foo: {object-literal} -- add foo to qname and recurse + ((js2-object-node-p right) + (js2-record-object-literal right + (append qname (list (js2-infix-node-left e))))))))) + +(defsubst js2-node-top-level-decl-p (node) + "Return t if NODE's name is defined in the top-level scope. +Also returns t if NODE's name is not defined in any scope, since it implies +that it's an external variable, which must also be in the top-level scope." + (let* ((name (js2-prop-node-name node)) + (this-scope (js2-node-get-enclosing-scope node)) + defining-scope) + (cond + ((js2-this-node-p node) + nil) + ((null this-scope) + t) + ((setq defining-scope (js2-get-defining-scope this-scope name)) + (js2-ast-root-p defining-scope)) + (t t)))) + +(defun js2-browse-postprocess-chains (chains) + "Modify function-declaration name chains after parsing finishes. +Some of the information is only available after the parse tree is complete. +For instance, following a 'this' reference requires a parent function node." + (let (result head fn parent-chain p elem) + (dolist (chain chains) + ;; examine the head of each node to get its defining scope + (setq head (car chain)) + (cond + ;; if top-level/external, keep as-is + ((js2-node-top-level-decl-p head) + (push chain result)) + ;; check for a this-reference + ((eq (js2-node-type head) js2-THIS) + (setq fn (js2-node-parent-script-or-fn head)) + ;; if there is no parent function, or if the parent function + ;; is nested, discard the head node and keep the rest of the chain. + (if (or (null fn) (js2-nested-function-p fn)) + (push (cdr chain) result) + ;; else look up parent in function-map. If not found, discard chain. + (when (setq parent-chain (and js2-imenu-function-map + (gethash fn js2-imenu-function-map))) + ;; else discard head node and prefix parent fn qname, which is + ;; the parent-chain sans tail, to this chain. + (push (append (butlast parent-chain) (cdr chain)) result)))))) + ;; finally replace each node in each chain with its name. + (dolist (chain result) + (setq p chain) + (while p + (if (js2-node-p (setq elem (car p))) + (setcar p (js2-node-qname-component elem))) + (setq p (cdr p)))) + result)) + +;; Merge name chains into a trie-like tree structure of nested lists. +;; To simplify construction of the trie, we first build it out using the rule +;; that the trie consists of lists of pairs. Each pair is a 2-element array: +;; [key, num-or-list]. The second element can be a number; if so, this key +;; is a leaf-node with only one value. (I.e. there is only one declaration +;; associated with the key at this level.) Otherwise the second element is +;; a list of pairs, with the rule applied recursively. This symmetry permits +;; a simple recursive formulation. +;; +;; js2-mode is building the data structure for imenu. The imenu documentation +;; claims that it's the structure above, but in practice it wants the children +;; at the same list level as the key for that level, which is how I've drawn +;; the "Expected final result" above. We'll postprocess the trie to remove the +;; list wrapper around the children at each level. +;; +;; A completed nested imenu-alist entry looks like this: +;; '(("foo" +;; ("<definition>" . 7) +;; ("bar" +;; ("a" . 40) +;; ("b" . 60)))) +;; +;; In particular, the documentation for `imenu--index-alist' says that +;; a nested sub-alist element looks like (INDEX-NAME SUB-ALIST). +;; The sub-alist entries immediately follow INDEX-NAME, the head of the list. + +(defsubst js2-treeify (lst) + "Convert (a b c d) to (a ((b ((c d)))))" + (if (null (cddr lst)) ; list length <= 2 + lst + (list (car lst) (list (js2-treeify (cdr lst)))))) + +(defun js2-build-alist-trie (chains trie) + "Merge declaration name chains into a trie-like alist structure for imenu. +CHAINS is the qname chain list produced during parsing. TRIE is a +list of elements built up so far." + (let (head tail pos branch kids) + (dolist (chain chains) + (setq head (car chain) + tail (cdr chain) + pos (if (numberp (car tail)) (car tail)) + branch (js2-find-if (lambda (n) + (string= (car n) head)) + trie) + kids (second branch)) + (cond + ;; case 1: this key isn't in the trie yet + ((null branch) + (if trie + (setcdr (last trie) (list (js2-treeify chain))) + (setq trie (list (js2-treeify chain))))) + + ;; case 2: key is present with a single number entry: replace w/ list + ;; ("a1" 10) + ("a1" 20) => ("a1" (("<definition>" 10) + ;; ("<definition>" 20))) + ((numberp kids) + (setcar (cdr branch) + (list (list "<definition-1>" kids) + (if pos + (list "<definition-2>" pos) + (js2-treeify tail))))) + + ;; case 3: key is there (with kids), and we're a number entry + (pos + (setcdr (last kids) + (list + (list (format "<definition-%d>" + (1+ (loop for kid in kids + count (eq ?< (aref (car kid) 0))))) + pos)))) + + ;; case 4: key is there with kids, need to merge in our chain + (t + (js2-build-alist-trie (list tail) kids)))) + trie)) + +(defun js2-flatten-trie (trie) + "Convert TRIE to imenu-format. +Recurses through nodes, and for each one whose second element is a list, +appends the list's flattened elements to the current element. Also +changes the tails into conses. For instance, this pre-flattened trie + +'(a ((b 20) + (c ((d 30) + (e 40))))) + +becomes + +'(a (b . 20) + (c (d . 30) + (e . 40))) + +Note that the root of the trie has no key, just a list of chains. +This is also true for the value of any key with multiple children, +e.g. key 'c' in the example above." + (cond + ((listp (car trie)) + (mapcar #'js2-flatten-trie trie)) + (t + (if (numberp (second trie)) + (cons (car trie) (second trie)) + ;; else pop list and append its kids + (apply #'append (list (car trie)) (js2-flatten-trie (cdr trie))))))) + +(defun js2-build-imenu-index () + "Turn `js2-imenu-recorder' into an imenu data structure." + (unless (eq js2-imenu-recorder 'empty) + (let* ((chains (js2-browse-postprocess-chains js2-imenu-recorder)) + (result (js2-build-alist-trie chains nil))) + (js2-flatten-trie result)))) + +(defun js2-test-print-chains (chains) + "Print a list of qname chains. +Each element of CHAINS is a list of the form (NODE [NODE *] pos); +i.e. one or more nodes, and an integer position as the list tail." + (mapconcat (lambda (chain) + (concat "(" + (mapconcat (lambda (elem) + (if (js2-node-p elem) + (or (js2-node-qname-component elem) + "nil") + (number-to-string elem))) + chain + " ") + ")")) + chains + "\n")) + + +(provide 'js2-browse) + +;;; js2-browse.el ends here +;;; js2-parse.el --- JavaScript parser + +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Keywords: javascript languages + +;; Commentary: + +;; This is based on Rhino's parser and tries to follow its code +;; structure as closely as practical, so that changes to the Rhino +;; parser can easily be propagated into this code. However, Rhino +;; does not currently generate a usable AST representation, at least +;; from an IDE perspective, so we build our own more suitable AST. + +;; The AST node structures are defined in `js2-ast.el'. +;; Every parser function that creates and returns an AST node has +;; the following responsibilities: + +;; 1) set the node start to the absolute buffer start position +;; 2) set the node length to include any closing chars (RC, SEMI) +;; 3) fix up any child-node starts to be relative to this node +;; 4) set any field positions (e.g. keywords) relative to this node +;; 5) report any child nodes with `js2-node-add-children' +;; (note that this call fixes up start positions by default) + +;; The resulting AST has all node start positions relative to the +;; parent nodes; only the root has an absolute start position. + +;; Note: fontification is done inline while parsing. It used to be +;; done in a second pass over the AST, but doing it inline is about +;; twice as fast. Most of the fontification happens when tokens are +;; scanned, and the parser has a few spots that perform extra +;; fontification. In addition to speed, a second benefit of inline +;; parsing is that if a long parse is interrupted, everything parsed +;; so far is still fontified. + +;; The editing mode that uses this parser, `js2-mode', directs the +;; parser to check periodically for user input. If user input +;; arrives, the parse is abandoned, except for the highlighting that +;; has occurred so far, and a re-parse is rescheduled for when Emacs +;; becomes idle again. This works pretty well, but could be better. +;; In particular, when the user input has not resulted in changes to +;; the buffer (for instance, navigation input), the parse tree built +;; so far should not be discarded, and the parse should continue where +;; it left off. It will be some work to create what amounts to a +;; continuation, but it should not be unreasonably difficult. + +;; TODO: +;; - make non-editing input restart parse at previous continuation +;; - in Eclipse, sibling nodes never overlap start/end ranges +;; - for getters, prop name and function nodes overlap +;; - should write a debug tree visitor to look for overlaps +;; - mark array and object literals as "destructuring" (node prop?) +;; so we can syntax-highlight them properly. +;; - figure out a way not to store value in string/name nodes +;; - needs a solution for synthetic nodes + +;;; Code + +(eval-and-compile + (require 'cl)) ; for delete-if + + +(defconst js2-version "1.7.0" + "Version of JavaScript supported, plus minor js2 version.") + +(defmacro js2-record-face (face) + "Record a style run of FACE for the current token." + `(js2-set-face js2-token-beg js2-token-end ,face 'record)) + +(defsubst js2-node-end (n) + "Computes the absolute end of node N. +Use with caution! Assumes `js2-node-pos' is -absolute-, which +is only true until the node is added to its parent; i.e., while parsing." + (+ (js2-node-pos n) + (js2-node-len n))) + +(defsubst js2-record-comment () + (push (make-js2-comment-node :len (- js2-token-end js2-token-beg) + :format js2-ts-comment-type) + js2-scanned-comments) + (when js2-parse-ide-mode + (js2-record-face 'font-lock-comment-face) + (when (memq js2-ts-comment-type '(html preprocessor)) + ;; Tell cc-engine the bounds of the comment. + (put-text-property js2-token-beg (1- js2-token-end) 'c-in-sws t)))) + +;; This function is called depressingly often, so it should be fast. +;; Most of the time it's looking at the same token it peeked before. +(defsubst js2-peek-token () + "Returns the next token without consuming it. +If previous token was consumed, calls scanner to get new token. +If previous token was -not- consumed, returns it (idempotent). + +This function will not return a newline (js2-EOL) - instead, it +gobbles newlines until it finds a non-newline token, and flags +that token as appearing just after a newline. + +This function will also not return a js2-COMMENT. Instead, it +records comments found in `js2-scanned-comments'. If the token +returned by this function immediately follows a jsdoc comment, +the token is flagged as such. + +Note that this function always returned the un-flagged token! +The flags, if any, are saved in `js2-current-flagged-token'." + (if (/= js2-current-flagged-token js2-EOF) ; last token not consumed + js2-current-token ; most common case - return already-peeked token + (let ((tt (js2-get-token)) ; call scanner + saw-eol + face) + ;; process comments and whitespace + (while (or (= tt js2-EOL) + (= tt js2-COMMENT)) + (if (= tt js2-EOL) + (setq saw-eol t) + (setq saw-eol nil) + (if js2-record-comments + (js2-record-comment))) + (setq tt (js2-get-token))) ; call scanner + + (setq js2-current-token tt + js2-current-flagged-token (if saw-eol + (logior tt js2-ti-after-eol) + tt)) + ;; perform lexical fontification as soon as token is scanned + (when js2-parse-ide-mode + (cond + ((minusp tt) + (js2-record-face 'js2-error-face)) + ((setq face (aref js2-kwd-tokens tt)) + (js2-record-face face)) + ((and (= tt js2-NAME) + (equal js2-ts-string "undefined")) + (js2-record-face 'font-lock-constant-face)))) + tt))) ; return unflagged token + +(defsubst js2-peek-flagged-token () + "Returns the current token along with any flags set for it." + (js2-peek-token) + js2-current-flagged-token) + +(defsubst js2-consume-token () + (setq js2-current-flagged-token js2-EOF)) + +(defsubst js2-next-token () + (prog1 + (js2-peek-token) + (js2-consume-token))) + +(defsubst js2-next-flagged-token () + (js2-peek-token) + (prog1 js2-current-flagged-token + (js2-consume-token))) + +(defsubst js2-match-token (match) + "Consume and return t if next token matches MATCH, a bytecode. +Returns nil and consumes nothing if MATCH is not the next token." + (if (/= (js2-peek-token) match) + nil + (js2-consume-token) + t)) + +(defsubst js2-valid-prop-name-token (tt) + (or (= tt js2-NAME) + (and js2-allow-keywords-as-property-names + (plusp tt) + (aref js2-kwd-tokens tt)))) + +(defsubst js2-match-prop-name () + "Consume token and return t if next token is a valid property name. +It's valid if it's a js2-NAME, or `js2-allow-keywords-as-property-names' +is non-nil and it's a keyword token." + (if (js2-valid-prop-name-token (js2-peek-token)) + (progn + (js2-consume-token) + t) + nil)) + +(defsubst js2-must-match-prop-name (msg-id &optional pos len) + (if (js2-match-prop-name) + t + (js2-report-error msg-id nil pos len) + nil)) + +(defsubst js2-peek-token-or-eol () + "Return js2-EOL if the current token immediately follows a newline. +Else returns the current token. Used in situations where we don't +consider certain token types valid if they are preceded by a newline. +One example is the postfix ++ or -- operator, which has to be on the +same line as its operand." + (let ((tt (js2-peek-token))) + ;; Check for last peeked token flags + (if (js2-flag-set-p js2-current-flagged-token js2-ti-after-eol) + js2-EOL + tt))) + +(defsubst js2-set-check-for-label () + (assert (= (logand js2-current-flagged-token js2-clear-ti-mask) js2-NAME)) + (js2-set-flag js2-current-flagged-token js2-ti-check-label)) + +(defsubst js2-must-match (token msg-id &optional pos len) + "Match next token to token code TOKEN, or record a syntax error. +MSG-ID is the error message to report if the match fails. +Returns t on match, nil if no match." + (if (js2-match-token token) + t + (js2-report-error msg-id nil pos len) + nil)) + +(defsubst js2-inside-function () + (plusp js2-nesting-of-function)) + +(defsubst js2-set-requires-activation () + (if (js2-function-node-p js2-current-script-or-fn) + (setf (js2-function-node-needs-activation js2-current-script-or-fn) t))) + +(defsubst js2-check-activation-name (name token) + (when (js2-inside-function) + ;; skip language-version 1.2 check from Rhino + (if (or (string= "arguments" name) + (and js2-compiler-activation-names ; only used in codegen + (gethash name js2-compiler-activation-names))) + (js2-set-requires-activation)))) + +(defsubst js2-set-is-generator () + (if (js2-function-node-p js2-current-script-or-fn) + (setf (js2-function-node-is-generator js2-current-script-or-fn) t))) + +(defsubst js2-must-have-xml () + (unless js2-compiler-xml-available + (js2-report-error "msg.XML.not.available"))) + +(defsubst js2-push-scope (scope) + "Push SCOPE, a `js2-scope', onto the lexical scope chain." + (assert (js2-scope-p scope)) + (assert (null (js2-scope-parent-scope scope))) + (assert (neq js2-current-scope scope)) + (setf (js2-scope-parent-scope scope) js2-current-scope + js2-current-scope scope)) + +(defsubst js2-pop-scope () + (setq js2-current-scope + (js2-scope-parent-scope js2-current-scope))) + +(defsubst js2-enter-loop (loop-node) + (push loop-node js2-loop-set) + (push loop-node js2-loop-and-switch-set) + (js2-push-scope loop-node) + ;; Tell the current labeled statement (if any) its statement, + ;; and set the jump target of the first label to the loop. + ;; These are used in `js2-parse-continue' to verify that the + ;; continue target is an actual labeled loop. (And for codegen.) + (when js2-labeled-stmt + (setf (js2-labeled-stmt-node-stmt js2-labeled-stmt) loop-node + (js2-label-node-loop (car (js2-labeled-stmt-node-labels + js2-labeled-stmt))) loop-node))) + +(defsubst js2-exit-loop () + (pop js2-loop-set) + (pop js2-loop-and-switch-set) + (js2-pop-scope)) + +(defsubst js2-enter-switch (switch-node) + (push switch-node js2-loop-and-switch-set)) + +(defsubst js2-exit-switch () + (pop js2-loop-and-switch-set)) + +(defun js2-parse (&optional buf cb) + "Tells the js2 parser to parse a region of JavaScript. + +BUF is a buffer or buffer name containing the code to parse. +Call `narrow-to-region' first to parse only part of the buffer. + +The returned AST root node is given some additional properties: + `node-count' - total number of nodes in the AST + `buffer' - BUF. The buffer it refers to may change or be killed, + so the value is not necessarily reliable. + +An optional callback CB can be specified to report parsing +progress. If `(functionp CB)' returns t, it will be called with +the current line number once before parsing begins, then again +each time the lexer reaches a new line number. + +CB can also be a list of the form `(symbol cb ...)' to specify +multiple callbacks with different criteria. Each symbol is a +criterion keyword, and the following element is the callback to +call + + :line - called whenever the line number changes + :token - called for each new token consumed + +The list of criteria could be extended to include entering or +leaving a statement, an expression, or a function definition." + (if (and cb (not (functionp cb))) + (error "criteria callbacks not yet implemented")) + (let ((inhibit-point-motion-hooks t) + (js2-compiler-xml-available (>= js2-language-version 160)) + ;; This is a recursive-descent parser, so give it a big stack. + (max-lisp-eval-depth (max max-lisp-eval-depth 3000)) + (max-specpdl-size (max max-specpdl-size 3000)) + (case-fold-search nil) + ast) + (or buf (setq buf (current-buffer))) + (save-excursion + (set-buffer buf) + (setq js2-scanned-comments nil + js2-parsed-errors nil + js2-parsed-warnings nil + js2-imenu-recorder nil + js2-imenu-function-map nil + js2-label-set nil) + (js2-init-scanner) + (setq ast (js2-with-unmodifying-text-property-changes + (js2-do-parse))) + (unless js2-ts-hit-eof + (js2-report-error "msg.got.syntax.errors" (length js2-parsed-errors))) + (setf (js2-ast-root-errors ast) js2-parsed-errors + (js2-ast-root-warnings ast) js2-parsed-warnings) + ;; if we didn't find any declarations, put a dummy in this list so we + ;; don't end up re-parsing the buffer in `js2-mode-create-imenu-index' + (unless js2-imenu-recorder + (setq js2-imenu-recorder 'empty)) + (run-hooks 'js2-parse-finished-hook) + ast))) + +;; Corresponds to Rhino's Parser.parse() method. +(defun js2-do-parse () + "Parse current buffer starting from current point. +Scanner should be initialized." + (let ((pos js2-ts-cursor) + (end js2-ts-cursor) ; in case file is empty + root n tt) + ;; initialize buffer-local parsing vars + (setf root (make-js2-ast-root :buffer (buffer-name) :pos pos) + js2-current-script-or-fn root + js2-current-scope root + js2-current-flagged-token js2-EOF + js2-nesting-of-function 0 + js2-labeled-stmt nil + js2-recorded-assignments nil) ; for js2-highlight + + (while (/= (setq tt (js2-peek-token)) js2-EOF) + (if (= tt js2-FUNCTION) + (progn + (js2-consume-token) + (setq n (js2-parse-function (if js2-called-by-compile-function + 'FUNCTION_EXPRESSION + 'FUNCTION_STATEMENT))) + (js2-record-imenu-functions n)) + ;; not a function - parse a statement + (setq n (js2-parse-statement))) + ;; add function or statement to script + (setq end (js2-node-end n)) + (js2-block-node-push root n)) + + ;; add comments to root in lexical order + (when js2-scanned-comments + ;; if we find a comment beyond end of normal kids, use its end + (setq end (max end (js2-node-end (first js2-scanned-comments)))) + (dolist (comment js2-scanned-comments) + (push comment (js2-ast-root-comments root)) + (js2-node-add-children root comment))) + + (setf (js2-node-len root) (- end pos)) + (js2-highlight-undeclared-vars) + root)) + +(defun js2-function-parser () + (js2-consume-token) + (js2-parse-function 'FUNCTION_EXPRESSION_STATEMENT)) + +(defun js2-parse-function-body (fn-node) + (js2-must-match js2-LC "msg.no.brace.body") + (let ((pos js2-token-beg) ; LC position + (pn (make-js2-block-node)) ; starts at LC position + tt + end) + (incf js2-nesting-of-function) + (unwind-protect + (while (not (or (= (setq tt (js2-peek-token)) js2-ERROR) + (= tt js2-EOF) + (= tt js2-RC))) + (js2-block-node-push pn (if (/= tt js2-FUNCTION) + (js2-parse-statement) + (js2-consume-token) + (js2-parse-function 'FUNCTION_STATEMENT)))) + (decf js2-nesting-of-function)) + (setq end js2-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-token-end)) + (setf (js2-node-pos pn) pos + (js2-node-len pn) (- end pos)) + (setf (js2-function-node-body fn-node) pn) + (js2-node-add-children fn-node pn) + pn)) + +(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) + (loop for tt = (js2-peek-token) + do + (cond + ;; destructuring param + ((or (= tt js2-LB) (= tt js2-LC)) + (push (js2-parse-primary-expr) params)) + ;; simple 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) + (push param params))) + while + (js2-match-token js2-COMMA)) + (if (js2-must-match js2-RP "msg.no.paren.after.parms") + (setf (js2-function-node-rp fn-node) (- js2-token-beg pos))) + (dolist (p params) + (js2-node-add-children fn-node p) + (push p (js2-function-node-params fn-node)))))) + +(defsubst js2-check-inconsistent-return-warning (fn-node name) + "Possibly show inconsistent-return warning. +Last token scanned is the close-curly for the function body." + (when (and js2-mode-show-strict-warnings + js2-strict-inconsistent-return-warning + (not (js2-has-consistent-return-usage + (js2-function-node-body fn-node)))) + ;; Have it extend from close-curly to bol or beginning of block. + (let ((pos (save-excursion + (goto-char js2-token-end) + (max (js2-node-abs-pos (js2-function-node-body fn-node)) + (point-at-bol)))) + (end js2-token-end)) + (if (plusp (js2-name-node-length name)) + (js2-add-strict-warning "msg.no.return.value" + (js2-name-node-name name) pos end) + (js2-add-strict-warning "msg.anon.no.return.value" nil pos end))))) + +(defun js2-parse-function (function-type) + "Function parser. FUNCTION-TYPE is a symbol." + (let ((pos js2-token-beg) ; start of 'function' keyword + name + name-beg + name-end + fn-node + lp + (synthetic-type function-type) + member-expr-node) + + ;; parse function name, expression, or non-name (anonymous) + (cond + ;; function foo(...) + ((js2-match-token js2-NAME) + (setq name (js2-create-name-node t) + name-beg js2-token-beg + name-end js2-token-end) + (unless (js2-match-token js2-LP) + (when js2-allow-member-expr-as-function-name + ;; function foo.bar(...) + (setq member-expr-node name + name nil + member-expr-node (js2-parse-member-expr-tail + nil member-expr-node))) + (js2-must-match js2-LP "msg.no.paren.parms"))) + + ((js2-match-token js2-LP) + nil) ; anonymous function: leave name as null + + (t + ;; function random-member-expr(...) + (when js2-allow-member-expr-as-function-name + ;; Note that memberExpr can not start with '(' like + ;; in function (1+2).toString(), because 'function (' already + ;; processed as anonymous function + (setq member-expr-node (js2-parse-member-expr))) + (js2-must-match js2-LP "msg.no.paren.parms"))) + + (if (= js2-current-token js2-LP) ; eventually matched LP? + (setq lp js2-token-beg)) + + (if member-expr-node + (progn + (setq synthetic-type 'FUNCTION_EXPRESSION) + (js2-parse-highlight-member-expr-fn-name member-expr-node)) + (if name + (js2-set-face name-beg name-end + 'font-lock-function-name-face 'record))) + + (if (and (neq synthetic-type 'FUNCTION_EXPRESSION) + (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)) + + (setf fn-node (make-js2-function-node :pos pos + :name name + :form function-type + :lp (if lp (- lp pos)))) + + (if (or (js2-inside-function) (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. + ;; 2. Functions defined under the with statement also immune to + ;; this setup, in which case dynamic scope is ignored in favor + ;; of the with object. + (setf (js2-function-node-ignore-dynamic fn-node) t)) + + ;; dynamically bind all the per-function variables + (let ((js2-current-script-or-fn fn-node) + (js2-current-scope fn-node) + (js2-nesting-of-with 0) + (js2-end-flags 0) + js2-label-set + js2-loop-set + js2-loop-and-switch-set) + + ;; parse params and function body + (js2-parse-function-params fn-node pos) + (js2-parse-function-body fn-node) + (if name + (js2-node-add-children fn-node name)) + + (js2-check-inconsistent-return-warning fn-node name) + + ;; Function expressions define a name only in the body of the + ;; function, and only if not hidden by a parameter name + (if (and name + (eq synthetic-type 'FUNCTION_EXPRESSION) + (null (js2-scope-get-symbol js2-current-scope + (js2-name-node-name name)))) + (js2-define-symbol js2-FUNCTION + (js2-name-node-name name) + fn-node)) + (if (and name + (eq function-type 'FUNCTION_EXPRESSION_STATEMENT)) + (js2-record-imenu-functions fn-node))) + + (setf (js2-node-len fn-node) (- js2-ts-cursor pos) + (js2-function-node-member-expr fn-node) member-expr-node) ; may be nil + + ;; Rhino doesn't do this, but we need it for finding undeclared vars. + ;; We wait until after parsing the function to set its parent scope, + ;; since `js2-define-symbol' needs the defining-scope check to stop + ;; at the function boundary when checking for redeclarations. + (setf (js2-scope-parent-scope fn-node) js2-current-scope) + + fn-node)) + +(defun js2-parse-statements (&optional parent) + "Parse a statement list. Last token consumed must be js2-LC. + +PARENT can be a `js2-block-node', in which case the statements are +appended to PARENT. Otherwise a new `js2-block-node' is created +and returned. + +This function does not match the closing js2-RC: the caller +matches the RC so it can provide a suitable error message if not +matched. This means it's up to the caller to set the length of +the node to include the closing RC. The node start pos is set to +the absolute buffer start position, and the caller should fix it +up to be relative to the parent node. All children of this block +node are given relative start positions and correct lengths." + (let ((pn (or parent (make-js2-block-node))) + tt) + (setf (js2-node-pos pn) js2-token-beg) + (while (and (> (setq tt (js2-peek-token)) js2-EOF) + (/= tt js2-RC)) + (js2-block-node-push pn (js2-parse-statement))) + pn)) + +(defun js2-parse-statement () + (let (tt pn beg end) + + ;; coarse-grained user-interrupt check - needs work + (and js2-parse-interruptable-p + (zerop (% (incf js2-parse-stmt-count) + js2-statements-per-pause)) + (input-pending-p) + (throw 'interrupted t)) + + (setq pn (js2-statement-helper)) + + ;; no-side-effects warning check + (unless (js2-node-has-side-effects pn) + (setq end (js2-node-end pn)) + (save-excursion + (goto-char end) + (setq beg (max (js2-node-pos pn) (point-at-bol)))) + (js2-add-strict-warning "msg.no.side.effects" nil beg end)) + + pn)) + +;; These correspond to the switch cases in Parser.statementHelper +(defconst js2-parsers + (let ((parsers (make-vector js2-num-tokens + #'js2-parse-expr-stmt))) + (aset parsers js2-BREAK #'js2-parse-break) + (aset parsers js2-CONST #'js2-parse-const-var) + (aset parsers js2-CONTINUE #'js2-parse-continue) + (aset parsers js2-DEBUGGER #'js2-parse-debugger) + (aset parsers js2-DEFAULT #'js2-parse-default-xml-namespace) + (aset parsers js2-DO #'js2-parse-do) + (aset parsers js2-FOR #'js2-parse-for) + (aset parsers js2-FUNCTION #'js2-function-parser) + (aset parsers js2-IF #'js2-parse-if) + (aset parsers js2-LC #'js2-parse-block) + (aset parsers js2-LET #'js2-parse-let-stmt) + (aset parsers js2-NAME #'js2-parse-name-or-label) + (aset parsers js2-RETURN #'js2-parse-ret-yield) + (aset parsers js2-SEMI #'js2-parse-semi) + (aset parsers js2-SWITCH #'js2-parse-switch) + (aset parsers js2-THROW #'js2-parse-throw) + (aset parsers js2-TRY #'js2-parse-try) + (aset parsers js2-VAR #'js2-parse-const-var) + (aset parsers js2-WHILE #'js2-parse-while) + (aset parsers js2-WITH #'js2-parse-with) + (aset parsers js2-YIELD #'js2-parse-ret-yield) + parsers) + "A vector mapping token types to parser functions.") + +(defsubst js2-parse-warn-missing-semi (beg end) + (and js2-mode-show-strict-warnings + js2-strict-missing-semi-warning + (js2-add-strict-warning + "msg.missing.semi" nil + ;; back up to beginning of statement or line + (max beg (save-excursion + (goto-char end) + (point-at-bol))) + end))) + +(defconst js2-no-semi-insertion + (list js2-IF + js2-SWITCH + js2-WHILE + js2-DO + js2-FOR + js2-TRY + js2-WITH + js2-LC + js2-ERROR + js2-SEMI + js2-FUNCTION) + "List of tokens that don't do automatic semicolon insertion.") + +(defconst js2-autoinsert-semi-and-warn + (list js2-ERROR js2-EOF js2-RC)) + +(defun js2-statement-helper () + (let* ((tt (js2-peek-token)) + (first-tt tt) + (beg js2-token-beg) + (parser (if (= tt js2-ERROR) + #'js2-parse-semi + (aref js2-parsers tt))) + pn + tt-flagged) + ;; If the statement is set, then it's been told its label by now. + (and js2-labeled-stmt + (js2-labeled-stmt-node-stmt js2-labeled-stmt) + (setq js2-labeled-stmt nil)) + + (setq pn (funcall parser) + tt-flagged (js2-peek-flagged-token) + tt (logand tt-flagged js2-clear-ti-mask)) + + ;; Don't do auto semi insertion for certain statement types. + (unless (or (memq first-tt js2-no-semi-insertion) + (js2-labeled-stmt-node-p pn)) + (cond + ((= tt js2-SEMI) + ;; Consume ';' as a part of expression + (js2-consume-token) + ;; extend the node bounds to include the semicolon. + (setf (js2-node-len pn) (- js2-token-end beg))) + ((memq tt js2-autoinsert-semi-and-warn) + ;; Autoinsert ; + (js2-parse-warn-missing-semi beg (js2-node-end pn))) + (t + (if (js2-flag-not-set-p tt-flagged js2-ti-after-eol) + ;; Report error if no EOL or autoinsert ';' otherwise + (js2-report-error "msg.no.semi.stmt") + (js2-parse-warn-missing-semi beg (js2-node-end pn)))))) + pn)) + +(defun js2-parse-condition () + "Parse a parenthesized boolean expression, e.g. in an if- or while-stmt. +The parens are discarded and the expression node is returned. +The `pos' field of the return value is set to an absolute position +that must be fixed up by the caller. +Return value is a list (EXPR LP RP), with absolute paren positions." + (let (pn lp rp) + (if (js2-must-match js2-LP "msg.no.paren.cond") + (setq lp js2-token-beg)) + (setq pn (js2-parse-expr)) + (if (js2-must-match js2-RP "msg.no.paren.after.cond") + (setq rp js2-token-beg)) + ;; Report strict warning on code like "if (a = 7) ..." + (if (and js2-strict-cond-assign-warning + (js2-assign-node-p pn)) + (js2-add-strict-warning "msg.equal.as.assign" nil + (js2-node-pos pn) + (+ (js2-node-pos pn) + (js2-node-len pn)))) + (list pn lp rp))) + +(defun js2-parse-if () + "Parser for if-statement. Last matched token must be js2-IF." + (let ((pos js2-token-beg) + cond + if-true + if-false + else-pos + end + pn) + (js2-consume-token) + (setq cond (js2-parse-condition) + if-true (js2-parse-statement) + if-false (if (js2-match-token js2-ELSE) + (progn + (setq else-pos (- js2-token-beg pos)) + (js2-parse-statement))) + end (js2-node-end (or if-false if-true)) + pn (make-js2-if-node :pos pos + :len (- end pos) + :condition (car cond) + :then-part if-true + :else-part if-false + :else-pos else-pos + :lp (js2-relpos (second cond) pos) + :rp (js2-relpos (third cond) pos))) + (js2-node-add-children pn (car cond) if-true if-false) + pn)) + +(defun js2-parse-switch () + "Parser for if-statement. Last matched token must be js2-SWITCH." + (let ((pos js2-token-beg) + tt + pn + discriminant + has-default + case-expr + case-node + case-pos + cases + stmt + lp + rp) + (js2-consume-token) + (if (js2-must-match js2-LP "msg.no.paren.switch") + (setq lp js2-token-beg)) + (setq discriminant (js2-parse-expr) + pn (make-js2-switch-node :discriminant discriminant + :pos pos + :lp (js2-relpos lp pos))) + (js2-node-add-children pn discriminant) + (js2-enter-switch pn) + (unwind-protect + (progn + (if (js2-must-match js2-RP "msg.no.paren.after.switch") + (setf (js2-switch-node-rp pn) (- js2-token-beg pos))) + (js2-must-match js2-LC "msg.no.brace.switch") + (catch 'break + (while t + (setq tt (js2-next-token) + case-pos js2-token-beg) + (cond + ((= tt js2-RC) + (setf (js2-node-len pn) (- js2-token-end pos)) + (throw 'break nil)) ; done + + ((= tt js2-CASE) + (setq case-expr (js2-parse-expr)) + (js2-must-match js2-COLON "msg.no.colon.case")) + + ((= tt js2-DEFAULT) + (if has-default + (js2-report-error "msg.double.switch.default")) + (setq has-default t + case-expr nil) + (js2-must-match js2-COLON "msg.no.colon.case")) + + (t + (js2-report-error "msg.bad.switch") + (throw 'break nil))) + + (setq case-node (make-js2-case-node :pos case-pos + :len (- js2-token-end case-pos) + :expr case-expr)) + (js2-node-add-children case-node case-expr) + (while (and (/= (setq tt (js2-peek-token)) js2-RC) + (/= tt js2-CASE) + (/= tt js2-DEFAULT) + (/= tt js2-EOF)) + (setf stmt (js2-parse-statement) + (js2-node-len case-node) (- (js2-node-end stmt) case-pos)) + (js2-block-node-push case-node stmt)) + (push case-node cases))) + ;; add cases last, as pushing reverses the order to be correct + (dolist (kid cases) + (js2-node-add-children pn kid) + (push kid (js2-switch-node-cases pn))) + pn) ; return value + (js2-exit-switch)))) + +(defun js2-parse-while () + "Parser for while-statement. Last matched token must be js2-WHILE." + (let ((pos js2-token-beg) + (pn (make-js2-while-node)) + cond + body) + (js2-consume-token) + (js2-enter-loop pn) + (unwind-protect + (progn + (setf cond (js2-parse-condition) + (js2-while-node-condition pn) (car cond) + body (js2-parse-statement) + (js2-while-node-body pn) body + (js2-node-len pn) (- (js2-node-end body) pos) + (js2-while-node-lp pn) (js2-relpos (second cond) pos) + (js2-while-node-rp pn) (js2-relpos (third cond) pos)) + (js2-node-add-children pn body (car cond))) + (js2-exit-loop)) + pn)) + +(defun js2-parse-do () + "Parser for do-statement. Last matched token must be js2-DO." + (let ((pos js2-token-beg) + (pn (make-js2-do-node)) + cond + body + end) + (js2-consume-token) + (js2-enter-loop pn) + (unwind-protect + (progn + (setq body (js2-parse-statement)) + (js2-must-match js2-WHILE "msg.no.while.do") + (setf (js2-do-node-while-pos pn) (- js2-token-beg pos) + cond (js2-parse-condition) + (js2-do-node-condition pn) (car cond) + (js2-do-node-body pn) body + end js2-ts-cursor + (js2-do-node-lp pn) (js2-relpos (second cond) pos) + (js2-do-node-rp pn) (js2-relpos (third cond) pos)) + (js2-node-add-children pn (car cond) body)) + (js2-exit-loop)) + ;; Always auto-insert semicolon to follow SpiderMonkey: + ;; It is required by ECMAScript but is ignored by the rest of + ;; world; see bug 238945 + (if (js2-match-token js2-SEMI) + (setq end js2-ts-cursor)) + (setf (js2-node-len pn) (- end pos)) + pn)) + +(defun js2-parse-for () + "Parser for for-statement. Last matched token must be js2-FOR. +Parses for, for-in, and for each-in statements." + (let ((for-pos js2-token-beg) + pn + is-for-each + is-for-in + in-pos + each-pos + tmp-pos + init ; Node init is also foo in 'foo in object' + cond ; Node cond is also object in 'foo in object' + incr ; 3rd section of for-loop initializer + body + tt + lp + rp) + (js2-consume-token) + ;; See if this is a for each () instead of just a for () + (when (js2-match-token js2-NAME) + (if (string= "each" js2-ts-string) + (progn + (setq is-for-each t + each-pos (- js2-token-beg for-pos)) ; relative + (js2-record-face 'font-lock-keyword-face)) + (js2-report-error "msg.no.paren.for"))) + + (if (js2-must-match js2-LP "msg.no.paren.for") + (setq lp (- js2-token-beg for-pos))) + (setq tt (js2-peek-token)) + + ;; parse init clause + (let ((js2-in-for-init t)) ; set as dynamic variable + (cond + ((= tt js2-SEMI) + (setq init (make-js2-empty-expr-node))) + ((or (= tt js2-VAR) (= tt js2-LET)) + (js2-consume-token) + (setq init (js2-parse-variables tt js2-token-beg))) + (t + (setq init (js2-parse-expr))))) + + (if (js2-match-token js2-IN) + (setq is-for-in t + in-pos (- js2-token-beg for-pos) + cond (js2-parse-expr)) ; object over which we're iterating + ;; else ordinary for loop - parse cond and incr + (js2-must-match js2-SEMI "msg.no.semi.for") + (setq cond (if (= (js2-peek-token) js2-SEMI) + (make-js2-empty-expr-node) ; no loop condition + (js2-parse-expr))) + (js2-must-match js2-SEMI "msg.no.semi.for.cond") + (setq tmp-pos js2-token-end + incr (if (= (js2-peek-token) js2-RP) + (make-js2-empty-expr-node :pos tmp-pos) + (js2-parse-expr)))) + + (if (js2-must-match js2-RP "msg.no.paren.for.ctrl") + (setq rp (- js2-token-beg for-pos))) + (if (not is-for-in) + (setq pn (make-js2-for-node :init init + :condition cond + :update incr + :lp lp + :rp rp)) + ;; cond could be null if 'in obj' got eaten by the init node. + (if (js2-infix-node-p init) + ;; it was (foo in bar) instead of (var foo in bar) + (setq cond (js2-infix-node-right init) + init (js2-infix-node-left init)) + (if (and (js2-var-decl-node-p init) + (> (length (js2-var-decl-node-kids init)) 1)) + (js2-report-error "msg.mult.index"))) + + (setq pn (make-js2-for-in-node :iterator init + :object cond + :in-pos in-pos + :foreach-p is-for-each + :each-pos each-pos + :lp lp + :rp rp))) + (unwind-protect + (progn + (js2-enter-loop pn) + ;; We have to parse the body -after- creating the loop node, + ;; so that the loop node appears in the js2-loop-set, allowing + ;; break/continue statements to find the enclosing loop. + (setf body (js2-parse-statement) + (js2-loop-node-body pn) body + (js2-node-pos pn) for-pos + (js2-node-len pn) (- (js2-node-end body) for-pos)) + (js2-node-add-children pn init cond incr body)) + ;; finally + (js2-exit-loop)) + pn)) + +(defun js2-parse-try () + "Parser for try-statement. Last matched token must be js2-TRY." + (let ((try-pos js2-token-beg) + try-end + try-block + catch-blocks + finally-block + saw-default-catch + peek + var-name + catch-cond + catch-node + guard-kwd + catch-pos + finally-pos + pn + block + lp + rp) + (js2-consume-token) + (if (/= (js2-peek-token) js2-LC) + (js2-report-error "msg.no.brace.try")) + (setq try-block (js2-parse-statement) + try-end (js2-node-end try-block) + peek (js2-peek-token)) + (cond + ((= peek js2-CATCH) + (while (js2-match-token js2-CATCH) + (setq catch-pos js2-token-beg + guard-kwd nil + catch-cond nil + lp nil + rp nil) + (if saw-default-catch + (js2-report-error "msg.catch.unreachable")) + (if (js2-must-match js2-LP "msg.no.paren.catch") + (setq lp (- js2-token-beg catch-pos))) + + (js2-must-match js2-NAME "msg.bad.catchcond") + (setq var-name (js2-create-name-node)) + + (if (js2-match-token js2-IF) + (setq guard-kwd (- js2-token-beg catch-pos) + catch-cond (js2-parse-expr)) + (setq saw-default-catch t)) + + (if (js2-must-match js2-RP "msg.bad.catchcond") + (setq rp (- js2-token-beg catch-pos))) + (js2-must-match js2-LC "msg.no.brace.catchblock") + + (setq block (js2-parse-statements) + try-end (js2-node-end block) + catch-node (make-js2-catch-node :pos catch-pos + :var-name var-name + :guard-expr catch-cond + :guard-kwd guard-kwd + :block block + :lp lp + :rp rp)) + (if (js2-must-match js2-RC "msg.no.brace.after.body") + (setq try-end js2-token-beg)) + (setf (js2-node-len block) (- try-end (js2-node-pos block)) + (js2-node-len catch-node) (- try-end catch-pos)) + (js2-node-add-children catch-node var-name catch-cond block) + (push catch-node catch-blocks))) + + ((/= peek js2-FINALLY) + (js2-must-match js2-FINALLY "msg.try.no.catchfinally" + (js2-node-pos try-block) + (- (setq try-end (js2-node-end try-block)) + (js2-node-pos try-block))))) + + (when (js2-match-token js2-FINALLY) + (setq finally-pos js2-token-beg + block (js2-parse-statement) + try-end (js2-node-end block) + finally-block (make-js2-finally-node :pos finally-pos + :len (- try-end finally-pos) + :body block)) + (js2-node-add-children finally-block block)) + + (setq pn (make-js2-try-node :pos try-pos + :len (- try-end try-pos) + :try-block try-block + :finally-block finally-block)) + (js2-node-add-children pn try-block finally-block) + + ;; push them onto the try-node, which reverses and corrects their order + (dolist (cb catch-blocks) + (js2-node-add-children pn cb) + (push cb (js2-try-node-catch-clauses pn))) + pn)) + +(defun js2-parse-throw () + "Parser for throw-statement. Last matched token must be js2-THROW." + (let ((pos js2-token-beg) + expr + pn) + (js2-consume-token) + (if (= (js2-peek-token-or-eol) js2-EOL) + ;; ECMAScript does not allow new lines before throw expression, + ;; see bug 256617 + (js2-report-error "msg.bad.throw.eol")) + (setq expr (js2-parse-expr) + pn (make-js2-throw-node :pos pos + :len (- (js2-node-end expr) pos) + :expr expr)) + (js2-node-add-children pn expr) + pn)) + +(defsubst js2-match-jump-label-name (label-name) + "If break/continue specified a label, return that label's labeled stmt. +Returns the corresponding `js2-labeled-stmt-node', or if LABEL-NAME +does not match an existing label, reports an error and returns nil." + (let ((bundle (cdr (assoc label-name js2-label-set)))) + (if (null bundle) + (js2-report-error "msg.undef.label")) + bundle)) + +(defun js2-parse-break () + "Parser for break-statement. Last matched token must be js2-BREAK." + (let ((pos js2-token-beg) + (end js2-token-end) + break-target ; statement to break from + break-label ; in "break foo", name-node representing the foo + labels ; matching labeled statement to break to + pn) + (js2-consume-token) ; `break' + (when (eq (js2-peek-token-or-eol) js2-NAME) + (js2-consume-token) + (setq break-label (js2-create-name-node) + end (js2-node-end break-label) + ;; matchJumpLabelName only matches if there is one + labels (js2-match-jump-label-name js2-ts-string) + break-target (if labels (car (js2-labeled-stmt-node-labels labels))))) + + (unless (or break-target break-label) + ;; no break target specified - try for innermost enclosing loop/switch + (if (null js2-loop-and-switch-set) + (unless break-label + (js2-report-error "msg.bad.break" nil pos (length "break"))) + (setq break-target (car js2-loop-and-switch-set)))) + + (setq pn (make-js2-break-node :pos pos + :len (- end pos) + :label break-label + :target break-target)) + (js2-node-add-children pn break-label) ; but not break-target + pn)) + +(defun js2-parse-continue () + "Parser for continue-statement. Last matched token must be js2-CONTINUE." + (let ((pos js2-token-beg) + (end js2-token-end) + label ; optional user-specified label, a `js2-name-node' + labels ; current matching labeled stmt, if any + target ; the `js2-loop-node' target of this continue stmt + pn) + (js2-consume-token) ; `continue' + (when (= (js2-peek-token-or-eol) js2-NAME) + (js2-consume-token) + (setq label (js2-create-name-node) + end (js2-node-end label) + ;; matchJumpLabelName only matches if there is one + labels (js2-match-jump-label-name js2-ts-string))) + (cond + ((null labels) ; no current label to go to + (if (null js2-loop-set) ; no loop to continue to + (js2-report-error "msg.continue.outside" nil pos + (length "continue")) + (setq target (car js2-loop-set)))) ; innermost enclosing loop + (t + (if (js2-loop-node-p (js2-labeled-stmt-node-stmt labels)) + (setq target (js2-labeled-stmt-node-stmt labels)) + (js2-report-error "msg.continue.nonloop" nil pos (- end pos))))) + + (setq pn (make-js2-continue-node :pos pos + :len (- end pos) + :label label + :target target)) + (js2-node-add-children pn label) ; but not target - it's not our child + pn)) + +(defun js2-parse-with () + "Parser for with-statement. Last matched token must be js2-WITH." + (js2-consume-token) + (let ((pos js2-token-beg) + obj body pn lp rp) + + (if (js2-must-match js2-LP "msg.no.paren.with") + (setq lp js2-token-beg)) + + (setq obj (js2-parse-expr)) + + (if (js2-must-match js2-RP "msg.no.paren.after.with") + (setq rp js2-token-beg)) + + (let ((js2-nesting-of-with (1+ js2-nesting-of-with))) + (setq body (js2-parse-statement))) + + (setq pn (make-js2-with-node :pos pos + :len (- (js2-node-end body) pos) + :object obj + :body body + :lp (js2-relpos lp pos) + :rp (js2-relpos rp pos))) + (js2-node-add-children pn obj body) + pn)) + +(defun js2-parse-const-var () + "Parser for var- or const-statement. +Last matched token must be js2-CONST or js2-VAR." + (let ((tt (js2-peek-token)) + (pos js2-token-beg) + expr + pn) + (js2-consume-token) + (setq expr (js2-parse-variables tt js2-token-beg) + pn (make-js2-expr-stmt-node :pos pos + :len (- (js2-node-end expr) pos) + :expr expr)) + (js2-node-add-children pn expr) + pn)) + +(defsubst js2-wrap-with-expr-stmt (pos expr &optional add-child) + (let ((pn (make-js2-expr-stmt-node :pos pos + :len (js2-node-len expr) + :type (if (js2-inside-function) + js2-EXPR_VOID + js2-EXPR_RESULT) + :expr expr))) + (if add-child + (js2-node-add-children pn expr)) + pn)) + +(defun js2-parse-let-stmt () + "Parser for let-statement. Last matched token must be js2-LET." + (js2-consume-token) + (let ((pos js2-token-beg) + expr + pn) + (if (= (js2-peek-token) js2-LP) + ;; let expression in statement context + (setq expr (js2-parse-let pos 'statement) + pn (js2-wrap-with-expr-stmt pos expr t)) + ;; else we're looking at a statement like let x=6, y=7; + (setf expr (js2-parse-variables js2-LET pos) + pn (js2-wrap-with-expr-stmt pos expr t) + (js2-node-type pn) js2-EXPR_RESULT)) + pn)) + +(defun js2-parse-ret-yield () + (js2-parse-return-or-yield (js2-peek-token) nil)) + +(defconst js2-parse-return-stmt-enders + (list js2-SEMI js2-RC js2-EOF js2-EOL js2-ERROR js2-RB js2-RP js2-YIELD)) + +(defsubst js2-now-all-set (before after mask) + "Return whether or not the bits in the mask have changed to all set. +BEFORE is bits before change, AFTER is bits after change, and MASK is +the mask for bits. Returns t if all the bits in the mask are set in AFTER +but not BEFORE." + (and (/= (logand before mask) mask) + (= (logand after mask) mask))) + +(defun js2-parse-return-or-yield (tt expr-context) + (let ((pos js2-token-beg) + (end js2-token-end) + (before js2-end-flags) + (inside-function (js2-inside-function)) + e + ret + name) + (unless inside-function + (js2-report-error (if (eq tt js2-RETURN) + "msg.bad.return" + "msg.bad.yield"))) + (js2-consume-token) + ;; This is ugly, but we don't want to require a semicolon. + (unless (memq (js2-peek-token-or-eol) js2-parse-return-stmt-enders) + (setq e (js2-parse-expr) + end (js2-node-end e))) + (cond + ((eq tt js2-RETURN) + (js2-set-flag js2-end-flags (if (null e) + js2-end-returns + js2-end-returns-value)) + (setq ret (make-js2-return-node :pos pos + :len (- end pos) + :retval e)) + (js2-node-add-children ret e) + ;; See if we need a strict mode warning. + ;; TODO: The analysis done by `js2-has-consistent-return-usage' is + ;; more thorough and accurate than this before/after flag check. + ;; E.g. if there's a finally-block that always returns, we shouldn't + ;; show a warning generated by inconsistent returns in the catch blocks. + ;; Basically `js2-has-consistent-return-usage' needs to keep more state, + ;; so we know which returns/yields to highlight, and we should get rid of + ;; all the checking in `js2-parse-return-or-yield'. + (if (and js2-strict-inconsistent-return-warning + (js2-now-all-set before js2-end-flags + (logior js2-end-returns js2-end-returns-value))) + (js2-add-strict-warning "msg.return.inconsistent" nil pos end))) + (t + (unless (js2-inside-function) + (js2-report-error "msg.bad.yield")) + (js2-set-flag js2-end-flags js2-end-yields) + (setq ret (make-js2-yield-node :pos pos + :len (- end pos) + :value e)) + (js2-node-add-children ret e) + (unless expr-context + (setq e ret + ret (js2-wrap-with-expr-stmt pos e t)) + (js2-set-requires-activation) + (js2-set-is-generator)))) + + ;; see if we are mixing yields and value returns. + (when (and inside-function + (js2-now-all-set before js2-end-flags + (logior js2-end-yields js2-end-returns-value))) + (setq name (js2-function-name js2-current-script-or-fn)) + (if (zerop (length name)) + (js2-report-error "msg.anon.generator.returns" nil pos (- end pos)) + (js2-report-error "msg.generator.returns" name pos (- end pos)))) + + ret)) + +(defun js2-parse-debugger () + (js2-consume-token) + (make-js2-keyword-node :type js2-DEBUGGER)) + +(defun js2-parse-block () + "Parser for a curly-delimited statement block. +Last token matched must be js2-LC." + (let ((pos js2-token-beg) + (pn (make-js2-scope))) + (js2-consume-token) + (js2-push-scope pn) + (unwind-protect + (progn + (js2-parse-statements pn) + (js2-must-match js2-RC "msg.no.brace.block") + (setf (js2-node-len pn) (- js2-token-end pos))) + (js2-pop-scope)) + pn)) + +;; for js2-ERROR too, to have a node for error recovery to work on +(defun js2-parse-semi () + "Parse a statement or handle an error. +Last matched token is js-SEMI or js-ERROR." + (let ((tt (js2-peek-token)) pos len) + (js2-consume-token) + (if (eq tt js2-SEMI) + (make-js2-empty-expr-node :len 1) + (setq pos js2-token-beg + len (- js2-token-beg pos)) + (js2-report-error "msg.syntax" nil pos len) + (make-js2-error-node :pos pos :len len)))) + +(defun js2-parse-default-xml-namespace () + "Parse a `default xml namespace = <expr>' e4x statement." + (let ((pos js2-token-beg) + end len expr unary es) + (js2-consume-token) + (js2-must-have-xml) + (js2-set-requires-activation) + (setq len (- js2-ts-cursor pos)) + (unless (and (js2-match-token js2-NAME) + (string= js2-ts-string "xml")) + (js2-report-error "msg.bad.namespace" nil pos len)) + (unless (and (js2-match-token js2-NAME) + (string= js2-ts-string "namespace")) + (js2-report-error "msg.bad.namespace" nil pos len)) + (unless (js2-match-token js2-ASSIGN) + (js2-report-error "msg.bad.namespace" nil pos len)) + (setq expr (js2-parse-expr) + end (js2-node-end expr) + unary (make-js2-unary-node :type js2-DEFAULTNAMESPACE + :pos pos + :len (- end pos) + :operand expr)) + (js2-node-add-children unary expr) + (make-js2-expr-stmt-node :pos pos + :len (- end pos) + :expr unary))) + +(defun js2-record-label (label bundle) + ;; current token should be colon that `js2-parse-primary-expr' left untouched + (js2-consume-token) + (let ((name (js2-label-node-name label)) + labeled-stmt + dup) + (when (setq labeled-stmt (cdr (assoc name js2-label-set))) + ;; flag both labels if possible when used in editing mode + (if (and js2-parse-ide-mode + (setq dup (js2-get-label-by-name labeled-stmt name))) + (js2-report-error "msg.dup.label" nil + (js2-node-abs-pos dup) (js2-node-len dup))) + (js2-report-error "msg.dup.label" nil + (js2-node-pos label) (js2-node-len label))) + (js2-labeled-stmt-node-add-label bundle label) + (js2-node-add-children bundle label) + ;; Add one reference to the bundle per label in `js2-label-set' + (push (cons name bundle) js2-label-set))) + +(defun js2-parse-name-or-label () + "Parser for identifier or label. Last token matched must be js2-NAME. +Called when we found a name in a statement context. If it's a label, we gather +up any following labels and the next non-label statement into a +`js2-labeled-stmt-node' bundle and return that. Otherwise we parse an +expression and return it wrapped in a `js2-expr-stmt-node'." + (let ((pos js2-token-beg) + (end js2-token-end) + expr + stmt + pn + bundle + (continue t)) + ;; set check for label and call down to `js2-parse-primary-expr' + (js2-set-check-for-label) + (setq expr (js2-parse-expr)) + + (if (/= (js2-node-type expr) js2-LABEL) + ;; Parsed non-label expression - wrap with expression stmt. + (setq pn (js2-wrap-with-expr-stmt pos expr t)) + + ;; else parsed a label + (setq bundle (make-js2-labeled-stmt-node :pos pos)) + (js2-record-label expr bundle) + + ;; look for more labels + (while (and continue (= (js2-peek-token) js2-NAME)) + (js2-set-check-for-label) + (setq expr (js2-parse-expr)) + (if (/= (js2-node-type expr) js2-LABEL) + (setq stmt (js2-wrap-with-expr-stmt pos expr t) + continue nil) + (js2-record-label expr bundle))) + + ;; no more labels; now parse the labeled statement + (unwind-protect + (unless stmt + (let ((js2-labeled-stmt bundle)) ; bind dynamically + (setq stmt (js2-statement-helper)))) + ;; remove the labels for this statement from the global set + (dolist (label (js2-labeled-stmt-node-labels bundle)) + (setq js2-label-set (remove label js2-label-set)))) + + (setf (js2-labeled-stmt-node-stmt bundle) stmt) + (js2-node-add-children bundle stmt) + bundle))) + +(defun js2-parse-expr-stmt () + "Default parser in statement context, if no recognized statement found." + (js2-wrap-with-expr-stmt js2-token-beg (js2-parse-expr) t)) + +(defun js2-parse-variables (decl-type pos) + "Parse a comma-separated list of variable declarations. +Could be a 'var', 'const' or 'let' expression, possibly in a for-loop initializer. + +DECL-TYPE is a token value: either VAR, CONST, or LET depending on context. +For 'var' or 'const', the keyword should be the token last scanned. + +POS is the position where the node should start. It's sometimes the +var/const/let keyword, and other times the beginning of the first token +in the first variable declaration. + +Returns the parsed `js2-var-decl-node' expression node." + (let* ((result (make-js2-var-decl-node :decl-type decl-type + :pos pos)) + destructuring + kid-pos + tt + init + name + end + nbeg nend + vi + (continue t)) + ;; Example: + ;; var foo = {a: 1, b: 2}, bar = [3, 4]; + ;; var {b: s2, a: s1} = foo, x = 6, y, [s3, s4] = bar; + (while continue + (setq destructuring nil + name nil + tt (js2-peek-token) + kid-pos js2-token-beg + end js2-token-end + init nil) + (if (or (= tt js2-LB) (= tt js2-LC)) + ;; Destructuring assignment, e.g., var [a, b] = ... + (setq destructuring (js2-parse-primary-expr) + end (js2-node-end destructuring)) + ;; Simple variable name + (when (js2-must-match js2-NAME "msg.bad.var") + (setq name (js2-create-name-node) + nbeg js2-token-beg + nend js2-token-end + end nend) + (js2-define-symbol decl-type js2-ts-string name js2-in-for-init))) + + (when (js2-match-token js2-ASSIGN) + (setq init (js2-parse-assign-expr) + end (js2-node-end init)) + (if (and js2-parse-ide-mode + (or (js2-object-node-p init) + (js2-function-node-p init))) + (js2-record-imenu-functions init name))) + + (when name + (js2-set-face nbeg nend (if (js2-function-node-p init) + 'font-lock-function-name-face + 'font-lock-variable-name-face) + 'record)) + + (setq vi (make-js2-var-init-node :pos kid-pos + :len (- end kid-pos) + :type decl-type)) + (if destructuring + (progn + (if (and (null init) (not js2-in-for-init)) + (js2-report-error "msg.destruct.assign.no.init")) + (setf (js2-var-init-node-target vi) destructuring)) + (setf (js2-var-init-node-target vi) name)) + (setf (js2-var-init-node-initializer vi) init) + (js2-node-add-children vi name destructuring init) + + (js2-block-node-push result vi) + (unless (js2-match-token js2-COMMA) + (setq continue nil))) + + (setf (js2-node-len result) (- end pos)) + result)) + +(defun js2-parse-let (pos &optional stmt-p) + "Parse a let expression or statement. +A let-expression is of the form `let (vars) expr'. +A let-statment is of the form `let (vars) {statements}'. +The third form of let is a variable declaration list, handled +by `js2-parse-variables'." + (let ((pn (make-js2-let-node :pos pos)) + beg vars body) + (if (js2-must-match js2-LP "msg.no.paren.after.let") + (setf (js2-let-node-lp pn) (- js2-token-beg pos))) + (js2-push-scope pn) + (unwind-protect + (progn + (setq vars (js2-parse-variables js2-LET js2-token-beg)) + (if (js2-must-match js2-RP "msg.no.paren.let") + (setf (js2-let-node-rp pn) (- js2-token-beg pos))) + (if (and stmt-p (eq (js2-peek-token) js2-LC)) + ;; let statement + (progn + (js2-consume-token) + (setf beg js2-token-beg ; position stmt at LC + body (js2-parse-statements)) + (js2-must-match js2-RC "msg.no.curly.let") + (setf (js2-node-len body) (- js2-token-end beg) + (js2-node-len pn) (- js2-token-end pos) + (js2-let-node-body pn) body + (js2-node-type pn) js2-LET)) + ;; let expression + (setf body (js2-parse-expr) + (js2-node-len pn) (- (js2-node-end body) pos) + (js2-let-node-body pn) body)) + (js2-node-add-children pn vars body)) + (js2-pop-scope)) + pn)) + +(defsubst js2-define-new-symbol (decl-type name node) + (js2-scope-put-symbol js2-current-scope + name + (make-js2-symbol decl-type name node))) + +(defun js2-define-symbol (decl-type name &optional node ignore-not-in-block) + "Define a symbol in the current scope. +If NODE is non-nil, it is the AST node associated with the symbol." + (let* ((defining-scope (js2-get-defining-scope js2-current-scope name)) + (symbol (if defining-scope + (js2-scope-get-symbol defining-scope name))) + (sdt (if symbol (js2-symbol-decl-type symbol) -1))) + (cond + ((and symbol ; already defined + (or (= sdt js2-CONST) ; old version is const + (= decl-type js2-CONST) ; new version is const + ;; two let-bound vars in this block have same name + (and (= sdt js2-LET) + (eq defining-scope js2-current-scope)))) + (js2-report-error + (cond + ((= sdt js2-CONST) "msg.const.redecl") + ((= sdt js2-LET) "msg.let.redecl") + ((= sdt js2-VAR) "msg.var.redecl") + ((= sdt js2-FUNCTION) "msg.function.redecl") + (t "msg.parm.redecl")) + name)) + + ((= decl-type js2-LET) + (if (and (not ignore-not-in-block) + (or (= (js2-node-type js2-current-scope) js2-IF) + (js2-loop-node-p js2-current-scope))) + (js2-report-error "msg.let.decl.not.in.block") + (js2-define-new-symbol decl-type name node))) + + ((or (= decl-type js2-VAR) + (= decl-type js2-CONST) + (= decl-type js2-FUNCTION)) + (if symbol + (if (and js2-strict-var-redeclaration-warning (= sdt js2-VAR)) + (js2-add-strict-warning "msg.var.redecl" name) + (if (and js2-strict-var-hides-function-arg-warning (= sdt js2-LP)) + (js2-add-strict-warning "msg.var.hides.arg" name))) + (js2-define-new-symbol decl-type name node))) + + ((= decl-type js2-LP) + (if symbol + ;; must be duplicate parameter. Second parameter hides the + ;; first, so go ahead and add the second pararameter + (js2-report-warning "msg.dup.parms" name)) + (js2-define-new-symbol decl-type name node)) + + (t (js2-code-bug))))) + +(defun js2-parse-expr () + (let* ((pn (js2-parse-assign-expr)) + (pos (js2-node-pos pn)) + left + right + op-pos) + (while (js2-match-token js2-COMMA) + (setq op-pos (- js2-token-beg pos)) ; relative + (if (= (js2-peek-token) js2-YIELD) + (js2-report-error "msg.yield.parenthesized")) + (setq right (js2-parse-assign-expr) + left pn + pn (make-js2-infix-node :type js2-COMMA + :pos pos + :len (- js2-ts-cursor pos) + :op-pos op-pos + :left left + :right right)) + (js2-node-add-children pn left right)) + pn)) + +(defun js2-parse-assign-expr () + (let ((tt (js2-peek-token)) + (pos js2-token-beg) + pn + left + right + op-pos) + (if (= tt js2-YIELD) + (js2-parse-return-or-yield tt t) + ;; not yield - parse assignment expression + (setq pn (js2-parse-cond-expr) + tt (js2-peek-token)) + (when (and (<= js2-first-assign tt) + (<= tt js2-last-assign)) + (js2-consume-token) + (setq op-pos (- js2-token-beg pos) ; relative + left pn + right (js2-parse-assign-expr) + pn (make-js2-assign-node :type tt + :pos pos + :len (- (js2-node-end right) pos) + :op-pos op-pos + :left left + :right right)) + (when js2-parse-ide-mode + (js2-highlight-assign-targets pn left right) + (if (or (js2-function-node-p right) + (js2-object-node-p right)) + (js2-record-imenu-functions right left))) + ;; do this last so ide checks above can use absolute positions + (js2-node-add-children pn left right)) + pn))) + +(defun js2-parse-cond-expr () + (let ((pos js2-token-beg) + (pn (js2-parse-or-expr)) + test-expr + if-true + if-false + q-pos + c-pos) + (when (js2-match-token js2-HOOK) + (setq q-pos (- js2-token-beg pos) + if-true (js2-parse-assign-expr)) + (js2-must-match js2-COLON "msg.no.colon.cond") + (setq c-pos (- js2-token-beg pos) + if-false (js2-parse-assign-expr) + test-expr pn + pn (make-js2-cond-node :pos pos + :len (- (js2-node-end if-false) pos) + :test-expr test-expr + :true-expr if-true + :false-expr if-false + :q-pos q-pos + :c-pos c-pos)) + (js2-node-add-children pn test-expr if-true if-false)) + pn)) + +(defun js2-make-binary (type left parser) + "Helper for constructing a binary-operator AST node. +LEFT is the left-side-expression, already parsed, and the +binary operator should have just been matched. +PARSER is a function to call to parse the right operand, +or a `js2-node' struct if it has already been parsed." + (let* ((pos (js2-node-pos left)) + (op-pos (- js2-token-beg pos)) + (right (if (js2-node-p parser) + parser + (funcall parser))) + (pn (make-js2-infix-node :type type + :pos pos + :len (- (js2-node-end right) pos) + :op-pos op-pos + :left left + :right right))) + (js2-node-add-children pn left right) + pn)) + +(defun js2-parse-or-expr () + (let ((pn (js2-parse-and-expr))) + (when (js2-match-token js2-OR) + (setq pn (js2-make-binary js2-OR + pn + 'js2-parse-or-expr))) + pn)) + +(defun js2-parse-and-expr () + (let ((pn (js2-parse-bit-or-expr))) + (when (js2-match-token js2-AND) + (setq pn (js2-make-binary js2-AND + pn + 'js2-parse-and-expr))) + pn)) + +(defun js2-parse-bit-or-expr () + (let ((pn (js2-parse-bit-xor-expr))) + (while (js2-match-token js2-BITOR) + (setq pn (js2-make-binary js2-BITOR + pn + 'js2-parse-bit-xor-expr))) + pn)) + +(defun js2-parse-bit-xor-expr () + (let ((pn (js2-parse-bit-and-expr))) + (while (js2-match-token js2-BITXOR) + (setq pn (js2-make-binary js2-BITXOR + pn + 'js2-parse-bit-and-expr))) + pn)) + +(defun js2-parse-bit-and-expr () + (let ((pn (js2-parse-eq-expr))) + (while (js2-match-token js2-BITAND) + (setq pn (js2-make-binary js2-BITAND + pn + 'js2-parse-eq-expr))) + pn)) + +(defconst js2-parse-eq-ops + (list js2-EQ js2-NE js2-SHEQ js2-SHNE)) + +(defun js2-parse-eq-expr () + (let ((pn (js2-parse-rel-expr)) + tt) + (while (memq (setq tt (js2-peek-token)) js2-parse-eq-ops) + (js2-consume-token) + (setq pn (js2-make-binary tt + pn + 'js2-parse-rel-expr))) + pn)) + +(defconst js2-parse-rel-ops + (list js2-IN js2-INSTANCEOF js2-LE js2-LT js2-GE js2-GT)) + +(defun js2-parse-rel-expr () + (let ((pn (js2-parse-shift-expr)) + (continue t) + tt) + (while continue + (setq tt (js2-peek-token)) + (cond + ((and js2-in-for-init (= tt js2-IN)) + (setq continue nil)) + ((memq tt js2-parse-rel-ops) + (js2-consume-token) + (setq pn (js2-make-binary tt pn 'js2-parse-shift-expr))) + (t + (setq continue nil)))) + pn)) + +(defconst js2-parse-shift-ops + (list js2-LSH js2-URSH js2-RSH)) + +(defun js2-parse-shift-expr () + (let ((pn (js2-parse-add-expr)) + tt + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (if (memq tt js2-parse-shift-ops) + (progn + (js2-consume-token) + (setq pn (js2-make-binary tt pn 'js2-parse-add-expr))) + (setq continue nil))) + pn)) + +(defun js2-parse-add-expr () + (let ((pn (js2-parse-mul-expr)) + tt + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (if (or (= tt js2-ADD) (= tt js2-SUB)) + (progn + (js2-consume-token) + (setq pn (js2-make-binary tt pn 'js2-parse-mul-expr))) + (setq continue nil))) + pn)) + +(defconst js2-parse-mul-ops + (list js2-MUL js2-DIV js2-MOD)) + +(defun js2-parse-mul-expr () + (let ((pn (js2-parse-unary-expr)) + tt + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (if (memq tt js2-parse-mul-ops) + (progn + (js2-consume-token) + (setq pn (js2-make-binary tt pn 'js2-parse-unary-expr))) + (setq continue nil))) + pn)) + +(defsubst js2-make-unary (type parser &rest args) + "Make a unary node of type TYPE. +PARSER is either a node (for postfix operators) or a function to call +to parse the operand (for prefix operators)." + (let* ((pos js2-token-beg) + (postfix (js2-node-p parser)) + (expr (if postfix + parser + (apply parser args))) + end + pn) + (if postfix ; e.g. i++ + (setq pos (js2-node-pos expr) + end js2-token-end) + (setq end (js2-node-end expr))) + (setq pn (make-js2-unary-node :type type + :pos pos + :len (- end pos) + :operand expr)) + (js2-node-add-children pn expr) + pn)) + +(defconst js2-incrementable-node-types + (list js2-NAME js2-GETPROP js2-GETELEM js2-GET_REF js2-CALL) + "Node types that can be the operand of a ++ or -- operator.") + +(defsubst js2-check-bad-inc-dec (tt beg end unary) + (unless (memq (js2-node-type (js2-unary-node-operand unary)) + js2-incrementable-node-types) + (js2-report-error (if (= tt js2-INC) + "msg.bad.incr" + "msg.bad.decr") + nil beg (- end beg)))) + +(defun js2-parse-unary-expr () + (let ((tt (js2-peek-token)) + pn expr beg end) + (cond + ((or (= tt js2-VOID) + (= tt js2-NOT) + (= tt js2-BITNOT) + (= tt js2-TYPEOF)) + (js2-consume-token) + (js2-make-unary tt 'js2-parse-unary-expr)) + + ((= tt js2-ADD) + (js2-consume-token) + ;; Convert to special POS token in decompiler and parse tree + (js2-make-unary js2-POS 'js2-parse-unary-expr)) + + ((= tt js2-SUB) + (js2-consume-token) + ;; Convert to special NEG token in decompiler and parse tree + (js2-make-unary js2-NEG 'js2-parse-unary-expr)) + + ((or (= tt js2-INC) + (= tt js2-DEC)) + (js2-consume-token) + (prog1 + (setq beg js2-token-beg + end js2-token-end + expr (js2-make-unary tt 'js2-parse-member-expr t)) + (js2-check-bad-inc-dec tt beg end expr))) + + ((= tt js2-DELPROP) + (js2-consume-token) + (js2-make-unary js2-DELPROP 'js2-parse-unary-expr)) + + ((= tt js2-ERROR) + (js2-consume-token) + (make-js2-error-node)) ; try to continue + + ((and (= tt js2-LT) + js2-compiler-xml-available) + ;; XML stream encountered in expression. + (js2-consume-token) + (js2-parse-member-expr-tail t (js2-parse-xml-initializer))) + (t + (setq pn (js2-parse-member-expr t) + ;; Don't look across a newline boundary for a postfix incop. + tt (js2-peek-token-or-eol)) + (when (or (= tt js2-INC) (= tt js2-DEC)) + (js2-consume-token) + (setf expr pn + pn (js2-make-unary tt expr)) + (js2-node-set-prop pn 'postfix t) + (js2-check-bad-inc-dec tt js2-token-beg js2-token-end pn)) + pn)))) + +(defun js2-parse-xml-initializer () + "Parse an E4X XML initializer. +I'm parsing it the way Rhino parses it, but without the tree-rewriting. +Then I'll postprocess the result, depending on whether we're in IDE +mode or codegen mode, and generate the appropriate rewritten AST. +IDE mode uses a rich AST that models the XML structure. Codegen mode +just concatenates everything and makes a new XML or XMLList out of it." + (let ((tt (js2-get-first-xml-token)) + pn-xml + pn + expr + kids + expr-pos + (continue t) + (first-token t)) + (when (not (or (= tt js2-XML) (= tt js2-XMLEND))) + (js2-report-error "msg.syntax")) + (setq pn-xml (make-js2-xml-node)) + (while continue + (if first-token + (setq first-token nil) + (setq tt (js2-get-next-xml-token))) + (cond + ;; js2-XML means we found a {expr} in the XML stream. + ;; The js2-ts-string is the XML up to the left-curly. + ((= tt js2-XML) + (push (make-js2-string-node :pos js2-token-beg + :len (- js2-ts-cursor js2-token-beg)) + kids) + (js2-must-match js2-LC "msg.syntax") + (setq expr-pos js2-ts-cursor + expr (if (eq (js2-peek-token) js2-RC) + (make-js2-empty-expr-node :pos expr-pos) + (js2-parse-expr))) + (js2-must-match js2-RC "msg.syntax") + (setq pn (make-js2-xml-js-expr-node :pos (js2-node-pos expr) + :len (js2-node-len expr) + :expr expr)) + (js2-node-add-children pn expr) + (push pn kids)) + + ;; a js2-XMLEND token means we hit the final close-tag. + ((= tt js2-XMLEND) + (push (make-js2-string-node :pos js2-token-beg + :len (- js2-ts-cursor js2-token-beg)) + kids) + (dolist (kid (nreverse kids)) + (js2-block-node-push pn-xml kid)) + (setf (js2-node-len pn-xml) (- js2-ts-cursor + (js2-node-pos pn-xml)) + continue nil)) + (t + (js2-report-error "msg.syntax") + (setq continue nil)))) + pn-xml)) + + +(defun js2-parse-argument-list () + "Parse an argument list and return it as a lisp list of nodes. +Returns the list in reverse order. Consumes the right-paren token." + (let (result) + (unless (js2-match-token js2-RP) + (loop do + (if (= (js2-peek-token) js2-YIELD) + (js2-report-error "msg.yield.parenthesized")) + (push (js2-parse-assign-expr) result) + while + (js2-match-token js2-COMMA)) + (js2-must-match js2-RP "msg.no.paren.arg") + result))) + +(defun js2-parse-member-expr (&optional allow-call-syntax) + (let ((tt (js2-peek-token)) + pn + pos + target + args + beg + end + init + tail) + (if (/= tt js2-NEW) + (setq pn (js2-parse-primary-expr)) + ;; parse a 'new' expression + (js2-consume-token) + (setq pos js2-token-beg + beg pos + target (js2-parse-member-expr) + end (js2-node-end target) + pn (make-js2-new-node :pos pos + :target target + :len (- end pos))) + (js2-node-add-children pn target) + (when (js2-match-token js2-LP) + ;; Add the arguments to pn, if any are supplied. + (setf beg pos ; start of "new" keyword + pos js2-token-beg + args (nreverse (js2-parse-argument-list)) + (js2-new-node-args pn) args + end js2-token-end + (js2-new-node-lp pn) (- pos beg) + (js2-new-node-rp pn) (- end 1 beg)) + (apply #'js2-node-add-children pn args)) + + (when (and js2-allow-rhino-new-expr-initializer + (js2-match-token js2-LC)) + (setf init (js2-parse-object-literal) + end (js2-node-end init) + (js2-new-node-initializer pn) init) + (js2-node-add-children pn init)) + + (setf (js2-node-len pn) (- beg pos))) ; end outer if + + (js2-parse-member-expr-tail allow-call-syntax pn))) + +(defun js2-parse-member-expr-tail (allow-call-syntax pn) + "Parse a chain of property/array accesses or function calls. +Includes parsing for E4X operators like `..' and `.@'. +If ALLOW-CALL-SYNTAX is nil, stops when we encounter a left-paren. +Returns an expression tree that includes PN, the parent node." + (let ((beg (js2-node-pos pn)) + tt + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (cond + ((or (= tt js2-DOT) (= tt js2-DOTDOT)) + (setq pn (js2-parse-property-access tt pn))) + + ((= tt js2-DOTQUERY) + (setq pn (js2-parse-dot-query pn))) + + ((= tt js2-LB) + (setq pn (js2-parse-element-get pn))) + + ((= tt js2-LP) + (if allow-call-syntax + (setq pn (js2-parse-function-call pn)) + (setq continue nil))) + (t + (setq continue nil)))) + (if (>= js2-highlight-level 2) + (js2-parse-highlight-member-expr-node pn)) + pn)) + +(defun js2-parse-dot-query (pn) + "Parse a dot-query expression, e.g. foo.bar.(@name == 2) +Last token parsed must be `js2-DOTQUERY'." + (let ((pos (js2-node-pos pn)) + op-pos + expr + end) + (js2-consume-token) + (js2-must-have-xml) + (js2-set-requires-activation) + (setq op-pos js2-token-beg + expr (js2-parse-expr) + end (js2-node-end expr) + pn (make-js2-xml-dot-query-node :left pn + :pos pos + :op-pos op-pos + :right expr)) + (js2-node-add-children pn + (js2-xml-dot-query-node-left pn) + (js2-xml-dot-query-node-right pn)) + (if (js2-must-match js2-RP "msg.no.paren") + (setf (js2-xml-dot-query-node-rp pn) js2-token-beg + end js2-token-end)) + (setf (js2-node-len pn) (- end pos)) + pn)) + +(defun js2-parse-element-get (pn) + "Parse an element-get expression, e.g. foo[bar]. +Last token parsed must be `js2-RB'." + (let ((lb js2-token-beg) + (pos (js2-node-pos pn)) + rb + expr) + (js2-consume-token) + (setq expr (js2-parse-expr)) + (if (js2-must-match js2-RB "msg.no.bracket.index") + (setq rb js2-token-beg)) + (setq pn (make-js2-elem-get-node :target pn + :pos pos + :element expr + :lb (js2-relpos lb pos) + :rb (js2-relpos rb pos) + :len (- js2-token-end pos))) + (js2-node-add-children pn + (js2-elem-get-node-target pn) + (js2-elem-get-node-element pn)) + pn)) + +(defun js2-parse-function-call (pn) + (let (args + (pos (js2-node-pos pn))) + (js2-consume-token) + (setq pn (make-js2-call-node :pos pos + :target pn + :lp (- js2-token-beg pos))) + (js2-node-add-children pn (js2-call-node-target pn)) + + ;; Add the arguments to pn, if any are supplied. + (setf args (nreverse (js2-parse-argument-list)) + (js2-call-node-rp pn) (- js2-token-beg pos) + (js2-call-node-args pn) args) + (apply #'js2-node-add-children pn args) + + (setf (js2-node-len pn) (- js2-ts-cursor pos)) + pn)) + +(defun js2-parse-property-access (tt pn) + "Parse a property access, XML descendants access, or XML attr access." + (let ((member-type-flags 0) + (dot-pos js2-token-beg) + (dot-len (if (= tt js2-DOTDOT) 2 1)) + name + ref ; right side of . or .. operator + result) + (js2-consume-token) + (when (= tt js2-DOTDOT) + (js2-must-have-xml) + (setq member-type-flags js2-descendants-flag)) + (if (not js2-compiler-xml-available) + (progn + (js2-must-match-prop-name "msg.no.name.after.dot") + (setq name (js2-create-name-node t js2-GETPROP) + result (make-js2-prop-get-node :left pn + :pos js2-token-beg + :right name + :len (- js2-token-end + js2-token-beg))) + (js2-node-add-children result pn name) + result) + ;; otherwise look for XML operators + (setf result (if (= tt js2-DOT) + (make-js2-prop-get-node) + (make-js2-infix-node :type js2-DOTDOT)) + (js2-node-pos result) (js2-node-pos pn) + (js2-infix-node-op-pos result) dot-pos + (js2-infix-node-left result) pn ; do this after setting position + tt (js2-next-token)) + (cond + ;; needed for generator.throw() + ((= tt js2-THROW) + (js2-save-name-token-data js2-token-beg "throw") + (setq ref (js2-parse-property-name nil js2-ts-string member-type-flags))) + + ;; handles: name, ns::name, ns::*, ns::[expr] + ((js2-valid-prop-name-token tt) + (setq ref (js2-parse-property-name -1 js2-ts-string member-type-flags))) + + ;; handles: *, *::name, *::*, *::[expr] + ((= tt js2-MUL) + (js2-save-name-token-data js2-token-beg "*") + (setq ref (js2-parse-property-name nil "*" member-type-flags))) + + ;; handles: '@attr', '@ns::attr', '@ns::*', '@ns::[expr]', etc. + ((= tt js2-XMLATTR) + (setq result (js2-parse-attribute-access))) + + (t + (js2-report-error "msg.no.name.after.dot" nil dot-pos dot-len))) + + (if ref + (setf (js2-node-len result) (- (js2-node-end ref) + (js2-node-pos result)) + (js2-infix-node-right result) ref)) + (if (js2-infix-node-p result) + (js2-node-add-children result + (js2-infix-node-left result) + (js2-infix-node-right result))) + result))) + +(defun js2-parse-attribute-access () + "Parse an E4X XML attribute expression. +This includes expressions of the forms: + + @attr @ns::attr @ns::* + @* @*::attr @*::* + @[expr] @*::[expr] @ns::[expr] + +Called if we peeked an '@' token." + (let ((tt (js2-next-token)) + (at-pos js2-token-beg)) + (cond + ;; handles: @name, @ns::name, @ns::*, @ns::[expr] + ((js2-valid-prop-name-token tt) + (js2-parse-property-name at-pos js2-ts-string 0)) + + ;; handles: @*, @*::name, @*::*, @*::[expr] + ((= tt js2-MUL) + (js2-save-name-token-data js2-token-beg "*") + (js2-parse-property-name js2-token-beg "*" 0)) + + ;; handles @[expr] + ((= tt js2-LB) + (js2-parse-xml-elem-ref at-pos)) + + (t + (js2-report-error "msg.no.name.after.xmlAttr") + ;; Avoid cascaded errors that happen if we make an error node here. + (js2-save-name-token-data js2-token-beg "") + (js2-parse-property-name js2-token-beg "" 0))))) + +(defun js2-parse-property-name (at-pos s member-type-flags) + "Check if :: follows name in which case it becomes qualified name. + +AT-POS is a natural number if we just read an '@' token, else nil. +S is the name or string that was matched: an identifier, 'throw' or '*'. +MEMBER-TYPE-FLAGS is a bit set tracking whether we're a '.' or '..' child. + +Returns a `js2-xml-ref-node' if it's an attribute access, a child of a '..' +operator, or the name is followed by ::. For a plain name, returns a +`js2-name-node'. Returns a `js2-error-node' for malformed XML expressions." + (let ((pos (or at-pos js2-token-beg)) + colon-pos + (name (js2-create-name-node t js2-current-token)) + ns + tt + ref + pn) + (catch 'return + (when (js2-match-token js2-COLONCOLON) + (setq ns name + colon-pos js2-token-beg + tt (js2-next-token)) + (cond + ;; handles name::name + ((js2-valid-prop-name-token tt) + (setq name (js2-create-name-node))) + + ;; handles name::* + ((= tt js2-MUL) + (js2-save-name-token-data js2-token-beg "*") + (setq name (js2-create-name-node))) + + ;; handles name::[expr] + ((= tt js2-LB) + (throw 'return (js2-parse-xml-elem-ref at-pos ns colon-pos))) + + (t + (js2-report-error "msg.no.name.after.coloncolon")))) + + (if (and (null ns) (zerop member-type-flags)) + name + (prog1 + (setq pn + (make-js2-xml-prop-ref-node :pos pos + :len (- (js2-node-end name) pos) + :at-pos at-pos + :colon-pos colon-pos + :propname name)) + (js2-node-add-children pn name)))))) + +(defun js2-parse-xml-elem-ref (at-pos &optional namespace colon-pos) + "Parse the [expr] portion of an xml element reference. +For instance, @[expr], @*::[expr], or ns::[expr]." + (let* ((lb js2-token-beg) + (pos (or at-pos lb)) + rb + (expr (js2-parse-expr)) + (end (js2-node-end expr)) + pn) + (if (js2-must-match js2-RB "msg.no.bracket.index") + (setq rb js2-token-beg + end js2-token-end)) + (prog1 + (setq pn + (make-js2-xml-elem-ref-node :pos pos + :len (- end pos) + :namespace namespace + :colon-pos colon-pos + :at-pos at-pos + :expr expr + :lb (js2-relpos lb pos) + :rb (js2-relpos rb pos))) + (js2-node-add-children pn namespace expr)))) + +(defun js2-parse-primary-expr () + "Parses a literal (leaf) expression of some sort. +Includes complex literals such as functions, object-literals, +array-literals, array comprehensions and regular expressions." + (let ((tt-flagged (js2-next-flagged-token)) + pn ; parent node (usually return value) + tt + px-pos ; paren-expr pos + len + flags ; regexp flags + expr) + (setq tt js2-current-token) + (cond + ((= tt js2-FUNCTION) + (js2-parse-function 'FUNCTION_EXPRESSION)) + + ((= tt js2-LB) + (js2-parse-array-literal)) + + ((= tt js2-LC) + (js2-parse-object-literal)) + + ((= tt js2-LET) + (js2-parse-let js2-token-beg)) + + ((= tt js2-LP) + (setq px-pos js2-token-beg + expr (js2-parse-expr)) + (js2-must-match js2-RP "msg.no.paren") + (setq pn (make-js2-paren-node :pos px-pos + :expr expr + :len (- js2-token-end px-pos))) + (js2-node-add-children pn (js2-paren-node-expr pn)) + pn) + + ((= tt js2-XMLATTR) + (js2-must-have-xml) + (js2-parse-attribute-access)) + + ((= tt js2-NAME) + (js2-parse-name tt-flagged tt)) + + ((= tt js2-NUMBER) + (make-js2-number-node)) + + ((= tt js2-STRING) + (prog1 + (make-js2-string-node) + (js2-record-face 'font-lock-string-face))) + + ((or (= tt js2-DIV) (= tt js2-ASSIGN_DIV)) + ;; Got / or /= which in this context means a regexp literal + (setq px-pos js2-token-beg) + (js2-read-regexp tt) + (setq flags js2-ts-regexp-flags + js2-ts-regexp-flags nil) + (prog1 + (make-js2-regexp-node :pos px-pos + :len (- js2-ts-cursor px-pos) + :value js2-ts-string + :flags flags) + (js2-set-face px-pos js2-ts-cursor 'font-lock-string-face 'record))) + + ((or (= tt js2-NULL) + (= tt js2-THIS) + (= tt js2-FALSE) + (= tt js2-TRUE)) + (make-js2-keyword-node :type tt)) + + ((= tt js2-RESERVED) + (js2-report-error "msg.reserved.id") + (make-js2-name-node)) + + ((= tt js2-ERROR) + ;; the scanner or one of its subroutines reported the error. + (make-js2-error-node)) + + ((= tt js2-EOF) + (setq px-pos (point-at-bol) + len (- js2-ts-cursor px-pos)) + (js2-report-error "msg.unexpected.eof" nil px-pos len) + (make-js2-error-node :pos px-pos :len len)) + + (t + (js2-report-error "msg.syntax") + (make-js2-error-node))))) + +(defun js2-parse-name (tt-flagged tt) + (let ((name js2-ts-string) + (name-pos js2-token-beg)) + (if (and (js2-flag-set-p tt-flagged js2-ti-check-label) + (= (js2-peek-token) js2-COLON)) + (prog1 + ;; Do not consume colon, it is used as unwind indicator + ;; to return to statementHelper. + (make-js2-label-node :pos name-pos + :len (- js2-token-end name-pos) + :name name) + (js2-set-face name-pos + js2-token-end + 'font-lock-variable-name-face 'record)) + ;; Otherwise not a label, just a name. Unfortunately peeking + ;; the next token to check for a colon has biffed js2-token-beg + ;; and js2-token-end. We store the name's bounds in buffer vars + ;; and `js2-create-name-node' uses them. + (js2-save-name-token-data name-pos name) + (if js2-compiler-xml-available + (js2-parse-property-name nil name 0) + (js2-create-name-node 'check-activation))))) + +(defsubst js2-parse-warn-trailing-comma (msg pos elems comma-pos) + (js2-add-strict-warning + msg nil + ;; back up from comma to beginning of line or array/objlit + (max (if elems + (js2-node-pos (car elems)) + pos) + (save-excursion + (goto-char comma-pos) + (back-to-indentation) + (point))) + comma-pos)) + +(defun js2-parse-array-literal () + (let ((pos js2-token-beg) + (end js2-token-end) + (after-lb-or-comma t) + after-comma + tt + elems + pn + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (cond + ;; comma + ((= tt js2-COMMA) + (js2-consume-token) + (setq after-comma js2-token-end) + (if (not after-lb-or-comma) + (setq after-lb-or-comma t) + (push nil elems))) + + ;; end of array + ((or (= tt js2-RB) + (= tt js2-EOF)) ; prevent infinite loop + (if (= tt js2-EOF) + (js2-report-error "msg.no.bracket.arg" nil pos) + (js2-consume-token)) + (setq continue nil + end js2-token-end + pn (make-js2-array-node :pos pos + :len (- js2-ts-cursor pos) + :elems (nreverse elems))) + (apply #'js2-node-add-children pn (js2-array-node-elems pn)) + (when after-comma + (js2-parse-warn-trailing-comma "msg.array.trailing.comma" + pos elems after-comma))) + + ;; array comp + ((and (>= js2-language-version 170) + (= tt js2-FOR) ; check for array comprehension + (not after-lb-or-comma) ; "for" can't follow a comma + elems ; must have at least 1 element + (not (cdr elems))) ; but no 2nd element + (setf continue nil + pn (js2-parse-array-comprehension (car elems) pos))) + + ;; another element + (t + (unless after-lb-or-comma + (js2-report-error "msg.no.bracket.arg")) + (push (js2-parse-assign-expr) elems) + (setq after-lb-or-comma nil + after-comma nil)))) + pn)) + +(defun js2-parse-array-comprehension (expr pos) + "Parse a JavaScript 1.7 Array Comprehension. +EXPR is the first expression after the opening left-bracket. +POS is the beginning of the LB token preceding EXPR. +We should have just parsed the 'for' keyword before calling this function." + (let (loops + filter + if-pos + result) + (while (= (js2-peek-token) js2-FOR) + (push (js2-parse-array-comp-loop) loops)) + (when (= (js2-peek-token) js2-IF) + (js2-consume-token) + (setq if-pos (- js2-token-beg pos) ; relative + filter (js2-parse-condition))) + (js2-must-match js2-RB "msg.no.bracket.arg" pos) + (setq result (make-js2-array-comp-node :pos pos + :len (- js2-ts-cursor pos) + :result expr + :loops (nreverse loops) + :filter (car filter) + :lp (js2-relpos (second filter) pos) + :rp (js2-relpos (third filter) pos) + :if-pos if-pos)) + (apply #'js2-node-add-children result expr (car filter) + (js2-array-comp-node-loops result)) + result)) + +(defun js2-parse-array-comp-loop () + "Parse a 'for [each] (foo in bar)' expression in an Array comprehension. +Last token peeked should be the initial FOR." + (let ((pos js2-token-beg) + (pn (make-js2-array-comp-loop-node)) + tt + iter + obj + foreach-p + in-pos + each-pos + lp + rp) + (assert (= (js2-next-token) js2-FOR)) ; consumes token + (js2-push-scope pn) + (unwind-protect + (progn + (when (js2-match-token js2-NAME) + (if (string= js2-ts-string "each") + (progn + (setq foreach-p t + each-pos (- js2-token-beg pos)) ; relative + (js2-record-face 'font-lock-keyword-face)) + (js2-report-error "msg.no.paren.for"))) + + (if (js2-must-match js2-LP "msg.no.paren.for") + (setq lp (- js2-token-beg pos))) + + (setq tt (js2-peek-token)) + (cond + ((or (= tt js2-LB) + (= tt js2-LC)) + ;; handle destructuring assignment + (setq iter (js2-parse-primary-expr))) + + ((js2-valid-prop-name-token tt) + (js2-consume-token) + (setq iter (js2-create-name-node))) + + (t + (js2-report-error "msg.bad.var"))) + + ;; Define as a let since we want the scope of the variable to + ;; be restricted to the array comprehension + (if (js2-name-node-p iter) + (js2-define-symbol js2-LET (js2-name-node-name iter) pn t)) + + (if (js2-must-match js2-IN "msg.in.after.for.name") + (setq in-pos (- js2-token-beg pos))) + + (setq obj (js2-parse-expr)) + (if (js2-must-match js2-RP "msg.no.paren.for.ctrl") + (setq rp (- js2-token-beg pos))) + + (setf (js2-node-pos pn) pos + (js2-node-len pn) (- js2-ts-cursor pos) + (js2-array-comp-loop-node-iterator pn) iter + (js2-array-comp-loop-node-object pn) obj + (js2-array-comp-loop-node-in-pos pn) in-pos + (js2-array-comp-loop-node-each-pos pn) each-pos + (js2-array-comp-loop-node-foreach-p pn) foreach-p + (js2-array-comp-loop-node-lp pn) lp + (js2-array-comp-loop-node-rp pn) rp) + (js2-node-add-children pn iter obj)) + (js2-pop-scope)) + pn)) + +(defun js2-parse-object-literal () + (let ((pos js2-token-beg) + tt + elems + result + after-comma + (continue t)) + (while continue + (setq tt (js2-peek-token)) + (cond + ;; {foo: ...}, {'foo': ...}, {get foo() {...}}, or {set foo(x) {...}} + ((or (js2-valid-prop-name-token tt) + (= tt js2-STRING)) + (setq after-comma nil + result (js2-parse-named-prop tt)) + (if (and (null result) + (not js2-recover-from-parse-errors)) + (setq continue nil) + (push result elems))) + + ;; {12: x} or {10.7: x} + ((= tt js2-NUMBER) + (js2-consume-token) + (setq after-comma nil) + (push (js2-parse-plain-property (make-js2-number-node)) elems)) + + ;; trailing comma + ((= tt js2-RC) + (setq continue nil) + (if after-comma + (js2-parse-warn-trailing-comma "msg.extra.trailing.comma" + pos elems after-comma))) + (t + (js2-report-error "msg.bad.prop") + (unless js2-recover-from-parse-errors + (setq continue nil)))) ; end switch + + (if (js2-match-token js2-COMMA) + (setq after-comma js2-token-end) + (setq continue nil))) ; end loop + + (js2-must-match js2-RC "msg.no.brace.prop") + (setq result (make-js2-object-node :pos pos + :len (- js2-ts-cursor pos) + :elems (nreverse elems))) + (apply #'js2-node-add-children result (js2-object-node-elems result)) + result)) + +(defun js2-parse-named-prop (tt) + "Parse a name, string, or getter/setter object property." + (js2-consume-token) + (let ((string-prop (and (= tt js2-STRING) + (make-js2-string-node))) + expr + (ppos js2-token-beg) + (pend js2-token-end) + (name (js2-create-name-node)) + (prop js2-ts-string)) + + (if (and (= tt js2-NAME) + (= (js2-peek-token) js2-NAME) + (or (string= prop "get") + (string= prop "set"))) + (progn + ;; getter/setter prop + (js2-consume-token) + (js2-set-face ppos pend 'font-lock-keyword-face 'record) ; get/set + (js2-record-face 'font-lock-function-name-face) ; for peeked name + (setq name (js2-create-name-node)) ; discard get/set & use peeked name + (js2-parse-getter-setter-prop ppos name (string= prop "get"))) + + ;; regular prop + (prog1 + (setq expr (js2-parse-plain-property (or string-prop name))) + (js2-set-face ppos pend + (if (js2-function-node-p + (js2-object-prop-node-right expr)) + 'font-lock-function-name-face + 'font-lock-variable-name-face) + 'record))))) + +(defun js2-parse-plain-property (prop) + "Parse a non-getter/setter property in an object literal. +PROP is the node representing the property: a number, name or string." + (js2-must-match js2-COLON "msg.no.colon.prop") + (let* ((pos (js2-node-pos prop)) + (colon (- js2-token-beg pos)) + (expr (js2-parse-assign-expr)) + (result (make-js2-object-prop-node + :pos pos + ;; don't include last consumed token in length + :len (- (+ (js2-node-pos expr) + (js2-node-len expr)) + pos) + :left prop + :right expr + :op-pos colon))) + (js2-node-add-children result prop expr) + result)) + +(defun js2-parse-getter-setter-prop (pos prop get-p) + "Parse getter or setter property in an object literal. +JavaScript syntax is: + + { get foo() {...}, set foo(x) {...} } + +POS is the start position of the `get' or `set' keyword. +PROP is the `js2-name-node' representing the property name. +GET-P is non-nil if the keyword was `get'." + (let ((type (if get-p js2-GET js2-SET)) + result + end + (fn (js2-parse-function 'FUNCTION_EXPRESSION))) + + ;; it has to be an anonymous function, as we already parsed the name + (if (/= (js2-node-type fn) js2-FUNCTION) + (js2-report-error "msg.bad.prop") + (if (plusp (length (js2-function-name fn))) + (js2-report-error "msg.bad.prop"))) + + (js2-node-set-prop fn 'GETTER_SETTER type) ; for codegen + (setq end (js2-node-end fn) + result (make-js2-getter-setter-node :type type + :pos pos + :len (- end pos) + :left prop + :right fn)) + (js2-node-add-children result prop fn) + result)) + +(defun js2-create-name-node (&optional check-activation-p token) + "Create a name node using the token info from last scanned name. +In some cases we need to either synthesize a name node, or we lost +the name token information by peeking. If the TOKEN parameter is +not `js2-NAME', then we use the token info saved in instance vars." + (let ((beg js2-token-beg) + (s js2-ts-string) + name) + (when (/= js2-current-token js2-NAME) + (setq beg (or js2-prev-name-token-start js2-ts-cursor) + s js2-prev-name-token-string + js2-prev-name-token-start nil + js2-prev-name-token-string nil)) + (setq name (make-js2-name-node :pos beg + :name s + :len (length s))) + (if check-activation-p + (js2-check-activation-name s (or token js2-NAME))) + name)) + +(provide 'js2-parse) + +;;; js2-parse.el ends here +;;; js2-indent.el --- indentation for js2-mode +;; +;; Copyright (C) 2008 Steve Yegge +;; Author: Steve Yegge (steve.yegge@gmail.com) +;; Maintainer: Steve Yegge (steve.yegge@gmail.com) + +;; Commentary: +;; +;; This indenter is based on Karl Landström's "javascript.el" indenter. +;; Karl cleverly deduces that the desired indentation level is often a +;; function of paren/bracket/brace nesting depth, which can be determined +;; quickly via the built-in `parse-partial-sexp' function. His indenter +;; then does some equally clever checks to see if we're in the context of a +;; substatement of a possibly braceless statement keyword such as if, while, +;; or finally. This approach yields pretty good results. +;; +;; The indenter is often "wrong", however, and needs to be overridden. +;; The right long-term solution is probably to emulate (or modify) +;; cc-engine, but it's thousands upon thousands of lines of code. Even +;; if you were to assume the accurate parse tree from `js2-parse' is +;; present, indentation is still thousands of lines of code (I've been +;; down that path) to handle every possible syntactic edge case, and in +;; any case, relying on the parse tree is undesirable because parsing is +;; slow. So you might as well go the cc-engine approach, but it's a +;; huge pile of work that I'm just not up for any time soon. +;; +;; In the meantime, the compromise solution is that we offer a +;; "bounce indenter", configured with `js2-bounce-indent-flag', which +;; cycles the current line indent among various likely guess points. +;; This approach is far from perfect, but should at least make it +;; slightly easier to move the line towards its desired indentation +;; when manually overriding Karl's heuristic nesting guesser. +;; +;; I've made miscellaneous tweaks to Karl's code to handle some Ecma +;; extensions such as `let' and Array comprehensions, and will likely +;; make further tweaks to it, but major kudos to Karl for coming up with +;; the initial approach, which packs a lot of punch for so little code. + +;;; Code: + +(defconst js-possibly-braceless-keyword-re + (regexp-opt + '("catch" "do" "else" "finally" "for" "if" "try" "while" "with" "let") + 'words) + "Regular expression matching keywords that are optionally +followed by an opening brace.") + +(defconst js-indent-operator-re + (concat "[-+*/%<>=&^|?:.]\\([^-+*/]\\|$\\)\\|" + (regexp-opt '("in" "instanceof") 'words)) + "Regular expression matching operators that affect indentation +of continued expressions.") + +;; This function has horrible results if you're typing an array +;; such as [[1, 2], [3, 4], [5, 6]]. Bounce indenting -really- sucks +;; in conjunction with electric-indent, so just disabling it. +(defsubst js2-code-at-bol-p () + "Return t if the first character on line is non-whitespace." + nil) +;; (not (memq (char-after (point-at-bol)) +;; '(? ?\t))))) + +(defun js2-insert-and-indent (key) + "Run command bound to key and indent current line. Runs the command +bound to KEY in the global keymap and indents the current line." + (interactive (list (this-command-keys))) + (let ((cmd (lookup-key (current-global-map) key))) + (if (commandp cmd) + (call-interactively cmd))) + ;; don't do the electric keys inside comments or strings, + ;; and don't do bounce-indent with them. + (let ((parse-state (parse-partial-sexp (point-min) (point))) + (js2-bounce-indent-flag (js2-code-at-bol-p))) + (unless (or (nth 3 parse-state) + (nth 4 parse-state)) + (indent-according-to-mode)))) + +(defun js-re-search-forward-inner (regexp &optional bound count) + "Auxiliary function for `js-re-search-forward'." + (let ((parse) + (saved-point (point-min))) + (while (> count 0) + (re-search-forward regexp bound) + (setq parse (parse-partial-sexp saved-point (point))) + (cond ((nth 3 parse) + (re-search-forward + (concat "\\([^\\]\\|^\\)" (string (nth 3 parse))) + (save-excursion (end-of-line) (point)) t)) + ((nth 7 parse) + (forward-line)) + ((or (nth 4 parse) + (and (eq (char-before) ?\/) (eq (char-after) ?\*))) + (re-search-forward "\\*/")) + (t + (setq count (1- count)))) + (setq saved-point (point)))) + (point)) + +(defun js-re-search-forward (regexp &optional bound noerror count) + "Search forward but ignore strings and comments. Invokes +`re-search-forward' but treats the buffer as if strings and +comments have been removed." + (let ((saved-point (point)) + (search-expr + (cond ((null count) + '(js-re-search-forward-inner regexp bound 1)) + ((< count 0) + '(js-re-search-backward-inner regexp bound (- count))) + ((> count 0) + '(js-re-search-forward-inner regexp bound count))))) + (condition-case err + (eval search-expr) + (search-failed + (goto-char saved-point) + (unless noerror + (error (error-message-string err))))))) + +(defun js-re-search-backward-inner (regexp &optional bound count) + "Auxiliary function for `js-re-search-backward'." + (let ((parse) + (saved-point (point-min))) + (while (> count 0) + (re-search-backward regexp bound) + (setq parse (parse-partial-sexp saved-point (point))) + (cond ((nth 3 parse) + (re-search-backward + (concat "\\([^\\]\\|^\\)" (string (nth 3 parse))) + (save-excursion (beginning-of-line) (point)) t)) + ((nth 7 parse) + (goto-char (nth 8 parse))) + ((or (nth 4 parse) + (and (eq (char-before) ?/) (eq (char-after) ?*))) + (re-search-backward "/\\*")) + (t + (setq count (1- count)))))) + (point)) + +(defun js-re-search-backward (regexp &optional bound noerror count) + "Search backward but ignore strings and comments. Invokes +`re-search-backward' but treats the buffer as if strings and +comments have been removed." + (let ((saved-point (point)) + (search-expr + (cond ((null count) + '(js-re-search-backward-inner regexp bound 1)) + ((< count 0) + '(js-re-search-forward-inner regexp bound (- count))) + ((> count 0) + '(js-re-search-backward-inner regexp bound count))))) + (condition-case err + (eval search-expr) + (search-failed + (goto-char saved-point) + (unless noerror + (error (error-message-string err))))))) + +(defun js-looking-at-operator-p () + "Return non-nil if text after point is an operator (that is not +a comma)." + (save-match-data + (and (looking-at js-indent-operator-re) + (or (not (looking-at ":")) + (save-excursion + (and (js-re-search-backward "[?:{]\\|\\<case\\>" nil t) + (looking-at "?"))))))) + +(defun js-continued-expression-p () + "Returns non-nil if the current line continues an expression." + (save-excursion + (back-to-indentation) + (or (js-looking-at-operator-p) + (and (js-re-search-backward "\n" nil t) + (progn + (skip-chars-backward " \t") + (backward-char) + (and (js-looking-at-operator-p) + (and (progn (backward-char) + (not (looking-at "\\*\\|++\\|--\\|/[/*]")))))))))) + +(defun js-end-of-do-while-loop-p () + "Returns non-nil if word after point is `while' of a do-while +statement, else returns nil. A braceless do-while statement +spanning several lines requires that the start of the loop is +indented to the same column as the current line." + (interactive) + (save-excursion + (save-match-data + (when (looking-at "\\s-*\\<while\\>") + (if (save-excursion + (skip-chars-backward "[ \t\n]*}") + (looking-at "[ \t\n]*}")) + (save-excursion + (backward-list) (backward-word 1) (looking-at "\\<do\\>")) + (js-re-search-backward "\\<do\\>" (point-at-bol) t) + (or (looking-at "\\<do\\>") + (let ((saved-indent (current-indentation))) + (while (and (js-re-search-backward "^[ \t]*\\<" nil t) + (/= (current-indentation) saved-indent))) + (and (looking-at "[ \t]*\\<do\\>") + (not (js-re-search-forward + "\\<while\\>" (point-at-eol) t)) + (= (current-indentation) saved-indent))))))))) + +(defun js-ctrl-statement-indentation () + "Returns the proper indentation of the current line if it +starts the body of a control statement without braces, else +returns nil." + (let (forward-sexp-function) ; temporarily unbind it + (save-excursion + (back-to-indentation) + (when (save-excursion + (and (not (js2-same-line (point-min))) + (not (looking-at "{")) + (js-re-search-backward "[[:graph:]]" nil t) + (not (looking-at "[{([]")) + (progn + (forward-char) + ;; scan-sexps sometimes throws an error + (ignore-errors (backward-sexp)) + (when (looking-at "(") (backward-word 1)) + (and (save-excursion + (skip-chars-backward " \t}" (point-at-bol)) + (bolp)) + (looking-at js-possibly-braceless-keyword-re) + (not (js-end-of-do-while-loop-p)))))) + (save-excursion + (goto-char (match-beginning 0)) + (+ (current-indentation) js2-basic-offset)))))) + +(defun js2-indent-in-array-comp (parse-status) + "Return non-nil if we think we're in an array comprehension. +In particular, return the buffer position of the first `for' kwd." + (let ((end (point))) + (when (nth 1 parse-status) + (save-excursion + (goto-char (nth 1 parse-status)) + (when (looking-at "\\[") + (forward-char 1) + (js2-forward-sws) + (if (looking-at "[[{]") + (let (forward-sexp-function) ; use lisp version + (forward-sexp) ; skip destructuring form + (js2-forward-sws) + (if (and (/= (char-after) ?,) ; regular array + (looking-at "for")) + (match-beginning 0))) + ;; to skip arbitrary expressions we need the parser, + ;; so we'll just guess at it. + (if (re-search-forward "[^,]* \\(for\\) " end t) + (match-beginning 1)))))))) + +(defun js2-array-comp-indentation (parse-status for-kwd) + (if (js2-same-line for-kwd) + ;; first continuation line + (save-excursion + (goto-char (nth 1 parse-status)) + (forward-char 1) + (skip-chars-forward " \t") + (current-column)) + (save-excursion + (goto-char for-kwd) + (current-column)))) + +(defun js-proper-indentation (parse-status) + "Return the proper indentation for the current line." + (save-excursion + (back-to-indentation) + (let ((ctrl-stmt-indent (js-ctrl-statement-indentation)) + (same-indent-p (looking-at "[]})]\\|\\<case\\>\\|\\<default\\>")) + (continued-expr-p (js-continued-expression-p)) + (bracket (nth 1 parse-status)) + beg) + (cond + ;; indent array comprehension continuation lines specially + ((and bracket + (not (js2-same-line bracket)) + (setq beg (js2-indent-in-array-comp parse-status)) + (>= (point) (save-excursion + (goto-char beg) + (point-at-bol)))) ; at or after first loop? + (js2-array-comp-indentation parse-status beg)) + + (ctrl-stmt-indent) + + (bracket + (goto-char bracket) + (cond + ((looking-at "[({[][ \t]*\\(/[/*]\\|$\\)") + (let ((p (parse-partial-sexp (point-at-bol) (point)))) + (when (save-excursion (skip-chars-backward " \t)") + (looking-at ")")) + (backward-list)) + (if (nth 1 p) + (progn (goto-char (1+ (nth 1 p))) + (skip-chars-forward " \t")) + (back-to-indentation)) + (cond (same-indent-p + (current-column)) + (continued-expr-p + (+ (current-column) (* 2 js2-basic-offset))) + (t + (+ (current-column) js2-basic-offset))))) + (t + (unless same-indent-p + (forward-char) + (skip-chars-forward " \t")) + (current-column)))) + + (continued-expr-p js2-basic-offset) + (t 0))))) + +(defun js2-lineup-comment (parse-status) + "Indent a multi-line block comment continuation line." + (let* ((beg (nth 8 parse-status)) + (first-line (js2-same-line beg)) + (offset (save-excursion + (goto-char beg) + (if (looking-at "/\\*") + (+ 1 (current-column)) + 0)))) + (unless first-line + (indent-line-to offset)))) + +(defun js2-backward-sws () + "Move backward through whitespace and comments." + (interactive) + (while (forward-comment -1))) + +(defun js2-forward-sws () + "Move forward through whitespace and comments." + (interactive) + (while (forward-comment 1))) + +(defsubst 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))) + +(defsubst js2-arglist-close () + "Return non-nil if we're on a line beginning with a close-paren/brace." + (save-match-data + (save-excursion + (goto-char (point-at-bol)) + (js2-forward-sws) + (looking-at "[])}]")))) + +(defsubst js2-indent-looks-like-label-p () + (goto-char (point-at-bol)) + (js2-forward-sws) + (looking-at (concat js2-mode-identifier-re ":"))) + +(defun js2-indent-in-objlit-p (parse-status) + "Return non-nil if this looks like an object-literal entry." + (let ((start (nth 1 parse-status))) + (and + start + (save-excursion + (and (zerop (forward-line -1)) + (not (< (point) start)) ; crossed a {} boundary + (js2-indent-looks-like-label-p))) + (save-excursion + (js2-indent-looks-like-label-p))))) + +;; if prev line looks like foobar({ then we're passing an object +;; literal to a function call, and people pretty much always want to +;; de-dent back to the previous line, so move the 'basic-offset' +;; position to the front. +(defsubst js2-indent-objlit-arg-p (parse-status) + (save-excursion + (back-to-indentation) + (js2-backward-sws) + (and (eq (1- (point)) (nth 1 parse-status)) + (eq (char-before) ?{) + (progn + (forward-char -1) + (skip-chars-backward " \t") + (eq (char-before) ?\())))) + +(defsubst js2-indent-case-block-p () + (save-excursion + (back-to-indentation) + (js2-backward-sws) + (goto-char (point-at-bol)) + (skip-chars-forward " \t") + (save-match-data + (looking-at "case\\s-.+:")))) + +(defsubst js2-syntax-bol () + "Return the point at the first non-whitespace char on the line. +Returns `point-at-bol' if the line is empty." + (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (point))) + +(defun js2-bounce-indent (normal-col parse-status) + "Cycle among alternate computed indentation positions. +PARSE-STATUS is the result of `parse-partial-sexp' from the beginning +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." + (let ((cur-indent (js2-current-indent)) + (old-buffer-undo-list buffer-undo-list) + ;; Emacs 21 only has `count-lines', not `line-number-at-pos' + (current-line (save-excursion + (forward-line 0) ; move to bol + (1+ (count-lines (point-min) (point))))) + positions + pos + anchor + arglist-cont + same-indent + prev-line-col + basic-offset + computed-pos) + ;; temporarily don't record undo info, if user requested this + (if js2-mode-indent-inhibit-undo + (setq buffer-undo-list t)) + (unwind-protect + (progn + ;; first likely point: indent from beginning of previous code line + (push (setq basic-offset + (+ (save-excursion + (back-to-indentation) + (js2-backward-sws) + (back-to-indentation) + (setq prev-line-col (current-column))) + js2-basic-offset)) + positions) + + ;; second likely point: indent from assign-expr RHS. This + ;; is just a crude guess based on finding " = " on the previous + ;; line containing actual code. + (setq pos (save-excursion + (save-match-data + (forward-line -1) + (goto-char (point-at-bol)) + (when (re-search-forward "\\s-+\\(=\\)\\s-+" + (point-at-eol) t) + (goto-char (match-end 1)) + (skip-chars-forward " \t\r\n") + (current-column))))) + (when pos + (incf pos js2-basic-offset) + (unless (member pos positions) + (push pos positions))) + + ;; third likely point: same indent as previous line of code. + ;; Make it the first likely point if we're not on an + ;; arglist-close line and previous line ends in a comma, or + ;; both this line and prev line look like object-literal + ;; elements. + (setq pos (save-excursion + (goto-char (point-at-bol)) + (js2-backward-sws) + (back-to-indentation) + (prog1 + (current-column) + ;; while we're here, look for trailing comma + (if (save-excursion + (goto-char (point-at-eol)) + (js2-backward-sws) + (eq (char-before) ?,)) + (setq arglist-cont (1- (point))))))) + (when pos + (if (and (or arglist-cont + (js2-indent-in-objlit-p parse-status)) + (not (js2-arglist-close))) + (setq same-indent pos)) + (unless (member pos positions) + (push pos positions))) + + ;; fourth likely position: first preceding code with less indentation + ;; than the immediately preceding code line. + (setq pos (save-excursion + (js2-backward-sws) + (back-to-indentation) + (setq anchor (current-column)) + (while (and (zerop (forward-line -1)) + (>= (progn + (back-to-indentation) + (current-column)) + anchor))) + (setq pos (current-column)))) + (unless (member pos positions) + (push pos positions)) + + ;; put nesting-heuristic position first in list, sort rest + (setq positions (nreverse (sort positions '<))) + (setq positions (cons normal-col (delete normal-col positions))) + + ;; comma-list continuation lines: prev line indent takes precedence + (if same-indent + (setq positions + (cons same-indent + (sort (delete same-indent positions) '<)))) + + ;; common special cases where we want to indent in from previous line + (if (or (js2-indent-case-block-p) + (js2-indent-objlit-arg-p parse-status)) + (setq positions + (cons basic-offset + (delete basic-offset positions)))) + + ;; record whether we're already sitting on one of the alternatives + (setq pos (member cur-indent positions)) + (cond + ;; case 0: we're one one of the alternatives and this is the + ;; first time they've pressed TAB on this line (best-guess). + ((and js2-mode-indent-ignore-first-tab + pos + ;; first time pressing TAB on this line? + (not (eq js2-mode-last-indented-line current-line))) + ;; do nothing + (setq computed-pos nil)) + ;; case 1: only one computed position => use it + ((null (cdr positions)) + (setq computed-pos 0)) + ;; case 2: not on any of the computed spots => use main spot + ((not pos) + (setq computed-pos 0)) + ;; case 3: on last position: cycle to first position + ((null (cdr pos)) + (setq computed-pos 0)) + ;; case 4: on intermediate position: cycle to next position + (t + (setq computed-pos (js2-position (second pos) positions)))) + + ;; see if any hooks want to indent; otherwise we do it + (loop with result = nil + for hook in js2-indent-hook + while (null result) + do + (setq result (funcall hook positions computed-pos)) + finally do + (unless (or result (null computed-pos)) + (indent-line-to (nth computed-pos positions))))) + + ;; finally + (if js2-mode-indent-inhibit-undo + (setq buffer-undo-list old-buffer-undo-list)) + ;; see commentary for `js2-mode-last-indented-line' + (setq js2-mode-last-indented-line current-line)))) + +(defsubst js2-1-line-comment-continuation-p () + "Return t if we're in a 1-line comment continuation. +If so, we don't ever want to use bounce-indent." + (save-excursion + (save-match-data + (and (progn + (forward-line 0) + (looking-at "\\s-*//")) + (progn + (forward-line -1) + (forward-line 0) + (when (looking-at "\\s-*$") + (js2-backward-sws) + (forward-line 0)) + (looking-at "\\s-*//")))))) + +(defun js2-indent-line () + "Indent the current line as JavaScript source text." + (interactive) + (let (parse-status + current-indent + offset + indent-col + moved + ;; don't whine about errors/warnings when we're indenting. + ;; This has to be set before calling parse-partial-sexp below. + (inhibit-point-motion-hooks t)) + (setq parse-status (save-excursion + (parse-partial-sexp (point-min) + (point-at-bol))) + offset (- (point) (save-excursion + (back-to-indentation) + (setq current-indent (current-column)) + (point)))) + (js2-with-underscore-as-word-syntax + (if (nth 4 parse-status) + (js2-lineup-comment parse-status) + (setq indent-col (js-proper-indentation parse-status)) + ;; see comments below about js2-mode-last-indented-line + (when + (cond + ;; bounce-indenting is disabled during electric-key indent. + ;; It doesn't work well on first line of buffer. + ((and js2-bounce-indent-flag + (not (js2-same-line (point-min))) + (not (js2-1-line-comment-continuation-p))) + (js2-bounce-indent indent-col parse-status) + (setq moved t)) + ;; just indent to the guesser's likely spot + ((/= current-indent indent-col) + (indent-line-to indent-col) + (setq moved t))) + (when (and moved (plusp offset)) + (forward-char offset))))))) + +(defun js2-indent-region (start end) + "Indent the region, but don't use bounce indenting." + (let ((js2-bounce-indent-flag nil) + (indent-region-function nil)) + (indent-region start end nil))) ; nil for byte-compiler + +(provide 'js2-indent) + +;;; js2-indent.el ends here + +(eval-when-compile + (require 'cl)) + +(require 'imenu) +(require 'cc-cmds) ; for `c-fill-paragraph' + + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) + +;;;###autoload +(defun js2-mode () + "Major mode for editing JavaScript code." + (interactive) + (js2-mode-check-compat) + (kill-all-local-variables) + (set-syntax-table js2-mode-syntax-table) + (use-local-map js2-mode-map) + (setq major-mode 'js2-mode + mode-name "JavaScript-IDE" + comment-start "//" ; used by comment-region; don't change it + comment-end "") + (setq local-abbrev-table js2-mode-abbrev-table) + (set (make-local-variable 'max-lisp-eval-depth) + (max max-lisp-eval-depth 3000)) + (set (make-local-variable 'indent-line-function) #'js2-indent-line) + (set (make-local-variable 'indent-region-function) #'js2-indent-region) + (set (make-local-variable 'fill-paragraph-function) #'js2-fill-paragraph) + (set (make-local-variable 'before-save-hook) #'js2-before-save) + (set (make-local-variable 'next-error-function) #'js2-next-error) + (set (make-local-variable 'beginning-of-defun-function) #'js2-beginning-of-defun) + (set (make-local-variable 'end-of-defun-function) #'js2-end-of-defun) + ;; We un-confuse `parse-partial-sexp' by setting syntax-table properties + ;; for characters inside regexp literals. + (set (make-local-variable 'parse-sexp-lookup-properties) t) + ;; this is necessary to make `show-paren-function' work properly + (set (make-local-variable 'parse-sexp-ignore-comments) t) + ;; needed for M-x rgrep, among other things + (put 'js2-mode 'find-tag-default-function #'js2-mode-find-tag) + + ;; some variables needed by cc-engine for paragraph-fill, etc. + (setq c-buffer-is-cc-mode t + c-comment-prefix-regexp js2-comment-prefix-regexp + c-paragraph-start js2-paragraph-start + c-paragraph-separate "$" + comment-start-skip js2-comment-start-skip + c-syntactic-ws-start js2-syntactic-ws-start + c-syntactic-ws-end js2-syntactic-ws-end + c-syntactic-eol js2-syntactic-eol) + (if js2-emacs22 + (c-setup-paragraph-variables)) + + ;; We do our own syntax highlighting based on the parse tree. + ;; However, we want minor modes that add keywords to highlight properly + ;; (examples: doxymacs, column-marker). We do this by not letting + ;; font-lock unfontify anything, and telling it to fontify after we + ;; re-parse and re-highlight the buffer. (We currently don't do any + ;; work with regions other than the whole buffer.) + (dolist (var '(font-lock-unfontify-buffer-function + font-lock-unfontify-region-function)) + (set (make-local-variable var) (lambda (&rest args) t))) + + ;; Don't let font-lock do syntactic (string/comment) fontification. + (set (make-local-variable #'font-lock-syntactic-face-function) + (lambda (state) nil)) + + ;; Experiment: make reparse-delay longer for longer files. + (if (plusp js2-dynamic-idle-timer-adjust) + (setq js2-idle-timer-delay + (* js2-idle-timer-delay + (/ (point-max) js2-dynamic-idle-timer-adjust)))) + + (add-hook 'change-major-mode-hook #'js2-mode-exit nil t) + (add-hook 'after-change-functions #'js2-mode-edit nil t) + (setq imenu-create-index-function #'js2-mode-create-imenu-index) + (imenu-add-to-menubar (concat "IM-" mode-name)) + (when js2-mirror-mode + (js2-enter-mirror-mode)) + (add-to-invisibility-spec '(js2-outline . t)) + (set (make-local-variable 'line-move-ignore-invisible) t) + (set (make-local-variable 'forward-sexp-function) #'js2-mode-forward-sexp) + (setq js2-mode-functions-hidden nil + js2-mode-comments-hidden nil + js2-mode-buffer-dirty-p t + js2-mode-parsing nil) + (js2-reparse) + (run-hooks 'js2-mode-hook)) + +(defun js2-mode-check-compat () + "Signal an error if we can't run with this version of Emacs." + (if (and js2-mode-must-byte-compile + (not (byte-code-function-p (symbol-function 'js2-mode)))) + (error "You must byte-compile js2-mode before using it.")) + (if (and (boundp 'running-xemacs) + running-xemacs) + (error "js2-mode is not compatible with XEmacs")) + (unless (>= emacs-major-version 21) + (error "js2-mode requires GNU Emacs version 21 or higher"))) + +(defun js2-mode-exit () + (interactive) + (when js2-mode-node-overlay + (delete-overlay js2-mode-node-overlay) + (setq js2-mode-node-overlay nil)) + (js2-remove-overlays) + (setq js2-mode-ast nil) + (remove-hook 'change-major-mode-hook #'js2-mode-exit t) + (remove-from-invisibility-spec '(js2-outline . t)) + (js2-mode-show-all) + (js2-with-unmodifying-text-property-changes + (js2-clear-face (point-min) (point-max)))) + +(defun js2-before-save () + "Clean up whitespace before saving file. +You can disable this by customizing `js2-cleanup-whitespace'." + (when js2-cleanup-whitespace + (let ((col (current-column))) + (delete-trailing-whitespace) + ;; don't change trailing whitespace on current line + (unless (eq (current-column) col) + (indent-to col))))) + +(defsubst js2-mode-reset-timer () + (if js2-mode-parse-timer + (cancel-timer js2-mode-parse-timer)) + (setq js2-mode-parsing nil) + (setq js2-mode-parse-timer + (run-with-idle-timer js2-idle-timer-delay nil #'js2-reparse))) + +(defun js2-mode-edit (beg end len) + "Schedule a new parse after buffer is edited." + (setq js2-mode-buffer-dirty-p t) + (js2-mode-hide-overlay) + (js2-mode-reset-timer)) + +(defun js2-mode-run-font-lock () + "Run `font-lock-fontify-buffer' after parsing/highlighting. +This is intended to allow modes that install their own font-lock keywords +to work with js2-mode. In practice it never seems to work for long. +Hopefully the Emacs maintainers can help figure out a way to make it work." + (when (and (boundp 'font-lock-keywords) + font-lock-keywords + (boundp 'font-lock-mode) + font-lock-mode) + ;; TODO: font-lock and jit-lock really really REALLY don't want to + ;; play nicely with js2-mode. They go out of their way to fail to + ;; provide any option for saying "look, fontify the goddamn buffer + ;; with just the keywords already". Argh. + (setq font-lock-defaults (list font-lock-keywords 'keywords-only)) + (let (font-lock-verbose) + (font-lock-default-fontify-buffer)))) + +(defun js2-reparse (&optional force) + "Re-parse current buffer after user finishes some data entry. +If we get any user input while parsing, including cursor motion, +we discard the parse and reschedule it. If FORCE is nil, then the +buffer will only rebuild its `js2-mode-ast' if the buffer is dirty." + (let (time + interrupted-p + (js2-compiler-strict-mode js2-mode-show-strict-warnings)) + (unless js2-mode-parsing + (setq js2-mode-parsing t) + (unwind-protect + (when (or js2-mode-buffer-dirty-p force) + (js2-remove-overlays) + (js2-with-unmodifying-text-property-changes + (setq js2-mode-buffer-dirty-p nil + js2-mode-fontifications nil + js2-mode-deferred-properties nil) + (if js2-mode-verbose-parse-p + (message "parsing...")) + (setq time + (js2-time + (setq interrupted-p + (catch 'interrupted + (setq js2-mode-ast (js2-parse)) + (js2-mode-fontify-regions) + (js2-mode-remove-suppressed-warnings) + (js2-mode-show-warnings) + (js2-mode-show-errors) + (js2-mode-run-font-lock) ; note: doesn't work + (if (>= js2-highlight-level 1) + (js2-highlight-jsdoc js2-mode-ast)) + nil)))) + (if interrupted-p + (progn + ;; unfinished parse => try again + (setq js2-mode-buffer-dirty-p t) + (js2-mode-reset-timer)) + (if js2-mode-verbose-parse-p + (message "Parse time: %s" time))))) + ;; finally + (setq js2-mode-parsing nil) + (unless interrupted-p + (setq js2-mode-parse-timer nil)))))) + +(defun js2-mode-show-node () + "Debugging aid: highlight selected AST node on mouse click." + (interactive) + (let ((node (js2-node-at-point)) + beg + end) + (when js2-mode-show-overlay + (if (null node) + (message "No node found at location %s" (point)) + (setq beg (js2-node-abs-pos node) + end (+ beg (js2-node-len node))) + (if js2-mode-node-overlay + (move-overlay js2-mode-node-overlay beg end) + (setq js2-mode-node-overlay (make-overlay beg end)) + (overlay-put js2-mode-node-overlay 'face 'highlight)) + (js2-with-unmodifying-text-property-changes + (put-text-property beg end 'point-left #'js2-mode-hide-overlay)) + (message "%s, parent: %s" + (js2-node-short-name node) + (if (js2-node-parent node) + (js2-node-short-name (js2-node-parent node)) + "nil")))))) + +(defun js2-mode-hide-overlay (&optional p1 p2) + "Remove the debugging overlay when the point moves." + (when js2-mode-node-overlay + (let ((beg (overlay-start js2-mode-node-overlay)) + (end (overlay-end js2-mode-node-overlay))) + ;; Sometimes we're called spuriously. + (unless (and p2 + (>= p2 beg) + (<= p2 end)) + (js2-with-unmodifying-text-property-changes + (remove-text-properties beg end '(point-left nil))) + (delete-overlay js2-mode-node-overlay) + (setq js2-mode-node-overlay nil))))) + +(defun js2-mode-reset () + "Debugging helper; resets everything." + (interactive) + (js2-mode-exit) + (js2-mode)) + +(defsubst js2-mode-show-warn-or-err (e face) + "Highlight a warning or error E with FACE. +E is a list of ((MSG-KEY MSG-ARG) BEG END)." + (let* ((key (first e)) + (beg (second e)) + (end (+ beg (third e))) + ;; Don't inadvertently go out of bounds. + (beg (max (point-min) (min beg (point-max)))) + (end (max (point-min) (min end (point-max)))) + (js2-highlight-level 3) ; so js2-set-face is sure to fire + (ovl (make-overlay beg end))) + (overlay-put ovl 'face face) + (overlay-put ovl 'js2 t) + (put-text-property beg end 'help-echo (js2-get-msg key)) + (put-text-property beg end 'point-entered #'js2-echo-error))) + +(defun js2-remove-overlays () + "Remove overlays from buffer that have a `js2' property." + (let ((beg (point-min)) + (end (point-max))) + (save-excursion + (dolist (o (overlays-in beg end)) + (when (overlay-get o 'js2) + (delete-overlay o)))))) + +(defun js2-mode-fontify-regions () + "Apply fontifications recorded during parsing." + ;; We defer clearing faces as long as possible to eliminate flashing. + (js2-clear-face (point-min) (point-max)) + ;; have to reverse the recorded fontifications so that errors and + ;; warnings overwrite the normal fontifications + (dolist (f (nreverse js2-mode-fontifications)) + (put-text-property (first f) (second f) 'face (third f))) + (setq js2-mode-fontifications nil) + (dolist (p js2-mode-deferred-properties) + (apply #'put-text-property p)) + (setq js2-mode-deferred-properties nil)) + +(defun js2-mode-show-errors () + "Highlight syntax errors." + (when js2-mode-show-parse-errors + (dolist (e (js2-ast-root-errors js2-mode-ast)) + (js2-mode-show-warn-or-err e 'js2-error-face)))) + +(defun js2-mode-remove-suppressed-warnings () + "Take suppressed warnings out of the AST warnings list. +This ensures that the counts and `next-error' are correct." + (setf (js2-ast-root-warnings js2-mode-ast) + (js2-delete-if + (lambda (e) + (let ((key (caar e))) + (or + (and (not js2-strict-trailing-comma-warning) + (string-match "trailing\\.comma" key)) + (and (not js2-strict-cond-assign-warning) + (string= key "msg.equal.as.assign")) + (and js2-missing-semi-one-line-override + (string= key "msg.missing.semi") + (let* ((beg (second e)) + (node (js2-node-at-point beg)) + (fn (js2-mode-find-parent-fn node)) + (body (and fn (js2-function-node-body fn))) + (lc (and body (js2-node-abs-pos body))) + (rc (and lc (+ lc (js2-node-len body))))) + (and fn + (or (null body) + (save-excursion + (goto-char beg) + (and (js2-same-line lc) + (js2-same-line rc)))))))))) + (js2-ast-root-warnings js2-mode-ast)))) + +(defun js2-mode-show-warnings () + "Highlight strict-mode warnings." + (when js2-mode-show-strict-warnings + (dolist (e (js2-ast-root-warnings js2-mode-ast)) + (js2-mode-show-warn-or-err e 'js2-warning-face)))) + +(defun js2-echo-error (old-point new-point) + "Called by point-motion hooks." + (let ((msg (get-text-property new-point 'help-echo))) + (if msg + (message msg)))) + +(defalias #'js2-echo-help #'js2-echo-error) + +(defun js2-enter-key () + "Handle user pressing the Enter key." + (interactive) + (let ((parse-status (save-excursion + (parse-partial-sexp (point-min) (point))))) + (cond + ;; check if we're inside a string + ((nth 3 parse-status) + (js2-mode-split-string parse-status)) + ;; check if inside a block comment + ((nth 4 parse-status) + (js2-mode-extend-comment)) + (t + ;; should probably figure out what the mode-map says we should do + (if js2-indent-on-enter-key + (let ((js2-bounce-indent-flag nil)) + (js2-indent-line))) + (insert "\n") + (if js2-enter-indents-newline + (let ((js2-bounce-indent-flag nil)) + (js2-indent-line))))))) + +(defun js2-mode-split-string (parse-status) + "Turn a newline in mid-string into a string concatenation." + (let* ((col (current-column)) + (quote-char (nth 3 parse-status)) + (quote-string (string quote-char)) + (string-beg (nth 8 parse-status)) + (indent (save-match-data + (or + (save-excursion + (back-to-indentation) + (if (looking-at "\\+") + (current-column))) + (save-excursion + (goto-char string-beg) + (if (looking-back "\\+\\s-+") + (goto-char (match-beginning 0))) + (current-column)))))) + (insert quote-char "\n") + (indent-to indent) + (insert "+ " quote-string) + (when (eolp) + (insert quote-string) + (backward-char 1)))) + +(defun js2-mode-extend-comment () + "When inside a comment block, add comment prefix." + (let (star single col first-line needs-close) + (save-excursion + (back-to-indentation) + (cond + ((looking-at "\\*[^/]") + (setq star t + col (current-column))) + ((looking-at "/\\*") + (setq star t + first-line t + col (1+ (current-column)))) + ((looking-at "//") + (setq single t + col (current-column))))) + ;; Heuristic for whether we need to close the comment: + ;; if we've got a parse error here, assume it's an unterminated + ;; comment. + (setq needs-close + (or + (eq (get-text-property (1- (point)) 'point-entered) + 'js2-echo-error) + ;; The heuristic above doesn't work well when we're + ;; creating a comment and there's another one downstream, + ;; as our parser thinks this one ends at the end of the + ;; next one. (You can have a /* inside a js block comment.) + ;; So just close it if the next non-ws char isn't a *. + (and first-line + (eolp) + (save-excursion + (skip-syntax-forward " ") + (not (eq (char-after) ?*)))))) + (insert "\n") + (cond + (star + (indent-to col) + (insert "* ") + (if (and first-line needs-close) + (save-excursion + (insert "\n") + (indent-to col) + (insert "*/")))) + (single + (when (save-excursion + (and (zerop (forward-line 1)) + (looking-at "\\s-*//"))) + (indent-to col) + (insert "// ")))))) + +(defun js2-fill-string (beg quote) + "Line-wrap a single-line string into a multi-line string. +BEG is the string beginning, QUOTE is the quote char." + (let* ((squote (string quote)) + (end (if (re-search-forward (concat "[^\\]" squote) + (point-at-eol) t) + (1+ (match-beginning 0)) + (point-at-eol))) + (tag (make-marker)) + (fill-column (- fill-column 4))) ; make room + (unwind-protect + (progn + (move-marker tag end) + (fill-paragraph nil) + (goto-char beg) + (while (not (js2-same-line tag)) + (goto-char (point-at-eol)) + (insert squote) + (when (zerop (forward-line 1)) + (back-to-indentation) + (if (looking-at (concat squote "\\s-*$")) + (progn + (setq end (point-at-eol)) + (forward-line -1) + (delete-region (point-at-eol) end)) + (insert "+ " squote))))) + (move-marker tag nil)))) + +(defun js2-fill-paragraph (arg) + "Fill paragraph after point. Prefix ARG means justify as well. +Has special handling for filling in comments and strings." + (let* ((parse-status (save-excursion + (parse-partial-sexp (point-min) (point)))) + (quote-char (or (nth 3 parse-status) + (save-match-data + (if (looking-at "[\"\']") + (char-after)))))) + (cond + (quote-char + (js2-fill-string (or (nth 8 parse-status) + (point)) + quote-char) + t) ; or fill-paragraph does evil things afterwards + ((nth 4 parse-status) ; in block comment? + (js2-fill-comment parse-status arg)) + (t + (fill-paragraph arg))))) + +(defun js2-fill-comment (parse-status arg) + "Fill-paragraph in a block comment." + (let* ((beg (nth 8 parse-status)) + (end (save-excursion + (goto-char beg) + (re-search-forward "[^\\]\\*/" nil t))) + indent + end-marker) + (when end + (setq end-marker (make-marker)) + (move-marker end-marker end)) + (when (and end js2-mode-squeeze-spaces) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (while (re-search-forward "[ \t][ \t]+" nil t) + (replace-match " "))))) + ;; `c-fill-paragraph' doesn't indent the continuation stars properly + ;; if the comment isn't left-justified. They align to the first star + ;; on the first continuation line after the comment-open, so we make + ;; sure the first continuation line has the proper indentation. + (save-excursion + (goto-char beg) + (setq indent (1+ (current-column))) + (goto-char (point-at-eol)) + (skip-chars-forward " \t\r\n") + (indent-line-to indent) + + ;; Invoke `c-fill-paragraph' from the first continuation line, + ;; since it provides better results. Otherwise if you're on the + ;; last line, it doesn't prefix with stars the way you'd expect. + ;; TODO: write our own fill function that works in Emacs 21 + (c-fill-paragraph arg)) + + ;; last line is typically indented wrong, so fix it + (when end-marker + (save-excursion + (goto-char end-marker) + (js2-indent-line))))) + +(defun js2-beginning-of-line () + "Toggles point between bol and first non-whitespace char in line. +Also moves past comment delimiters when inside comments." + (interactive) + (let (node beg) + (cond + ((bolp) + (back-to-indentation)) + ((looking-at "//") + (skip-chars-forward "/ \t")) + ((and (eq (char-after) ?*) + (setq node (js2-comment-at-point)) + (memq (js2-comment-node-format node) '(jsdoc block)) + (save-excursion + (skip-chars-backward " \t") + (bolp))) + (skip-chars-forward "\* \t")) + (t + (goto-char (point-at-bol)))))) + +(defun js2-end-of-line () + "Toggles point between eol and last non-whitespace char in line." + (interactive) + (if (eolp) + (skip-chars-backward " \t") + (goto-char (point-at-eol)))) + +(defun js2-enter-mirror-mode() + "Turns on mirror mode, where quotes, brackets etc are mirrored automatically + on insertion." + (interactive) + (define-key js2-mode-map (read-kbd-macro "{") 'js2-mode-match-curly) + (define-key js2-mode-map (read-kbd-macro "}") 'js2-mode-magic-close-paren) + (define-key js2-mode-map (read-kbd-macro "\"") 'js2-mode-match-double-quote) + (define-key js2-mode-map (read-kbd-macro "'") 'js2-mode-match-single-quote) + (define-key js2-mode-map (read-kbd-macro "(") 'js2-mode-match-paren) + (define-key js2-mode-map (read-kbd-macro ")") 'js2-mode-magic-close-paren) + (define-key js2-mode-map (read-kbd-macro "[") 'js2-mode-match-bracket) + (define-key js2-mode-map (read-kbd-macro "]") 'js2-mode-magic-close-paren)) + +(defun js2-leave-mirror-mode() + "Turns off mirror mode." + (interactive) + (dolist (key '("{" "\"" "'" "(" ")" "[" "]")) + (define-key js2-mode-map (read-kbd-macro key) 'self-insert-command))) + +(defsubst js2-mode-inside-string () + "Return non-nil if inside a string. +Actually returns the quote character that begins the string." + (let ((parse-state (save-excursion + (parse-partial-sexp (point-min) (point))))) + (nth 3 parse-state))) + +(defsubst js2-mode-inside-comment-or-string () + "Return non-nil if inside a comment or string." + (or + (let ((comment-start + (save-excursion + (goto-char (point-at-bol)) + (if (re-search-forward "//" (point-at-eol) t) + (match-beginning 0))))) + (and comment-start + (<= comment-start (point)))) + (let ((parse-state (save-excursion + (parse-partial-sexp (point-min) (point))))) + (or (nth 3 parse-state) + (nth 4 parse-state))))) + +(defun js2-mode-match-curly (arg) + "Insert matching curly-brace." + (interactive "p") + (insert "{") + (if current-prefix-arg + (save-excursion + (insert "}")) + (unless (or (not (looking-at "\\s-*$")) + (js2-mode-inside-comment-or-string)) + (undo-boundary) + + ;; absolutely mystifying bug: when inserting the next "\n", + ;; the buffer-undo-list is given two new entries: the inserted range, + ;; and the incorrect position of the point. It's recorded incorrectly + ;; as being before the opening "{", not after it. But it's recorded + ;; as the correct value if you're debugging `js2-mode-match-curly' + ;; in edebug. I have no idea why it's doing this, but incrementing + ;; the inserted position fixes the problem, so that the undo takes us + ;; back to just after the user-inserted "{". + (insert "\n") + (ignore-errors + (incf (cadr buffer-undo-list))) + + (js2-indent-line) + (save-excursion + (insert "\n}") + (let ((js2-bounce-indent-flag (js2-code-at-bol-p))) + (js2-indent-line)))))) + +(defun js2-mode-match-bracket () + "Insert matching bracket." + (interactive) + (insert "[") + (unless (or (not (looking-at "\\s-*$")) + (js2-mode-inside-comment-or-string)) + (save-excursion + (insert "]")) + (when js2-auto-indent-flag + (let ((js2-bounce-indent-flag (js2-code-at-bol-p))) + (js2-indent-line))))) + +(defun js2-mode-match-paren () + "Insert matching paren unless already inserted." + (interactive) + (insert "(") + (unless (or (not (looking-at "\\s-*$")) + (js2-mode-inside-comment-or-string)) + (save-excursion + (insert ")")) + (when js2-auto-indent-flag + (let ((js2-bounce-indent-flag (js2-code-at-bol-p))) + (js2-indent-line))))) + +(defsubst js2-match-quote (quote-string) + (let ((start-quote (js2-mode-inside-string))) + (cond + ;; inside a comment - don't do quote-matching, since we can't + ;; reliably figure out if we're in a string inside the comment + ((js2-comment-at-point) + (insert quote-string)) + ((not start-quote) + ;; not in string => insert matched quotes + (insert quote-string) + ;; exception: if we're just before a word, don't double it. + (unless (looking-at "[^ \t\r\n]") + (save-excursion + (insert quote-string)))) + ((looking-at quote-string) + (if (looking-back "[^\\]\\\\") + (insert quote-string) + (forward-char 1))) + ((and js2-mode-escape-quotes + (save-excursion + (save-match-data + (re-search-forward quote-string (point-at-eol) t)))) + ;; inside terminated string, escape quote (unless already escaped) + (insert (if (looking-back "[^\\]\\\\") + quote-string + (concat "\\" quote-string)))) + (t + (insert quote-string))))) ; else terminate the string + +(defun js2-mode-match-single-quote () + "Insert matching single-quote." + (interactive) + (let ((parse-status (parse-partial-sexp (point-min) (point)))) + ;; don't match inside comments, since apostrophe is more common + (if (nth 4 parse-status) + (insert "'") + (js2-match-quote "'")))) + +(defun js2-mode-match-double-quote () + "Insert matching double-quote." + (interactive) + (js2-match-quote "\"")) + +(defun js2-mode-magic-close-paren () + "Skip over close-paren rather than inserting, where appropriate. +Uses some heuristics to try to figure out the right thing to do." + (interactive) + (let* ((parse-status (parse-partial-sexp (point-min) (point))) + (open-pos (nth 1 parse-status)) + (close last-input-char) + (open (cond + ((eq close 41) ; close-paren + 40) ; open-paren + ((eq close 93) ; close-bracket + 91) ; open-bracket + ((eq close ?}) + ?{) + (t nil)))) + (if (and (looking-at (string close)) + (eq open (char-after open-pos)) + (js2-same-line open-pos)) + (forward-char 1) + (insert (string close))) + (blink-matching-open))) + +(defun js2-mode-wait-for-parse (callback) + "Invoke CALLBACK when parsing is finished. +If parsing is already finished, calls CALLBACK immediately." + (if (not js2-mode-buffer-dirty-p) + (funcall callback) + (push callback js2-mode-pending-parse-callbacks) + (add-hook 'js2-parse-finished-hook #'js2-mode-parse-finished))) + +(defun js2-mode-parse-finished () + "Invoke callbacks in `js2-mode-pending-parse-callbacks'." + ;; We can't let errors propagate up, since it prevents the + ;; `js2-parse' method from completing normally and returning + ;; the ast, which makes things mysteriously not work right. + (unwind-protect + (dolist (cb js2-mode-pending-parse-callbacks) + (condition-case err + (funcall cb) + (error (message "%s" err)))) + (setq js2-mode-pending-parse-callbacks nil))) + +(defun js2-mode-flag-region (from to flag) + "Hide or show text from FROM to TO, according to FLAG. +If FLAG is nil then text is shown, while if FLAG is t the text is hidden. +Returns the created overlay if FLAG is non-nil." + (remove-overlays from to 'invisible 'js2-outline) + (when flag + (let ((o (make-overlay from to))) + (overlay-put o 'invisible 'js2-outline) + (overlay-put o 'isearch-open-invisible + 'js2-isearch-open-invisible) + o))) + +;; Function to be set as an outline-isearch-open-invisible' property +;; to the overlay that makes the outline invisible (see +;; `js2-mode-flag-region'). +(defun js2-isearch-open-invisible (overlay) + ;; We rely on the fact that isearch places point on the matched text. + (js2-mode-show-element)) + +(defun js2-mode-invisible-overlay-bounds (&optional pos) + "Return cons cell of bounds of folding overlay at POS. +Returns nil if not found." + (let ((overlays (overlays-at (or pos (point)))) + o) + (while (and overlays + (not o)) + (if (overlay-get (car overlays) 'invisible) + (setq o (car overlays)) + (setq overlays (cdr overlays)))) + (if o + (cons (overlay-start o) (overlay-end o))))) + +(defun js2-mode-function-at-point (&optional pos) + "Return the innermost function node enclosing current point. +Returns nil if point is not in a function." + (let ((node (js2-node-at-point pos))) + (while (and node (not (js2-function-node-p node))) + (setq node (js2-node-parent node))) + (if (js2-function-node-p node) + node))) + +(defun js2-mode-toggle-element () + "Hide or show the foldable element at the point." + (interactive) + (let (comment fn pos) + (save-excursion + (save-match-data + (cond + ;; /* ... */ comment? + ((js2-block-comment-p (setq comment (js2-comment-at-point))) + (if (js2-mode-invisible-overlay-bounds + (setq pos (+ 3 (js2-node-abs-pos comment)))) + (progn + (goto-char pos) + (js2-mode-show-element)) + (js2-mode-hide-element))) + + ;; //-comment? + ((save-excursion + (back-to-indentation) + (looking-at js2-mode-//-comment-re)) + (js2-mode-toggle-//-comment)) + + ;; function? + ((setq fn (js2-mode-function-at-point)) + (setq pos (and (js2-function-node-body fn) + (js2-node-abs-pos (js2-function-node-body fn)))) + (goto-char (1+ pos)) + (if (js2-mode-invisible-overlay-bounds) + (js2-mode-show-element) + (js2-mode-hide-element))) + (t + (message "Nothing at point to hide or show"))))))) + +(defun js2-mode-hide-element () + "Fold/hide contents of a block, showing ellipses. +Show the hidden text with \\[js2-mode-show-element]." + (interactive) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse #'js2-mode-hide-element)) + (let (node body beg end) + (cond + ((js2-mode-invisible-overlay-bounds) + (message "already hidden")) + (t + (setq node (js2-node-at-point)) + (cond + ((js2-block-comment-p node) + (js2-mode-hide-comment node)) + (t + (while (and node (not (js2-function-node-p node))) + (setq node (js2-node-parent node))) + (if (and node + (setq body (js2-function-node-body node))) + (progn + (setq beg (js2-node-abs-pos body) + end (+ beg (js2-node-len body))) + (js2-mode-flag-region (1+ beg) (1- end) 'hide)) + (message "No collapsable element found at point")))))))) + +(defun js2-mode-show-element () + "Show the hidden element at current point." + (interactive) + (let ((bounds (js2-mode-invisible-overlay-bounds))) + (if bounds + (js2-mode-flag-region (car bounds) (cdr bounds) nil) + (message "Nothing to un-hide")))) + +(defun js2-mode-show-all () + "Show all of the text in the buffer." + (interactive) + (js2-mode-flag-region (point-min) (point-max) nil)) + +(defun js2-mode-toggle-hide-functions () + (interactive) + (if js2-mode-functions-hidden + (js2-mode-show-functions) + (js2-mode-hide-functions))) + +(defun js2-mode-hide-functions () + "Hides all non-nested function bodies in the buffer. +Use \\[js2-mode-show-all] to reveal them, or \\[js2-mode-show-element] +to open an individual entry." + (interactive) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse #'js2-mode-hide-functions)) + (if (null js2-mode-ast) + (message "Oops - parsing failed") + (setq js2-mode-functions-hidden t) + (js2-visit-ast js2-mode-ast #'js2-mode-function-hider))) + +(defun js2-mode-function-hider (n endp) + (when (not endp) + (let ((tt (js2-node-type n)) + body beg end) + (cond + ((and (= tt js2-FUNCTION) + (setq body (js2-function-node-body n))) + (setq beg (js2-node-abs-pos body) + end (+ beg (js2-node-len body))) + (js2-mode-flag-region (1+ beg) (1- end) 'hide) + nil) ; don't process children of function + (t + t))))) ; keep processing other AST nodes + +(defun js2-mode-show-functions () + "Un-hide any folded function bodies in the buffer." + (interactive) + (setq js2-mode-functions-hidden nil) + (save-excursion + (goto-char (point-min)) + (while (/= (goto-char (next-overlay-change (point))) + (point-max)) + (dolist (o (overlays-at (point))) + (when (and (overlay-get o 'invisible) + (not (overlay-get o 'comment))) + (js2-mode-flag-region (overlay-start o) (overlay-end o) nil)))))) + +(defun js2-mode-hide-comment (n) + (let* ((head (if (eq (js2-comment-node-format n) 'jsdoc) + 3 ; /** + 2)) ; /* + (beg (+ (js2-node-abs-pos n) head)) + (end (- (+ beg (js2-node-len n)) head 2)) + (o (js2-mode-flag-region beg end 'hide))) + (overlay-put o 'comment t))) + +(defun js2-mode-toggle-hide-comments () + "Folds all block comments in the buffer. +Use \\[js2-mode-show-all] to reveal them, or \\[js2-mode-show-element] +to open an individual entry." + (interactive) + (if js2-mode-comments-hidden + (js2-mode-show-comments) + (js2-mode-hide-comments))) + +(defun js2-mode-hide-comments () + (interactive) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse #'js2-mode-hide-comments)) + (if (null js2-mode-ast) + (message "Oops - parsing failed") + (setq js2-mode-comments-hidden t) + (dolist (n (js2-ast-root-comments js2-mode-ast)) + (let ((format (js2-comment-node-format n))) + (when (js2-block-comment-p n) + (js2-mode-hide-comment n)))) + (js2-mode-hide-//-comments))) + +(defsubst js2-mode-extend-//-comment (direction) + "Find start or end of a block of similar //-comment lines. +DIRECTION is -1 to look back, 1 to look forward. +INDENT is the indentation level to match. +Returns the end-of-line position of the furthest adjacent +//-comment line with the same indentation as the current line. +If there is no such matching line, returns current end of line." + (let ((pos (point-at-eol)) + (indent (current-indentation))) + (save-excursion + (save-match-data + (while (and (zerop (forward-line direction)) + (looking-at js2-mode-//-comment-re) + (eq indent (length (match-string 1)))) + (setq pos (point-at-eol))) + pos)))) + +(defun js2-mode-hide-//-comments () + "Fold adjacent 1-line comments, showing only snippet of first one." + (let (beg end) + (save-excursion + (save-match-data + (goto-char (point-min)) + (while (re-search-forward js2-mode-//-comment-re nil t) + (setq beg (point) + end (js2-mode-extend-//-comment 1)) + (unless (eq beg end) + (overlay-put (js2-mode-flag-region beg end 'hide) + 'comment t)) + (goto-char end) + (forward-char 1)))))) + +(defun js2-mode-toggle-//-comment () + "Fold or un-fold any multi-line //-comment at point. +Caller should have determined that this line starts with a //-comment." + (let* ((beg (point-at-eol)) + (end beg)) + (save-excursion + (goto-char end) + (if (js2-mode-invisible-overlay-bounds) + (js2-mode-show-element) + ;; else hide the comment + (setq beg (js2-mode-extend-//-comment -1) + end (js2-mode-extend-//-comment 1)) + (unless (eq beg end) + (overlay-put (js2-mode-flag-region beg end 'hide) + 'comment t)))))) + +(defun js2-mode-show-comments () + "Un-hide any hidden comments, leaving other hidden elements alone." + (interactive) + (setq js2-mode-comments-hidden nil) + (save-excursion + (goto-char (point-min)) + (while (/= (goto-char (next-overlay-change (point))) + (point-max)) + (dolist (o (overlays-at (point))) + (when (overlay-get o 'comment) + (js2-mode-flag-region (overlay-start o) (overlay-end o) nil)))))) + +(defun js2-mode-display-warnings-and-errors () + "Turn on display of warnings and errors." + (interactive) + (setq js2-mode-show-parse-errors t + js2-mode-show-strict-warnings t) + (js2-reparse 'force)) + +(defun js2-mode-hide-warnings-and-errors () + "Turn off display of warnings and errors." + (interactive) + (setq js2-mode-show-parse-errors nil + js2-mode-show-strict-warnings nil) + (js2-reparse 'force)) + +(defun js2-mode-toggle-warnings-and-errors () + "Toggle the display of warnings and errors. +Some users don't like having warnings/errors reported while they type." + (interactive) + (setq js2-mode-show-parse-errors (not js2-mode-show-parse-errors) + js2-mode-show-strict-warnings (not js2-mode-show-strict-warnings)) + (if (interactive-p) + (message "warnings and errors %s" + (if js2-mode-show-parse-errors + "enabled" + "disabled"))) + (js2-reparse 'force)) + +(defun js2-mode-customize () + (interactive) + (customize-group 'js2-mode)) + +(defun js2-mode-forward-sexp (&optional arg) + "Move forward across one statement or balanced expression. +With ARG, do it that many times. Negative arg -N means +move backward across N balanced expressions." + (interactive "p") + (setq arg (or arg 1)) + (if js2-mode-buffer-dirty-p + (js2-mode-wait-for-parse #'js2-mode-forward-sexp)) + (let (node end (start (point))) + (cond + ;; backward-sexp + ;; could probably make this "better" for some cases: + ;; - if in statement block (e.g. function body), go to parent + ;; - infix exprs like (foo in bar) - maybe go to beginning + ;; of infix expr if in the right-side expression? + ((and arg (minusp arg)) + (dotimes (i (- arg)) + (js2-backward-sws) + (forward-char -1) ; enter the node we backed up to + (setq node (js2-node-at-point (point) t)) + (goto-char (if node + (js2-node-abs-pos node) + (point-min))))) + (t + ;; forward-sexp + (js2-forward-sws) + (dotimes (i arg) + (js2-forward-sws) + (setq node (js2-node-at-point (point) t) + end (if node (+ (js2-node-abs-pos node) + (js2-node-len node)))) + (goto-char (or end (point-max)))))))) + +(defun js2-next-error (&optional arg reset) + "Move to next parse error. +Typically invoked via \\[next-error]. +ARG is the number of errors, forward or backward, to move. +RESET means start over from the beginning." + (interactive "p") + (if (or (null js2-mode-ast) + (and (null (js2-ast-root-errors js2-mode-ast)) + (null (js2-ast-root-warnings js2-mode-ast)))) + (message "No errors") + (when reset + (goto-char (point-min))) + (let* ((errs (copy-sequence + (append (js2-ast-root-errors js2-mode-ast) + (js2-ast-root-warnings js2-mode-ast)))) + (continue t) + (start (point)) + (count (or arg 1)) + (backward (minusp count)) + (sorter (if backward '> '<)) + (stopper (if backward '< '>)) + (count (abs count)) + all-errs + err) + ;; sort by start position + (setq errs (sort errs (lambda (e1 e2) + (funcall sorter (second e1) (second e2)))) + all-errs errs) + ;; find nth error with pos > start + (while (and errs continue) + (when (funcall stopper (cadar errs) start) + (setq err (car errs)) + (if (zerop (decf count)) + (setq continue nil))) + (setq errs (cdr errs))) + (if err + (goto-char (second err)) + ;; wrap around to first error + (goto-char (second (car all-errs))) + ;; if we were already on it, echo msg again + (if (= (point) start) + (js2-echo-error (point) (point))))))) + +(defun js2-mouse-3 () + "Make right-click move the point to the click location. +This makes right-click context menu operations a bit more intuitive. +The point will not move if the region is active, however, to avoid +destroying the region selection." + (interactive) + (when (and js2-move-point-on-right-click + (not mark-active)) + (let ((e last-input-event)) + (ignore-errors + (goto-char (cadadr e)))))) + +(defun js2-mode-create-imenu-index () + "Return an alist for `imenu--index-alist'." + ;; This is built up in `js2-parse-record-imenu' during parsing. + (when js2-mode-ast + ;; if we have an ast but no recorder, they're requesting a rescan + (unless js2-imenu-recorder + (js2-reparse 'force)) + (prog1 + (js2-build-imenu-index) + (setq js2-imenu-recorder nil + js2-imenu-function-map nil)))) + +(defun js2-mode-find-tag () + "Replacement for `find-tag-default'. +`find-tag-default' returns a ridiculous answer inside comments." + (let (beg end) + (js2-with-underscore-as-word-syntax + (save-excursion + (if (and (not (looking-at "[A-Za-z0-9_$]")) + (looking-back "[A-Za-z0-9_$]")) + (setq beg (progn (forward-word -1) (point)) + end (progn (forward-word 1) (point))) + (setq beg (progn (forward-word 1) (point)) + end (progn (forward-word -1) (point)))) + (replace-regexp-in-string + "[\"']" "" + (buffer-substring-no-properties beg end)))))) + +(defun js2-mode-forward-sibling () + "Move to the end of the sibling following point in parent. +Returns non-nil if successful, or nil if there was no following sibling." + (let* ((node (js2-node-at-point)) + (parent (js2-mode-find-enclosing-fn node)) + sib) + (when (setq sib (js2-node-find-child-after (point) parent)) + (goto-char (+ (js2-node-abs-pos sib) + (js2-node-len sib)))))) + +(defun js2-mode-backward-sibling () + "Move to the beginning of the sibling node preceding point in parent. +Parent is defined as the enclosing script or function." + (let* ((node (js2-node-at-point)) + (parent (js2-mode-find-enclosing-fn node)) + sib) + (when (setq sib (js2-node-find-child-before (point) parent)) + (goto-char (js2-node-abs-pos sib))))) + +(defun js2-beginning-of-defun () + "Go to line on which current function starts, and return non-nil. +If we're not in a function, go to beginning of previous script-level element." + (interactive) + (let ((parent (js2-node-parent-script-or-fn (js2-node-at-point))) + pos sib) + (cond + ((and (js2-function-node-p parent) + (not (eq (point) (setq pos (js2-node-abs-pos parent))))) + (goto-char pos)) + (t + (js2-mode-backward-sibling))))) + +(defun js2-end-of-defun () + "Go to the char after the last position of the current function. +If we're not in a function, skips over the next script-level element." + (interactive) + (let ((parent (js2-node-parent-script-or-fn (js2-node-at-point)))) + (if (not (js2-function-node-p parent)) + ;; punt: skip over next script-level element beyond point + (js2-mode-forward-sibling) + (goto-char (+ 1 (+ (js2-node-abs-pos parent) + (js2-node-len parent))))))) + +(defun js2-mark-defun (&optional allow-extend) + "Put mark at end of this function, point at beginning. +The function marked is the one that contains point. + +Interactively, if this command is repeated, +or (in Transient Mark mode) if the mark is active, +it marks the next defun after the ones already marked." + (interactive "p") + (let (extended) + (when (and allow-extend + (or (and (eq last-command this-command) (mark t)) + (and transient-mark-mode mark-active))) + (let ((sib (save-excursion + (goto-char (mark)) + (if (js2-mode-forward-sibling) + (point)))) + node) + (if sib + (progn + (set-mark sib) + (setq extended t)) + ;; no more siblings - try extending to enclosing node + (goto-char (mark t))))) + (when (not extended) + (let ((node (js2-node-at-point (point) t)) ; skip comments + ast fn stmt parent beg end) + (when (js2-ast-root-p node) + (setq ast node + node (or (js2-node-find-child-after (point) node) + (js2-node-find-child-before (point) node)))) + ;; only mark whole buffer if we can't find any children + (if (null node) + (setq node ast)) + (if (js2-function-node-p node) + (setq parent node) + (setq fn (js2-mode-find-enclosing-fn node) + stmt (if (or (null fn) + (js2-ast-root-p fn)) + (js2-mode-find-first-stmt node)) + parent (or stmt fn))) + (setq beg (js2-node-abs-pos parent) + end (+ beg (js2-node-len parent))) + (push-mark beg) + (goto-char end) + (exchange-point-and-mark))))) + +(defun js2-narrow-to-defun () + "Narrow to the function enclosing point." + (interactive) + (let* ((node (js2-node-at-point (point) t)) ; skip comments + (fn (if (js2-script-node-p node) + node + (js2-mode-find-enclosing-fn node))) + (beg (js2-node-abs-pos fn))) + (unless (js2-ast-root-p fn) + (narrow-to-region beg (+ beg (js2-node-len fn)))))) + +(defalias 'js2r 'js2-mode-reset) + +(provide 'js2-mode) + +;;; js2-mode.el ends here + + +;;; js2.el ends here
new file mode 100644 index 0000000000000000000000000000000000000000..80fbe1d8a673c75d3144a03b542080231298bf31 GIT binary patch literal 1463351 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%0Ds^W^uw1&@ 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	T@t?~YsYsXK*S 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	tmIr5+J?50j>@n&T|`HhhkDW&LvYf9BXP-| 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 C^JZHB
--- a/.emacs +++ b/.emacs @@ -56,6 +56,9 @@ point." (add-hook 'emacs-lisp-mode-hook 'af-tab-fix) (add-hook 'clojure-mode-hook 'af-tab-fix) +(autoload 'js2-mode "js2" nil t) +(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) + (defun af-python-mode-hook () ; highlight tabs in Python (make-variable-buffer-local 'font-lock-mode-hook)