initial
This commit is contained in:
62
elpa/ac-js2-20190101.933/ac-js2-autoloads.el
Normal file
62
elpa/ac-js2-20190101.933/ac-js2-autoloads.el
Normal file
@@ -0,0 +1,62 @@
|
||||
;;; ac-js2-autoloads.el --- automatically extracted autoloads
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(add-to-list 'load-path (directory-file-name
|
||||
(or (file-name-directory #$) (car load-path))))
|
||||
|
||||
|
||||
;;;### (autoloads nil "ac-js2" "ac-js2.el" (0 0 0 0))
|
||||
;;; Generated autoloads from ac-js2.el
|
||||
|
||||
(autoload 'ac-js2-expand-function "ac-js2" "\
|
||||
Expand the function definition left of point.
|
||||
Expansion will only occur for candidates whose documentation
|
||||
string contain a function prototype.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'ac-js2-completion-function "ac-js2" "\
|
||||
Function for `completions-at-point'.
|
||||
|
||||
\(fn)" nil nil)
|
||||
|
||||
(autoload 'ac-js2-company "ac-js2" "\
|
||||
|
||||
|
||||
\(fn COMMAND &optional ARG &rest IGNORED)" t nil)
|
||||
|
||||
(autoload 'ac-js2-jump-to-definition "ac-js2" "\
|
||||
Jump to the definition of an object's property, variable or function.
|
||||
Navigation to a property definend in an Object literal isn't
|
||||
implemented.
|
||||
|
||||
\(fn)" t nil)
|
||||
|
||||
(autoload 'ac-js2-mode "ac-js2" "\
|
||||
A minor mode that provides auto-completion and navigation for Js2-mode.
|
||||
|
||||
\(fn &optional ARG)" t nil)
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ac-js2" '("ac-js2-")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil "ac-js2-tests" "ac-js2-tests.el" (0 0 0 0))
|
||||
;;; Generated autoloads from ac-js2-tests.el
|
||||
|
||||
(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ac-js2-tests" '("completion-frontend-test")))
|
||||
|
||||
;;;***
|
||||
|
||||
;;;### (autoloads nil nil ("ac-js2-pkg.el") (0 0 0 0))
|
||||
|
||||
;;;***
|
||||
|
||||
;; Local Variables:
|
||||
;; version-control: never
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; coding: utf-8
|
||||
;; End:
|
||||
;;; ac-js2-autoloads.el ends here
|
||||
11
elpa/ac-js2-20190101.933/ac-js2-pkg.el
Normal file
11
elpa/ac-js2-20190101.933/ac-js2-pkg.el
Normal file
@@ -0,0 +1,11 @@
|
||||
(define-package "ac-js2" "20190101.933" "Auto-complete source for Js2-mode, with navigation"
|
||||
'((js2-mode "20090723")
|
||||
(skewer-mode "1.4"))
|
||||
:authors
|
||||
'(("Scott Barnett" . "scott.n.barnett@gmail.com"))
|
||||
:maintainer
|
||||
'("Scott Barnett" . "scott.n.barnett@gmail.com")
|
||||
:url "https://github.com/ScottyB/ac-js2")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
76
elpa/ac-js2-20190101.933/ac-js2-tests.el
Normal file
76
elpa/ac-js2-20190101.933/ac-js2-tests.el
Normal file
@@ -0,0 +1,76 @@
|
||||
;;; Tests for ac-js2
|
||||
|
||||
(require 'ert)
|
||||
(require 'skewer-mode)
|
||||
(require 'js2-mode)
|
||||
(require 'ac-js2)
|
||||
|
||||
;;; Must have a skewer client connected before running the tests
|
||||
;; Need to call httpd-stop from main Emacs if running tests in batch mode
|
||||
(unless skewer-clients
|
||||
(run-skewer))
|
||||
|
||||
(ert-deftest ac-js2-candidates-test ()
|
||||
"Test the major function that returns candidates for all frontends."
|
||||
(let (property
|
||||
property-dot
|
||||
func-call
|
||||
var)
|
||||
(with-temp-buffer
|
||||
(insert "
|
||||
var temp = function(param1, param2) {
|
||||
var localParam = 15;
|
||||
return param1 + param2;
|
||||
};
|
||||
|
||||
var look;
|
||||
|
||||
temp.aFun = function(lolParam) {};
|
||||
temp.anotherFunction = function() { return {about: 3};}")
|
||||
(setq ac-js2-evaluate-calls t)
|
||||
(setq ac-js2-external-libraries nil)
|
||||
|
||||
(js2-mode)
|
||||
(ac-js2-mode t)
|
||||
(js2-parse)
|
||||
|
||||
(insert "tem")
|
||||
(ac-js2-candidates)
|
||||
(setq var ac-js2-skewer-candidates)
|
||||
(delete-char -3)
|
||||
|
||||
(insert "temp.")
|
||||
(js2-parse)
|
||||
(ac-js2-candidates)
|
||||
(setq property-dot ac-js2-skewer-candidates)
|
||||
(delete-char -5)
|
||||
|
||||
(insert "temp.aF")
|
||||
(js2-parse)
|
||||
(ac-js2-candidates)
|
||||
(setq property ac-js2-skewer-candidates))
|
||||
|
||||
(should (assoc 'anotherFunction property-dot))
|
||||
(print property)
|
||||
(should (assoc 'aFun property))
|
||||
(should (assoc 'temp var))))
|
||||
|
||||
(defmacro completion-frontend-test (test-name completion-function)
|
||||
"Utility for testing completion front ends.
|
||||
TODO: cover more cases"
|
||||
`(ert-deftest ,test-name ()
|
||||
(let (var)
|
||||
(with-temp-buffer
|
||||
(insert "var testComplete = function(param1, param2) {};")
|
||||
|
||||
(js2-mode)
|
||||
(ac-js2-mode t)
|
||||
(js2-parse)
|
||||
|
||||
(insert "testComplet")
|
||||
(funcall ',completion-function)
|
||||
(setq var (thing-at-point 'word)))
|
||||
(should (string= var "testComplete")))))
|
||||
|
||||
(completion-frontend-test auto-complete-test auto-complete)
|
||||
(completion-frontend-test completion-at-point-test completion-at-point)
|
||||
BIN
elpa/ac-js2-20190101.933/ac-js2-tests.elc
Normal file
BIN
elpa/ac-js2-20190101.933/ac-js2-tests.elc
Normal file
Binary file not shown.
608
elpa/ac-js2-20190101.933/ac-js2.el
Normal file
608
elpa/ac-js2-20190101.933/ac-js2.el
Normal file
@@ -0,0 +1,608 @@
|
||||
;;; ac-js2.el --- Auto-complete source for Js2-mode, with navigation
|
||||
|
||||
;; Copyright (C) 2013 Scott Barnett
|
||||
|
||||
;; Author: Scott Barnett <scott.n.barnett@gmail.com>
|
||||
;; URL: https://github.com/ScottyB/ac-js2
|
||||
;; Version: 1.0
|
||||
;; Package-Requires: ((js2-mode "20090723")(skewer-mode "1.4"))
|
||||
|
||||
;; 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/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; An attempt to get context sensitive Javascript completion in Emacs.
|
||||
;; Basic completions are obtained by parsing Javascript code with
|
||||
;; Js2-mode's parser.
|
||||
;;
|
||||
;; Installation
|
||||
;;
|
||||
;; Easiest way to get ac-js2 is to install it from MELPA. You may need
|
||||
;; this snippet
|
||||
;;
|
||||
;; `(add-to-list 'package-archives
|
||||
;; '("melpa" . "http://melpa.milkbox.net/packages/") t)'
|
||||
;;
|
||||
;; if you don't have it already to fetch packages from MELPA.
|
||||
;;
|
||||
;; Enable ac-js2 in js2-mode as follows:
|
||||
;;
|
||||
;; (add-hook 'js2-mode-hook 'ac-js2-mode)
|
||||
;;
|
||||
;; Ac-js2 does not require auto-complete mode but I suggest you grab
|
||||
;; it anyway as ac-js2 is designed to work with a completion frontend.
|
||||
;; Support for Company mode is on its way.
|
||||
;;
|
||||
;; For more comprehensive completions you can opt to evaluate the code
|
||||
;; for candidates. A browser needs to be connected to Emacs for the
|
||||
;; evaluation completions to work. Put this in your init.el file.
|
||||
;;
|
||||
;; `(setq ac-js2-evaluate-calls t)'
|
||||
;;
|
||||
;; To add completions for external libraries add something like this:
|
||||
;;
|
||||
;; (add-to-list 'ac-js2-external-libraries "path/to/lib/library.js")
|
||||
;;
|
||||
;; Then connect a browser to Emacs by calling `(run-skewer)'. You may
|
||||
;; need to save the buffer for completions to start.
|
||||
;;
|
||||
;; If auto-complete mode is installed on your system then completions
|
||||
;; should start showing up otherwise use `completion-at-point'.
|
||||
;;
|
||||
;; Note: library completions will only work if `ac-js2-evaluate-calls'
|
||||
;; is set and a browser is connected to Emacs.
|
||||
;;
|
||||
;; Bonus: M-. is bound to `ac-js2-jump-to-definition' which will jump
|
||||
;; to Javascript definitions found in the same buffer. Given the
|
||||
;; following proprety reference:
|
||||
;;
|
||||
;; foo.bar.baz();
|
||||
;;
|
||||
;; placing the cursor on `foo', `bar' or `baz' and executing M-. will
|
||||
;; take you straight to their respective definitions. Use M-, to jump
|
||||
;; back to where you were. Also works for object literals.
|
||||
;;
|
||||
;; Recently added `ac-js2-expand-function' that will expand a function's
|
||||
;; parameters bound to `C-c C-c`. Expansion will only work if the cursor
|
||||
;; is after the function.
|
||||
;;
|
||||
;; If you have any issues or suggestions please create an issue on Github:
|
||||
;; https://github.com/ScottyB/ac-js2
|
||||
|
||||
;;; History:
|
||||
|
||||
;; Version 1.0
|
||||
;; * Navigation within current buffer
|
||||
;; * Completion and docstring for objects via Skewer
|
||||
;; * External library support
|
||||
;; * Basic completions of objects in current buffer
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'js2-mode)
|
||||
(require 'skewer-mode)
|
||||
(require 'cl-lib)
|
||||
(require 'etags)
|
||||
|
||||
(defgroup ac-js2 nil
|
||||
"Auto-completion for js2-mode."
|
||||
:group 'completion
|
||||
:prefix "ac-js2-")
|
||||
|
||||
;;; Configuration variables
|
||||
|
||||
(defcustom ac-js2-add-ecma-262-externs t
|
||||
"If non-nil add `js2-ecma-262-externs' to completion candidates.")
|
||||
|
||||
(defcustom ac-js2-add-browser-externs t
|
||||
"If non-nil add `js2-browser-externs' to completion candidates.")
|
||||
|
||||
(defcustom ac-js2-add-keywords t
|
||||
"If non-nil add `js2-keywords' to completion candidates.")
|
||||
|
||||
(defcustom ac-js2-add-prototype-completions t
|
||||
"When non-nil traverse the prototype chain adding to completion candidates.")
|
||||
|
||||
(defcustom ac-js2-external-libraries '()
|
||||
"List of absolute paths to external Javascript libraries.")
|
||||
|
||||
(defcustom ac-js2-evaluate-calls nil
|
||||
"Warning. When true function calls will be evaluated in the browser.
|
||||
This may cause undesired side effects however it will
|
||||
provide better completions. Use at your own risk.")
|
||||
|
||||
(defcustom ac-js2-force-reparse t
|
||||
"Force Js2-mode to reparse buffer before fetching completion candidates.")
|
||||
|
||||
;;; Internal variables
|
||||
|
||||
(defvar ac-js2-keywords '()
|
||||
"Cached string version of `js2-keywords'.")
|
||||
|
||||
(defvar ac-js2-candidates '())
|
||||
|
||||
;; Types of skewer completion methods available
|
||||
(defconst ac-js2-method-eval 0)
|
||||
(defconst ac-js2-method-global 1
|
||||
"Return candidates for the global object.
|
||||
Only keys of the object are returned as the other properties come
|
||||
from js2-mode's externs.")
|
||||
|
||||
(defvar ac-js2-data-root (file-name-directory load-file-name)
|
||||
"Location of data files needed for `ac-js2-on-skewer-load'.")
|
||||
|
||||
;;; Skewer integration
|
||||
|
||||
(defvar ac-js2-skewer-candidates '()
|
||||
"Cadidates obtained from skewering.")
|
||||
|
||||
(defun ac-js2-on-skewer-load ()
|
||||
"Inject skewer addon and evaluate external libraries in browser."
|
||||
(insert-file-contents (expand-file-name "skewer-addon.js" ac-js2-data-root))
|
||||
(and ac-js2-evaluate-calls
|
||||
(mapcar (lambda (library)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (expand-file-name library))
|
||||
(skewer-eval (buffer-string)
|
||||
nil
|
||||
:type "complete"))) ac-js2-external-libraries)))
|
||||
|
||||
(defun ac-js2-skewer-completion-candidates ()
|
||||
"Get completions returned from skewer."
|
||||
(mapcar (lambda (candidate) (symbol-name (car candidate))) ac-js2-skewer-candidates))
|
||||
|
||||
(defun ac-js2-skewer-document-candidates (name)
|
||||
"Return document string for NAME from skewer."
|
||||
(let ((doc (cdr (assoc-string name ac-js2-skewer-candidates))))
|
||||
(or (ac-js2-format-function doc) doc)))
|
||||
|
||||
(defun ac-js2-get-object-properties (name)
|
||||
"Find properties of NAME for completion."
|
||||
(ac-js2-skewer-eval-wrapper name `((prototypes . ,ac-js2-add-prototype-completions))))
|
||||
|
||||
(defun ac-js2-skewer-result-callback (result)
|
||||
"Process the RESULT passed from the browser."
|
||||
(let ((value (cdr (assoc 'value result))))
|
||||
(if (and (skewer-success-p result) value)
|
||||
(setq ac-js2-skewer-candidates (append value nil)))))
|
||||
|
||||
(defun ac-js2-skewer-eval-wrapper (str &optional extras)
|
||||
"Wrap `skewer-eval-synchronously' to check if a skewer-client is avilable.
|
||||
STR is the text to send to the browser for evaluation. Extra
|
||||
parameters can be passed to the browser using EXTRAS. EXTRAS must
|
||||
be of the form (param-string . value) where param-string is the
|
||||
reference and value is the value that can be retrieved from the
|
||||
request object in Javacript."
|
||||
(setq ac-js2-skewer-candidates nil)
|
||||
(if skewer-clients
|
||||
(if (or ac-js2-evaluate-calls
|
||||
(not (ac-js2-has-function-calls str)))
|
||||
(ac-js2-skewer-result-callback
|
||||
(skewer-eval-synchronously str
|
||||
:type "complete"
|
||||
:extra extras)))
|
||||
(setq skewer-queue nil)))
|
||||
|
||||
;; Generate candidates
|
||||
(defun ac-js2-candidates ()
|
||||
"Main function called to gather candidates for auto-completion."
|
||||
(if ac-js2-force-reparse (js2-reparse))
|
||||
(let ((node (js2-node-parent (js2-node-at-point (1- (point)))))
|
||||
beg
|
||||
(prop-get-regex "[a-zA-Z)]\\.")
|
||||
name)
|
||||
(setq ac-js2-candidates nil)
|
||||
(cond
|
||||
((looking-back "\\.")
|
||||
;; TODO: Need to come up with a better way to extract object than this regex!!
|
||||
(save-excursion
|
||||
(setq beg (and (skip-chars-backward "[a-zA-Z_$][0-9a-zA-Z_$#\"())]+\\.") (point))))
|
||||
(setq name (buffer-substring-no-properties beg (1- (point))))
|
||||
(ac-js2-get-object-properties name)
|
||||
(setq node (ac-js2-initialized-node (if (string-match prop-get-regex name)
|
||||
(reverse (split-string name prop-get-regex)) name)))
|
||||
(if (js2-object-node-p node)
|
||||
(setq ac-js2-candidates
|
||||
(mapcar (lambda (elem)
|
||||
(ac-js2-format-node (js2-node-string (js2-object-prop-node-left elem))
|
||||
elem))
|
||||
(js2-object-node-elems node))))
|
||||
(append (mapcar 'cl-first ac-js2-candidates)
|
||||
(ac-js2-skewer-completion-candidates)))
|
||||
((js2-prop-get-node-p node)
|
||||
(setq node (js2-prop-get-node-left node))
|
||||
(setq name (js2-node-string node))
|
||||
(ac-js2-get-object-properties name)
|
||||
(ac-js2-skewer-completion-candidates))
|
||||
(t
|
||||
(ac-js2-skewer-eval-wrapper "" `((method . ,ac-js2-method-global)))
|
||||
(append (ac-js2-skewer-completion-candidates)
|
||||
(ac-js2-add-extra-completions
|
||||
(mapcar 'cl-first (ac-js2-get-names-in-scope))))))))
|
||||
|
||||
(defun ac-js2-document (name)
|
||||
"Show documentation for NAME from local buffer if present
|
||||
otherwise use documentation obtained from skewer."
|
||||
(let* ((docs (cdr (assoc name ac-js2-candidates)))
|
||||
(doc (if (listp docs) (cl-first docs) docs)))
|
||||
(if doc doc (ac-js2-skewer-document-candidates name))))
|
||||
|
||||
;; Auto-complete settings
|
||||
|
||||
(defun ac-js2-ac-candidates ()
|
||||
"Completion candidates for auto-complete mode."
|
||||
(ac-js2-candidates))
|
||||
|
||||
(defun ac-js2-ac-document (name)
|
||||
"Documentation to be shown for auto-complete mode."
|
||||
(ac-js2-document name))
|
||||
|
||||
(defun ac-js2-ac-prefix()
|
||||
(or (ac-prefix-default) (ac-prefix-c-dot)))
|
||||
|
||||
(defun ac-js2-save ()
|
||||
"Called on `before-save-hook' to evaluate buffer."
|
||||
(interactive)
|
||||
(when (string= major-mode "js2-mode")
|
||||
(ac-js2-skewer-eval-wrapper (buffer-string)))
|
||||
t)
|
||||
|
||||
;;;###autoload
|
||||
(defun ac-js2-expand-function()
|
||||
"Expand the function definition left of point.
|
||||
Expansion will only occur for candidates whose documentation
|
||||
string contain a function prototype."
|
||||
(interactive)
|
||||
(let* ((word (progn
|
||||
(if (featurep 'auto-complete) (ac-complete))
|
||||
(substring-no-properties (or (thing-at-point 'word) ""))))
|
||||
(candidate (ac-js2-ac-document word)))
|
||||
(if (and (looking-back word) (stringp candidate))
|
||||
(when (string-match "^function" candidate)
|
||||
(cond ((featurep 'yasnippet)
|
||||
(yas-expand-snippet
|
||||
(concat "("
|
||||
(replace-regexp-in-string "\\([a-zA-Z0-9]+\\)"
|
||||
(lambda (txt) (concat "${" txt "}"))
|
||||
(cl-second (split-string candidate "[()]")))
|
||||
")$0"))))))))
|
||||
|
||||
(defun ac-js2-setup-auto-complete-mode ()
|
||||
"Setup ac-js2 to be used with auto-complete-mode."
|
||||
(add-to-list 'ac-sources 'ac-source-js2)
|
||||
(auto-complete-mode)
|
||||
(ac-define-source "js2"
|
||||
'((candidates . ac-js2-ac-candidates)
|
||||
(document . ac-js2-ac-document)
|
||||
(prefix . ac-js2-ac-prefix)
|
||||
(requires . -1))))
|
||||
|
||||
;;; Completion at point function
|
||||
|
||||
;;;###autoload
|
||||
(defun ac-js2-completion-function ()
|
||||
"Function for `completions-at-point'."
|
||||
(save-excursion
|
||||
(let ((bounds (if (looking-back "\\.")
|
||||
(cons (point) (point))
|
||||
(bounds-of-thing-at-point 'word))))
|
||||
(list (car bounds) (cdr bounds) (ac-js2-candidates)))))
|
||||
|
||||
;;; Company
|
||||
|
||||
;;;###autoload
|
||||
(defun ac-js2-company (command &optional arg &rest ignored)
|
||||
(interactive (list 'interactive))
|
||||
(if (not (featurep 'company))
|
||||
(message "Company is not installed")
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'ac-js2-company))
|
||||
(prefix (when ac-js2-mode
|
||||
(or (company-grab-symbol)
|
||||
'stop)))
|
||||
(candidates (all-completions arg (ac-js2-candidates)))
|
||||
(duplicates t)
|
||||
(meta (let ((doc (ac-js2-document arg)))
|
||||
(when doc
|
||||
(with-temp-buffer
|
||||
(insert doc)
|
||||
(js-mode)
|
||||
(if (fboundp 'font-lock-ensure)
|
||||
(font-lock-ensure)
|
||||
(with-no-warnings
|
||||
(font-lock-fontify-buffer)))
|
||||
(buffer-string))))))))
|
||||
|
||||
;;; Helper functions
|
||||
|
||||
(defun ac-js2-build-prop-name-list (prop-node)
|
||||
"Build a list of names from a PROP-NODE."
|
||||
(let* (names
|
||||
left
|
||||
left-node)
|
||||
(unless (js2-prop-get-node-p prop-node)
|
||||
(error "Node is not a property prop-node"))
|
||||
(while (js2-prop-get-node-p prop-node)
|
||||
(push (js2-name-node-name (js2-prop-get-node-right prop-node)) names)
|
||||
(setq left-node (js2-prop-get-node-left prop-node))
|
||||
(when (js2-name-node-p left-node)
|
||||
(setq left (js2-name-node-name left-node)))
|
||||
(setq prop-node (js2-node-parent prop-node)))
|
||||
(append names `(,left))))
|
||||
|
||||
(defun ac-js2-prop-names-left (name-node)
|
||||
"Create a list of all of the names in the property NAME-NODE.
|
||||
NAME-NODE must have a js2-prop-get-node as parent. Only adds
|
||||
properties to the left of point. This is so individual jump
|
||||
points can be found for each property in the chain."
|
||||
(let* (name
|
||||
(parent (js2-node-parent name-node))
|
||||
left
|
||||
names)
|
||||
(unless (or (js2-prop-get-node-p parent) (js2-name-node-p name-node))
|
||||
(error "Not a name node or doesn't have a prop-get-node as parent"))
|
||||
(setq name (js2-name-node-name name-node)
|
||||
left (js2-prop-get-node-left parent))
|
||||
(if (and (js2-name-node-p left)
|
||||
(string= name (js2-name-node-name left)))
|
||||
(setq names name)
|
||||
(js2-visit-ast
|
||||
parent
|
||||
(lambda (node endp)
|
||||
(unless endp
|
||||
(if (js2-name-node-p node)
|
||||
(push (js2-name-node-name node) names)
|
||||
t))))
|
||||
names)))
|
||||
|
||||
(defun ac-js2-has-function-calls (string)
|
||||
"Check if the Javascript code in STRING has a Js2-call-node."
|
||||
(with-temp-buffer
|
||||
(insert string)
|
||||
(let* ((ast (js2-parse)))
|
||||
(catch 'call-node
|
||||
(js2-visit-ast-root
|
||||
ast
|
||||
(lambda (node end-p)
|
||||
(unless end-p
|
||||
(if (js2-call-node-p node)
|
||||
(throw 'call-node t)
|
||||
t))))))))
|
||||
|
||||
(defun ac-js2-add-extra-completions (completions)
|
||||
"Add extra candidates to COMPLETIONS."
|
||||
(append completions
|
||||
(if ac-js2-add-keywords (or ac-js2-keywords (setq ac-js2-keywords (mapcar 'symbol-name js2-keywords))))
|
||||
(if ac-js2-add-ecma-262-externs js2-ecma-262-externs)
|
||||
(if ac-js2-add-browser-externs js2-browser-externs)))
|
||||
|
||||
(defun ac-js2-root-or-node ()
|
||||
"Return the current node or js2-ast-root node."
|
||||
(let ((node (js2-node-at-point)))
|
||||
(if (js2-ast-root-p node)
|
||||
node
|
||||
(js2-node-get-enclosing-scope node))))
|
||||
|
||||
(defun ac-js2-get-names-in-scope ()
|
||||
"Fetches all symbols in scope and formats them for completion."
|
||||
(let* ((scope (ac-js2-root-or-node))
|
||||
result)
|
||||
(while scope
|
||||
(setq result (append result
|
||||
(cl-loop for item in (js2-scope-symbol-table scope)
|
||||
if (not (assoc (car item) result))
|
||||
collect item)))
|
||||
(setq scope (js2-scope-parent-scope scope)))
|
||||
(setq ac-js2-candidates
|
||||
(mapcar #'(lambda (x)
|
||||
(let* ((name (symbol-name (car x)))
|
||||
(init (ac-js2-initialized-node name)))
|
||||
(ac-js2-format-node name init)))
|
||||
result))))
|
||||
|
||||
(defun ac-js2-initialized-node (name)
|
||||
"Return initial value assigned to NAME.
|
||||
NAME may be either a variable, a function or a variable that
|
||||
holds a function. NAME may also be a list of names that make up a
|
||||
object property. Returns nil if no initial value can be found."
|
||||
(let* ((node (if (listp name) (ac-js2-find-property name)
|
||||
(ac-js2-name-declaration name)))
|
||||
(parent (if node (js2-node-parent node)))
|
||||
(init (cond
|
||||
((js2-function-node-p parent)
|
||||
parent)
|
||||
((js2-function-node-p node)
|
||||
node)
|
||||
((js2-var-init-node-p parent)
|
||||
(js2-var-init-node-initializer parent))
|
||||
((js2-assign-node-p parent)
|
||||
(js2-assign-node-right parent))
|
||||
(t
|
||||
nil))))
|
||||
init))
|
||||
|
||||
(defun ac-js2-name-declaration (name)
|
||||
"Return the declaration node for node named NAME."
|
||||
(let* ((node (ac-js2-root-or-node))
|
||||
(scope-def (js2-get-defining-scope node name))
|
||||
(scope (if scope-def (js2-scope-get-symbol scope-def name) nil))
|
||||
(symbol (if scope (js2-symbol-ast-node scope) nil)))
|
||||
(if (not symbol)
|
||||
(ac-js2-get-function-node name scope-def)
|
||||
symbol)))
|
||||
|
||||
;;; Completion candidate formatting
|
||||
|
||||
(defun ac-js2-format-node (name node)
|
||||
"Format NAME and NODE for completion.
|
||||
Returned format is a list where the first element is the NAME of
|
||||
the node (shown in completion candidate list) and the last
|
||||
element is the text to show as documentation."
|
||||
(let ((node (if (js2-object-prop-node-p node) (js2-object-prop-node-right node) node))
|
||||
(name-format (replace-regexp-in-string "\"" "" name))
|
||||
(doc (if (and (js2-function-node-p node)
|
||||
(cl-find name (js2-function-node-params node)
|
||||
:test '(lambda (name param) (string= name (js2-name-node-name param)))))
|
||||
"Function parameter"
|
||||
(ac-js2-format-node-doc node))))
|
||||
`(,name-format . ,doc)))
|
||||
|
||||
(defun ac-js2-format-object-node-doc (obj-node)
|
||||
"Format OBJ-NODE to display as documentation."
|
||||
(let (elems)
|
||||
(unless (js2-object-node-p obj-node)
|
||||
(error "Node is not an object node"))
|
||||
(setq elems (js2-object-node-elems obj-node))
|
||||
(if (not elems)
|
||||
"{}"
|
||||
(mapconcat #'(lambda (x) (ac-js2-format-js2-object-prop-doc x)) elems "\n"))))
|
||||
|
||||
(defun ac-js2-format-node-doc (node)
|
||||
"Format NODE for displaying in a document string."
|
||||
(let* ((node-above (and node (js2-node-at-point
|
||||
(save-excursion
|
||||
(goto-char (js2-node-abs-pos node))
|
||||
(forward-line -1)
|
||||
(point)))))
|
||||
(comment (if (js2-comment-node-p node-above)
|
||||
(ac-js2-format-comment (js2-node-string node-above))))
|
||||
(doc (cond
|
||||
((js2-function-node-p node)
|
||||
(ac-js2-format-function node))
|
||||
((js2-object-node-p node)
|
||||
(ac-js2-format-object-node-doc node))
|
||||
((js2-object-prop-node-p node)
|
||||
(ac-js2-format-node-doc (js2-object-prop-node-right node)))
|
||||
(t
|
||||
(if (js2-node-p node) (js2-node-string node) "")))))
|
||||
(if comment (concat comment "\n" doc) doc)))
|
||||
|
||||
(defun ac-js2-format-js2-object-prop-doc (obj-prop)
|
||||
"Format an OBJ-PROP for displaying as a document string."
|
||||
(unless (js2-object-prop-node-p obj-prop)
|
||||
(error "Node is not an object property node"))
|
||||
(let* ((left (js2-object-prop-node-left obj-prop))
|
||||
(right (js2-object-prop-node-right obj-prop)))
|
||||
(concat (js2-node-string left) " : "
|
||||
(ac-js2-format-node-doc right))))
|
||||
|
||||
(defun ac-js2-format-function (func)
|
||||
"Formats a function for a document string.
|
||||
FUNC can be either a function node or a string starting with
|
||||
'function'. Returns nil if neither."
|
||||
(let ((str (or (and (js2-function-node-p func) (js2-node-string func))
|
||||
(and (stringp func) (eq 0 (string-match "function" func)) func))))
|
||||
(if str (substring str 0 (1+ (string-match ")" str))))))
|
||||
|
||||
(defun ac-js2-format-comment (comment)
|
||||
"Prepare a COMMENT node for displaying in a popup."
|
||||
(let* ((node-string (if (js2-comment-node-p comment)
|
||||
(js2-node-string comment)
|
||||
comment))
|
||||
(string (replace-regexp-in-string "[ \t]$" ""
|
||||
(replace-regexp-in-string "^[ \t\n*/*]+" "" node-string))))
|
||||
string))
|
||||
|
||||
;;; Navigation commands for js2-mode
|
||||
|
||||
(defun ac-js2-find-property (list-names)
|
||||
"Find the property definition that consists of LIST-NAMES.
|
||||
Supports navigation to 'foo.bar = 3' and 'foo = {bar: 3}'."
|
||||
(catch 'prop-found
|
||||
(js2-visit-ast-root
|
||||
js2-mode-ast
|
||||
(lambda (node endp)
|
||||
(let ((parent (js2-node-parent node)))
|
||||
(unless endp
|
||||
(if (or (and (js2-prop-get-node-p node)
|
||||
(not (or (js2-elem-get-node-p parent) (js2-call-node-p parent)))
|
||||
(equal list-names (ac-js2-build-prop-name-list node)))
|
||||
(and (js2-name-node-p node)
|
||||
(js2-object-prop-node-p parent)
|
||||
(string= (js2-name-node-name node)
|
||||
(cl-first list-names))))
|
||||
(throw 'prop-found node))
|
||||
t))))))
|
||||
|
||||
(defun ac-js2-get-function-node (name scope)
|
||||
"Return node of function named NAME in SCOPE."
|
||||
(catch 'function-found
|
||||
(js2-visit-ast
|
||||
scope
|
||||
(lambda (node end-p)
|
||||
(when (and (not end-p)
|
||||
(string= name (ac-js2-get-function-name node)))
|
||||
(throw 'function-found node))
|
||||
t))
|
||||
nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun ac-js2-jump-to-definition ()
|
||||
"Jump to the definition of an object's property, variable or function.
|
||||
Navigation to a property definend in an Object literal isn't
|
||||
implemented."
|
||||
(interactive)
|
||||
(ring-insert find-tag-marker-ring (point-marker))
|
||||
(let* ((node (js2-node-at-point))
|
||||
(parent (js2-node-parent node))
|
||||
(prop-names (if (js2-prop-get-node-p parent)
|
||||
(ac-js2-prop-names-left node)))
|
||||
(name (if (and (js2-name-node-p node)
|
||||
(not (js2-object-prop-node-p parent)))
|
||||
(js2-name-node-name node)
|
||||
(error "Node is not a supported jump node")))
|
||||
(node-init (if (and prop-names (listp prop-names))
|
||||
(ac-js2-find-property prop-names)
|
||||
(ac-js2-name-declaration name))))
|
||||
(unless node-init
|
||||
(pop-tag-mark)
|
||||
(error "No jump location found"))
|
||||
(goto-char (js2-node-abs-pos node-init))))
|
||||
|
||||
(defun ac-js2-get-function-name (fn-node)
|
||||
"Return the name of the function FN-NODE.
|
||||
Value may be either function name or the variable name that holds
|
||||
the function."
|
||||
(let ((parent (js2-node-parent fn-node)))
|
||||
(if (js2-function-node-p fn-node)
|
||||
(or (js2-function-name fn-node)
|
||||
(if (js2-var-init-node-p parent)
|
||||
(js2-name-node-name (js2-var-init-node-target parent)))))))
|
||||
|
||||
(defvar ac-js2-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "M-.") 'ac-js2-jump-to-definition)
|
||||
(define-key map (kbd "M-,") 'pop-tag-mark)
|
||||
(define-key map (kbd "C-c C-c") 'ac-js2-expand-function)
|
||||
map)
|
||||
"Keymap for `ac-js2-mode'.")
|
||||
|
||||
;;; Minor mode
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode ac-js2-mode
|
||||
"A minor mode that provides auto-completion and navigation for Js2-mode."
|
||||
:keymap ac-js2-mode-map
|
||||
(if (featurep 'auto-complete)
|
||||
(ac-js2-setup-auto-complete-mode))
|
||||
(set (make-local-variable 'completion-at-point-functions)
|
||||
(cons 'ac-js2-completion-function completion-at-point-functions))
|
||||
(ac-js2-skewer-eval-wrapper (buffer-string))
|
||||
(add-hook 'before-save-hook 'ac-js2-save nil t)
|
||||
(add-hook 'skewer-js-hook 'ac-js2-on-skewer-load))
|
||||
|
||||
|
||||
(provide 'ac-js2)
|
||||
|
||||
;;; ac-js2.el ends here
|
||||
BIN
elpa/ac-js2-20190101.933/ac-js2.elc
Normal file
BIN
elpa/ac-js2-20190101.933/ac-js2.elc
Normal file
Binary file not shown.
116
elpa/ac-js2-20190101.933/skewer-addon.js
Normal file
116
elpa/ac-js2-20190101.933/skewer-addon.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @fileOverview Completion request handler for skewer.js
|
||||
* @requires skewer
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles a completion request from Emacs.
|
||||
* @param request The request object sent by Emacs
|
||||
* @returns The completions and init values to be returned to Emacs
|
||||
*/
|
||||
skewer.fn.complete = function(request) {
|
||||
var result = {
|
||||
type : request.type,
|
||||
id : request.id,
|
||||
strict : request.strict,
|
||||
status : "success"
|
||||
},
|
||||
|
||||
/**
|
||||
* Methods for generating candidates
|
||||
*/
|
||||
METHOD = {
|
||||
EVAL : 0,
|
||||
GLOBAL : 1
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the properties from object to extendObject. Properties
|
||||
* may be from the prototype but we still want to add them.
|
||||
*/
|
||||
extend = function(extendObject, object) {
|
||||
for(var key in object) {
|
||||
extendObject[key] = object[key];
|
||||
}
|
||||
},
|
||||
|
||||
globalCompletion = function() {
|
||||
var global = Function('return this')(),
|
||||
keys = Object.keys(global);
|
||||
candidates = buildCandidates(global, keys);
|
||||
},
|
||||
|
||||
evalCompletion = function(evalObject) {
|
||||
var obj = (eval, eval)(evalObject);
|
||||
if (typeof obj === "object") {
|
||||
candidates = buildCandidates(obj) || {};
|
||||
while (request.prototypes && (obj = Object.getPrototypeOf(obj)) !== null) {
|
||||
extend(candidates, buildCandidates(obj));
|
||||
}
|
||||
} else if (typeof obj === "function"){
|
||||
candidates = buildCandidates(obj) || {};
|
||||
extend(candidates, buildCandidates(Object.getPrototypeOf(obj)));
|
||||
if (request.prototypes) {
|
||||
var protoObject = Object.getPrototypeOf(obj.prototype);
|
||||
if (protoObject !== null) {
|
||||
extend(candidates, buildCandidates(protoObject));
|
||||
} else {
|
||||
extend(candidates, buildCandidates(obj.prototype));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Completion candidates sent back to Emacs. Keys are
|
||||
* completion candidates the values are the inital items or
|
||||
* function interfaces.
|
||||
*/
|
||||
candidates = {},
|
||||
|
||||
/**
|
||||
* Build the candiates to return to Emacs.
|
||||
* @param obj The object to get candidates from
|
||||
* @param items The selected keys from obj to create candidates for
|
||||
* @return object containing completion candidates and documentation strings
|
||||
*/
|
||||
buildCandidates = function(obj, items) {
|
||||
var keys = items || Object.getOwnPropertyNames(obj), values = {};
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (key === "callee" || key === "caller" || key === "arguments") continue;
|
||||
if (Object.prototype.toString.call(obj[key]) === "[object Function]") {
|
||||
values[key] = obj[key].toString();
|
||||
} else if (typeof obj[key] === "object"){
|
||||
values[key] = "[object Object]";
|
||||
} else if (typeof obj[key] === "number") {
|
||||
if (!(obj instanceof Array)) {
|
||||
values[key] = obj[key].toString();
|
||||
}
|
||||
} else if (typeof obj[key] === "string") {
|
||||
values[key] = obj[key].toString();
|
||||
} else if(obj[key] === true) {
|
||||
values[key] = "true";
|
||||
} else if (obj[key] === false) {
|
||||
values[key] = "false";
|
||||
} else {
|
||||
values[key] = "";
|
||||
}
|
||||
}
|
||||
return values;
|
||||
};
|
||||
try {
|
||||
switch (request.method) {
|
||||
case METHOD.GLOBAL:
|
||||
globalCompletion();
|
||||
break;
|
||||
default:
|
||||
evalCompletion(request.eval);
|
||||
}
|
||||
result.value = candidates;
|
||||
} catch (error){
|
||||
skewer.errorResult(error, result, request);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
Reference in New Issue
Block a user