538 lines
20 KiB
EmacsLisp
538 lines
20 KiB
EmacsLisp
![]() |
;;; js2r-functions.el --- Function manipulation functions for js2-refactor -*- lexical-binding: t; -*-
|
||
|
|
||
|
;; Copyright (C) 2012-2014 Magnar Sveen
|
||
|
;; Copyright (C) 2015-2016 Magnar Sveen and Nicolas Petton
|
||
|
|
||
|
;; Author: Magnar Sveen <magnars@gmail.com>,
|
||
|
;; Nicolas Petton <nicolas@petton.fr>
|
||
|
;; Keywords: conveniences
|
||
|
|
||
|
;; 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 3 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, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
;;; Code:
|
||
|
|
||
|
(require 'dash)
|
||
|
(require 'yasnippet)
|
||
|
|
||
|
(require 'js2r-helpers)
|
||
|
|
||
|
(defun js2r-localize-parameter ()
|
||
|
"Turn parameter into local var in local function."
|
||
|
(interactive)
|
||
|
(js2r--guard)
|
||
|
(js2r--wait-for-parse
|
||
|
(if (js2-name-node-p (js2-node-at-point))
|
||
|
(js2r--localize-parameter-pull)
|
||
|
(js2r--localize-parameter-push))))
|
||
|
|
||
|
(defun js2r--localize-parameter-push ()
|
||
|
(let* ((node (js2-node-at-point))
|
||
|
(arg-node (or (js2r--closest-node-where 'js2r--parent-is-call-node node)
|
||
|
(error "Place cursor on argument to localize")))
|
||
|
(call-node (js2-node-parent arg-node))
|
||
|
(value (js2-node-string arg-node))
|
||
|
(target (js2-call-node-target call-node))
|
||
|
(fn (if (js2-name-node-p target)
|
||
|
(js2r--local-fn-from-name-node target)
|
||
|
(error "Can only localize parameter for local functions")))
|
||
|
(usages (js2r--function-usages fn))
|
||
|
(index (car (--keep (when (eq arg-node it) it-index)
|
||
|
(js2-call-node-args call-node))))
|
||
|
(name (js2-name-node-name (nth index (js2-function-node-params fn)))))
|
||
|
(js2r--localize-parameter fn usages index name value)))
|
||
|
|
||
|
(defun js2r--localize-parameter-pull ()
|
||
|
(let* ((name-node (js2-node-at-point))
|
||
|
(name (if (js2-name-node-p name-node)
|
||
|
(js2-name-node-name name-node)
|
||
|
(error "Place cursor on parameter to localize")))
|
||
|
(fn (or (js2r--closest-node-where #'js2r--is-local-function name-node)
|
||
|
(error "Can only localize parameter in local functions")))
|
||
|
(index (or (js2r--param-index-for name fn)
|
||
|
(error "%S isn't a parameter to this function" name)))
|
||
|
(usages (js2r--function-usages fn))
|
||
|
(examples (-distinct (--map (js2r--argument index it) usages)))
|
||
|
(value (js2r--choose-one "Value: " examples)))
|
||
|
(js2r--localize-parameter fn usages index name value)))
|
||
|
|
||
|
(defun js2r--localize-parameter (fn usages index name value)
|
||
|
(save-excursion
|
||
|
(js2r--goto-fn-body-beg fn)
|
||
|
(save-excursion
|
||
|
(--each usages (js2r--remove-argument-at-index index it)))
|
||
|
(newline-and-indent)
|
||
|
(insert "var " name " = " value ";")
|
||
|
(js2r--remove-parameter-at-index index fn)))
|
||
|
|
||
|
(defun js2r--parent-is-call-node (node)
|
||
|
(js2-call-node-p (js2-node-parent node)))
|
||
|
|
||
|
(defun js2r--local-fn-from-name-node (name-node)
|
||
|
(->> name-node
|
||
|
(js2r--local-usages-of-name-node)
|
||
|
(-map #'js2-node-parent)
|
||
|
(-first #'js2-function-node-p)))
|
||
|
|
||
|
(defun js2r--param-index-for (name fn)
|
||
|
(car (--keep (when (equal name (js2-name-node-name it)) it-index)
|
||
|
(js2-function-node-params fn))))
|
||
|
|
||
|
(defun js2r--argument (index call-node)
|
||
|
(js2-node-string (nth index (js2-call-node-args call-node))))
|
||
|
|
||
|
(defun js2r--remove-parameter-at-index (index fn)
|
||
|
(js2r--delete-node-in-params (nth index (js2-function-node-params fn))))
|
||
|
|
||
|
(defun js2r--remove-argument-at-index (index call-node)
|
||
|
(js2r--delete-node-in-params (nth index (js2-call-node-args call-node))))
|
||
|
|
||
|
(defun js2r--delete-node-in-params (node)
|
||
|
(goto-char (js2-node-abs-pos node))
|
||
|
(delete-char (js2-node-len node))
|
||
|
(if (and (looking-back "(")
|
||
|
(looking-at ", "))
|
||
|
(delete-char 2)
|
||
|
(when (looking-back ", ")
|
||
|
(delete-char -2))))
|
||
|
|
||
|
(defun js2r--choose-one (prompt options)
|
||
|
(when options
|
||
|
(if (cdr options)
|
||
|
(completing-read prompt options)
|
||
|
(car options))))
|
||
|
|
||
|
(defun js2r-introduce-parameter ()
|
||
|
"Introduce a parameter in a local function."
|
||
|
(interactive)
|
||
|
(js2r--guard)
|
||
|
(js2r--wait-for-parse
|
||
|
(if (use-region-p)
|
||
|
(js2r--introduce-parameter-between (region-beginning) (region-end))
|
||
|
(let ((node (js2r--closest-extractable-node)))
|
||
|
(js2r--introduce-parameter-between (js2-node-abs-pos node)
|
||
|
(js2-node-abs-end node))))))
|
||
|
|
||
|
(defun js2r--introduce-parameter-between (beg end)
|
||
|
(unless (js2r--single-complete-expression-between-p beg end)
|
||
|
(error "Can only introduce single, complete expressions as parameter"))
|
||
|
|
||
|
(let ((fn (js2r--closest-node-where #'js2r--is-local-function (js2-node-at-point))))
|
||
|
(unless fn
|
||
|
(error "Can only introduce parameter in local functions"))
|
||
|
(save-excursion
|
||
|
(let ((name (read-string "Parameter name: "))
|
||
|
(val (buffer-substring beg end))
|
||
|
(usages (js2r--function-usages fn)))
|
||
|
(goto-char beg)
|
||
|
(save-excursion
|
||
|
(-each usages (-partial #'js2r--add-parameter val)))
|
||
|
(delete-char (- end beg))
|
||
|
(insert name)
|
||
|
(js2r--add-parameter name fn)
|
||
|
(query-replace val name nil (js2-node-abs-pos fn) (js2r--fn-body-end fn))))))
|
||
|
|
||
|
(defun js2r--function-usages (fn)
|
||
|
(-map #'js2-node-parent (js2r--function-usages-name-nodes fn)))
|
||
|
|
||
|
(defun js2r--function-usages-name-nodes (fn)
|
||
|
(let ((name-node (or (js2-function-node-name fn)
|
||
|
(js2-var-init-node-target (js2-node-parent fn)))))
|
||
|
(remove name-node (js2r--local-usages-of-name-node name-node))))
|
||
|
|
||
|
(defun js2r--add-parameter (name node)
|
||
|
(save-excursion
|
||
|
(js2r--goto-closing-paren node)
|
||
|
(unless (looking-back "(")
|
||
|
(insert ", "))
|
||
|
(insert name)))
|
||
|
|
||
|
(defun js2r--goto-closing-paren (node)
|
||
|
(goto-char (js2-node-abs-pos node))
|
||
|
(search-forward "(")
|
||
|
(forward-char -1)
|
||
|
(forward-list)
|
||
|
(forward-char -1))
|
||
|
|
||
|
(defun js2r--goto-fn-body-beg (fn)
|
||
|
(goto-char (js2-node-abs-pos fn))
|
||
|
(search-forward "{"))
|
||
|
|
||
|
(defun js2r--fn-body-end (fn)
|
||
|
(save-excursion
|
||
|
(js2r--goto-fn-body-beg fn)
|
||
|
(forward-char -1)
|
||
|
(forward-list)
|
||
|
(point)))
|
||
|
|
||
|
(defun js2r--is-local-function (node)
|
||
|
(or (js2r--is-var-function-expression node)
|
||
|
(js2r--is-function-declaration node)))
|
||
|
|
||
|
(defun js2r--is-method (node)
|
||
|
(and (js2-function-node-p node)
|
||
|
(js2-object-prop-node-p (js2-node-parent node))))
|
||
|
|
||
|
(defun js2r--is-var-function-expression (node)
|
||
|
(and (js2-function-node-p node)
|
||
|
(js2-var-init-node-p (js2-node-parent node))))
|
||
|
|
||
|
(defun js2r--is-assigned-function-expression (node)
|
||
|
(and (js2-function-node-p node)
|
||
|
(js2-assign-node-p (js2-node-parent node))))
|
||
|
|
||
|
(defun js2r--is-function-declaration (node)
|
||
|
(let ((parent (js2-node-parent node)))
|
||
|
(and (js2-function-node-p node)
|
||
|
(not (js2-assign-node-p parent))
|
||
|
(not (js2-var-init-node-p parent))
|
||
|
(not (js2-object-prop-node-p parent)))))
|
||
|
|
||
|
(defun js2r-arguments-to-object ()
|
||
|
"Change from a list of arguments to a parameter object."
|
||
|
(interactive)
|
||
|
(js2r--guard)
|
||
|
(js2r--wait-for-parse
|
||
|
(let ((node (js2-node-at-point)))
|
||
|
(unless (and (looking-at "(")
|
||
|
(or (js2-function-node-p node)
|
||
|
(js2-call-node-p node)
|
||
|
(js2-new-node-p node)))
|
||
|
(error "Place point right before the opening paren in the call or function"))
|
||
|
|
||
|
(-when-let* ((target (js2r--node-target node))
|
||
|
(fn (and (js2-name-node-p target)
|
||
|
(js2r--local-fn-from-name-node target))))
|
||
|
(setq node fn))
|
||
|
(if (js2-function-node-p node)
|
||
|
(js2r--arguments-to-object-for-function node)
|
||
|
(js2r--arguments-to-object-for-args-with-unknown-function (js2r--node-args node))))))
|
||
|
|
||
|
(defun js2r--arguments-to-object-for-function (function-node)
|
||
|
(let ((params (js2-function-node-params function-node)))
|
||
|
(when (null params)
|
||
|
(error "No params to convert"))
|
||
|
(save-excursion
|
||
|
(js2r--execute-changes
|
||
|
(-concat
|
||
|
;; change parameter list to just (params)
|
||
|
(list
|
||
|
(list :beg (+ (js2-node-abs-pos function-node) (js2-function-node-lp function-node))
|
||
|
:end (+ (js2-node-abs-pos function-node) (js2-function-node-rp function-node) 1)
|
||
|
:contents "(params)"))
|
||
|
|
||
|
;; add params. in front of function local param usages
|
||
|
(let* ((local-param-name-nodes (--mapcat (-> it
|
||
|
(js2-node-abs-pos)
|
||
|
(js2r--local-name-node-at-point)
|
||
|
(js2r--local-usages-of-name-node))
|
||
|
params))
|
||
|
(local-param-name-usages (--remove (js2-function-node-p (js2-node-parent it))
|
||
|
local-param-name-nodes))
|
||
|
(local-param-name-positions (-map #'js2-node-abs-pos local-param-name-usages)))
|
||
|
(--map
|
||
|
(list :beg it :end it :contents "params.")
|
||
|
local-param-name-positions))
|
||
|
|
||
|
;; update usages of function
|
||
|
(let ((names (-map #'js2-name-node-name params))
|
||
|
(usages (js2r--function-usages function-node)))
|
||
|
(--map
|
||
|
(js2r--changes/arguments-to-object it names)
|
||
|
usages)))))))
|
||
|
|
||
|
(defun js2r--changes/arguments-to-object (node names)
|
||
|
(let ((args (js2r--node-args node)))
|
||
|
(list :beg (+ (js2-node-abs-pos node) (js2r--node-lp node))
|
||
|
:end (+ (js2-node-abs-pos node) (js2r--node-rp node) 1)
|
||
|
:contents (js2r--create-object-with-arguments names args))))
|
||
|
|
||
|
(defun js2r--arguments-to-object-for-args-with-unknown-function (args)
|
||
|
(when (null args)
|
||
|
(error "No arguments to convert"))
|
||
|
(let ((names (--map-indexed
|
||
|
(format "${%d:%s}"
|
||
|
(1+ it-index)
|
||
|
(if (js2-name-node-p it)
|
||
|
(js2-name-node-name it)
|
||
|
"key"))
|
||
|
args)))
|
||
|
(yas-expand-snippet (js2r--create-object-with-arguments names args)
|
||
|
(point)
|
||
|
(save-excursion (forward-list) (point)))))
|
||
|
|
||
|
(defun js2r--create-object-with-arguments (names args)
|
||
|
(let (arg key result)
|
||
|
(--dotimes (length args)
|
||
|
(setq arg (nth it args))
|
||
|
(setq key (nth it names))
|
||
|
(setq result
|
||
|
(concat result
|
||
|
(format " %s: %s,\n"
|
||
|
key
|
||
|
(buffer-substring (js2-node-abs-pos arg)
|
||
|
(js2-node-abs-end arg))))))
|
||
|
(concat "({\n" (substring result 0 -2) "\n})")))
|
||
|
|
||
|
(defun js2r-extract-function (name)
|
||
|
"Extract a function from the closest statement expression from the point."
|
||
|
(interactive "sName of new function: ")
|
||
|
(js2r--extract-fn
|
||
|
name
|
||
|
(lambda ()
|
||
|
(unless (js2r--looking-at-function-declaration)
|
||
|
(goto-char (js2-node-abs-pos (js2r--closest #'js2-expr-stmt-node-p)))))
|
||
|
"%s(%s);"
|
||
|
"function %s(%s) {\n%s\n}\n\n"))
|
||
|
|
||
|
(defun js2r-extract-method (name)
|
||
|
"Extract a method from the closest statement expression from the point."
|
||
|
(interactive "sName of new method: ")
|
||
|
(let ((class-node (js2r--closest #'js2-class-node-p)))
|
||
|
(js2r--extract-fn
|
||
|
name
|
||
|
(unless class-node
|
||
|
(lambda ()
|
||
|
(goto-char (js2-node-abs-pos (js2r--closest #'js2-object-prop-node-p)))))
|
||
|
"this.%s(%s);"
|
||
|
(if class-node
|
||
|
"%s(%s) {\n%s\n}\n\n"
|
||
|
"%s: function (%s) {\n%s\n},\n\n"))))
|
||
|
|
||
|
(defun js2r--extract-fn (name goto-position call-template function-template)
|
||
|
(js2r--guard)
|
||
|
(js2r--wait-for-parse
|
||
|
(unless (use-region-p)
|
||
|
(error "Mark the expressions to extract first"))
|
||
|
(save-excursion
|
||
|
(let* ((parent (js2r--first-common-ancestor-in-region (region-beginning) (region-end)))
|
||
|
(block (js2r--closest-node-where #'js2-block-node-p parent))
|
||
|
(fn (js2r--closest-node-where #'js2-function-node-p block))
|
||
|
(exprs (js2r--marked-expressions-in-block block))
|
||
|
(vars (-mapcat #'js2r--name-node-decendants exprs))
|
||
|
(local (--filter (js2r--local-to-fn-p fn it) vars))
|
||
|
(names (-distinct (-map 'js2-name-node-name local)))
|
||
|
(declared-in-exprs (-map #'js2r--var-init-node-target-name (-mapcat #'js2r--var-init-node-decendants exprs)))
|
||
|
(outside-exprs (-difference (js2-block-node-kids block) exprs))
|
||
|
(outside-var-uses (-map #'js2-name-node-name (-mapcat #'js2r--name-node-decendants outside-exprs)))
|
||
|
(declared-in-but-used-outside (-intersection declared-in-exprs outside-var-uses))
|
||
|
(export-var (car declared-in-but-used-outside))
|
||
|
(params (-difference names declared-in-exprs))
|
||
|
(params-string (mapconcat #'identity (reverse params) ", "))
|
||
|
(first (car exprs))
|
||
|
(last (car (last exprs)))
|
||
|
(beg (js2-node-abs-pos (car exprs)))
|
||
|
(end (js2-node-abs-end last))
|
||
|
(contents (buffer-substring beg end)))
|
||
|
(goto-char beg)
|
||
|
(delete-region beg end)
|
||
|
(when (js2-return-node-p last)
|
||
|
(insert "return "))
|
||
|
(when export-var
|
||
|
(setq contents (concat contents "\nreturn " export-var ";"))
|
||
|
(insert "var " export-var " = "))
|
||
|
(insert (format call-template name params-string))
|
||
|
(goto-char (js2-node-abs-pos fn))
|
||
|
(when goto-position (funcall goto-position))
|
||
|
(let ((start (point)))
|
||
|
(insert (format function-template name params-string contents))
|
||
|
(indent-region start (1+ (point))))))))
|
||
|
|
||
|
(defun js2r--var-init-node-target-name (node)
|
||
|
(js2-name-node-name
|
||
|
(js2-var-init-node-target node)))
|
||
|
|
||
|
(defun js2r--function-around-region ()
|
||
|
(or
|
||
|
(js2r--closest-node-where #'js2-function-node-p
|
||
|
(js2r--first-common-ancestor-in-region
|
||
|
(region-beginning)
|
||
|
(region-end)))
|
||
|
(error "This only works when you mark stuff inside a function")))
|
||
|
|
||
|
(defun js2r--marked-expressions-in-block (fn)
|
||
|
(-select #'js2r--node-is-marked (js2-block-node-kids fn)))
|
||
|
|
||
|
(defun js2r--node-is-marked (node)
|
||
|
(and
|
||
|
(<= (region-beginning) (js2-node-abs-end node))
|
||
|
(>= (region-end) (js2-node-abs-pos node))))
|
||
|
|
||
|
(defun js2r--name-node-decendants (node)
|
||
|
(-select #'js2-name-node-p (js2r--decendants node)))
|
||
|
|
||
|
(defun js2r--var-init-node-decendants (node)
|
||
|
(-select #'js2-var-init-node-p (js2r--decendants node)))
|
||
|
|
||
|
(defun js2r--decendants (node)
|
||
|
(let (vars)
|
||
|
(js2-visit-ast node
|
||
|
(lambda (node end-p)
|
||
|
(unless end-p
|
||
|
(setq vars (cons node vars)))))
|
||
|
vars))
|
||
|
|
||
|
(defun js2r--local-to-fn-p (fn name-node)
|
||
|
(let* ((name (js2-name-node-name name-node))
|
||
|
(scope (js2-node-get-enclosing-scope name-node))
|
||
|
(scope (js2-get-defining-scope scope name)))
|
||
|
(eq fn scope)))
|
||
|
|
||
|
|
||
|
(defun js2r-toggle-arrow-function-and-expression ()
|
||
|
"Toggle between function expression to arrow function."
|
||
|
(interactive)
|
||
|
(save-excursion
|
||
|
(js2r--find-closest-function)
|
||
|
(cond ((js2r--arrow-function-p)
|
||
|
(js2r--transform-arrow-function-to-expression))
|
||
|
((and (js2r--function-start-p) (not (js2r--looking-at-function-declaration)))
|
||
|
(js2r--transform-function-expression-to-arrow))
|
||
|
(t (error "Can only toggle between function expressions and arrow function")))))
|
||
|
|
||
|
|
||
|
;; Toggle between function name() {} and var name = function ();
|
||
|
|
||
|
(defun js2r-toggle-function-expression-and-declaration ()
|
||
|
(interactive)
|
||
|
(save-excursion
|
||
|
(js2r--find-closest-function)
|
||
|
(cond
|
||
|
((js2r--looking-at-var-function-expression)
|
||
|
(when (js2r--arrow-function-p) (js2r--transform-arrow-function-to-expression))
|
||
|
(js2r--transform-function-expression-to-declaration))
|
||
|
((js2r--looking-at-function-declaration)
|
||
|
(js2r--transform-function-declaration-to-expression))
|
||
|
(t (error "Can only toggle between function declarations and free standing function expressions")))))
|
||
|
|
||
|
|
||
|
(defun js2r--arrow-function-p ()
|
||
|
(interactive)
|
||
|
(save-excursion
|
||
|
(ignore-errors
|
||
|
(js2r--find-closest-function)
|
||
|
(and (looking-at "(?[,[:space:][:word:]]*)?[[:space:]]*=>")
|
||
|
(not (js2r--point-inside-string-p))))))
|
||
|
|
||
|
(defun js2r--transform-arrow-function-to-expression ()
|
||
|
(when (js2r--arrow-function-p)
|
||
|
(let (has-parenthesis)
|
||
|
(save-excursion
|
||
|
(js2r--find-closest-function)
|
||
|
(let ((end (make-marker)))
|
||
|
(save-excursion
|
||
|
(search-forward "=>")
|
||
|
(set-marker end (js2-node-abs-end (js2-node-at-point))))
|
||
|
(setq has-parenthesis (looking-at "\\s-*("))
|
||
|
(insert "function ")
|
||
|
(if has-parenthesis
|
||
|
(forward-list)
|
||
|
(insert "("))
|
||
|
(search-forward "=>")
|
||
|
(delete-char -2)
|
||
|
(js2r--ensure-just-one-space)
|
||
|
(unless has-parenthesis
|
||
|
(backward-char 1)
|
||
|
(insert ")"))
|
||
|
(unless (looking-at "\\s-*{")
|
||
|
(js2r--ensure-just-one-space)
|
||
|
(insert "{ return ")
|
||
|
(js2r--ensure-just-one-space)
|
||
|
(goto-char (marker-position end))
|
||
|
(insert "; }")))))))
|
||
|
|
||
|
(defun js2r--transform-function-expression-to-arrow ()
|
||
|
(when (not (js2r--arrow-function-p))
|
||
|
(save-excursion
|
||
|
(js2r--find-closest-function)
|
||
|
(let ((pos (point))
|
||
|
(params
|
||
|
(js2-function-node-params (js2-node-at-point)))
|
||
|
parenthesis-start
|
||
|
parenthesis-end)
|
||
|
(when (js2r--looking-at-function-declaration)
|
||
|
(error "Can not convert function declarations to arrow function"))
|
||
|
(search-forward "(")
|
||
|
(backward-char 1)
|
||
|
(delete-region pos (point))
|
||
|
(setq parenthesis-start (point))
|
||
|
(forward-list)
|
||
|
(setq parenthesis-end (point))
|
||
|
(insert " => ")
|
||
|
(js2r--ensure-just-one-space)
|
||
|
(when (and (= 1 (length params))
|
||
|
(not js2r-always-insert-parens-around-arrow-function-params))
|
||
|
(goto-char parenthesis-end)
|
||
|
(backward-delete-char 1)
|
||
|
(goto-char parenthesis-start)
|
||
|
(delete-char 1))))))
|
||
|
|
||
|
|
||
|
(defun js2r--function-start-p()
|
||
|
(let* ((fn (js2r--closest #'js2-function-node-p)))
|
||
|
(and fn
|
||
|
(= (js2-node-abs-pos fn) (point)))))
|
||
|
|
||
|
(defun js2r--find-closest-function ()
|
||
|
(when (not (js2r--function-start-p))
|
||
|
(let* ((fn (js2r--closest #'js2-function-node-p)))
|
||
|
(goto-char (js2-node-abs-pos fn)))))
|
||
|
|
||
|
(defun js2r--looking-at-method ()
|
||
|
(and (js2r--function-start-p)
|
||
|
(looking-back ": ?")))
|
||
|
|
||
|
(defun js2r--looking-at-function-declaration ()
|
||
|
(and (js2r--function-start-p)
|
||
|
(looking-back "^ *")))
|
||
|
|
||
|
(defun js2r--looking-at-var-function-expression ()
|
||
|
(and (js2r--function-start-p)
|
||
|
(looking-back "^ *var[\s\n]*[a-z_$]+[\s\n]*=[\s\n]*")))
|
||
|
|
||
|
(defun js2r--transform-function-expression-to-declaration ()
|
||
|
(when (js2r--looking-at-var-function-expression)
|
||
|
(delete-char 9)
|
||
|
(forward-list)
|
||
|
(forward-list)
|
||
|
(delete-char 1)
|
||
|
(backward-list)
|
||
|
(backward-list)
|
||
|
(delete-backward-char 3)
|
||
|
(back-to-indentation)
|
||
|
(delete-char 4)
|
||
|
(insert "function ")))
|
||
|
|
||
|
(defun js2r--transform-function-declaration-to-expression ()
|
||
|
(when (js2r--looking-at-function-declaration)
|
||
|
(delete-char 9)
|
||
|
(insert "var ")
|
||
|
(search-forward "(")
|
||
|
(backward-char 1)
|
||
|
(insert " = function ")
|
||
|
(forward-list)
|
||
|
(forward-list)
|
||
|
(insert ";")))
|
||
|
|
||
|
(defun js2r-toggle-function-async ()
|
||
|
"Toggle the innermost function from sync to async."
|
||
|
(interactive)
|
||
|
(save-excursion
|
||
|
(js2r--find-closest-function)
|
||
|
(if (looking-back "async[[:space:]\n]+")
|
||
|
(delete-region (match-beginning 0) (match-end 0))
|
||
|
(insert "async "))))
|
||
|
|
||
|
(provide 'js2r-functions)
|
||
|
;;; js2-functions.el ends here
|