;;; js2-imenu-extras.el --- Imenu support for additional constructs\r
\r
-;; Copyright (C) 2012-2013 Free Software Foundation, Inc.\r
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.\r
\r
;; Author: Dmitry Gutov <dgutov@yandex.ru>\r
;; Keywords: languages, javascript, imenu\r
\r
(:framework backbone\r
:call-re ,(concat "\\_<" js2-mode-identifier-re "\\.extend\\s-*(")\r
- :recorder js2-imenu-record-backbone-extend))\r
+ :recorder js2-imenu-record-backbone-extend)\r
+\r
+ (:framework enyo\r
+ :call-re "\\_<enyo\\.kind\\s-*("\r
+ :recorder js2-imenu-record-enyo-kind))\r
"List of JavaScript class definition or extension styles.\r
\r
:framework is a valid value in `js2-imenu-enabled-frameworks'.\r
:type 'boolean\r
:group 'js2-imenu)\r
\r
+(defcustom js2-imenu-split-string-identifiers t\r
+ "When non-nil, split string identifiers on dots.\r
+Currently used for jQuery widgets, Dojo and Enyo declarations."\r
+ :type 'boolean\r
+ :group 'js2-imenu)\r
+\r
;;;###autoload\r
(defun js2-imenu-extras-setup ()\r
(when js2-imenu-enabled-frameworks\r
(defun js2-imenu-record-string-declare ()\r
(js2-imenu-record-extend-first-arg\r
(1- (point)) 'js2-string-node-p\r
- (lambda (node) (split-string (js2-string-node-value node) "\\." t))))\r
+ (lambda (node)\r
+ (if js2-imenu-split-string-identifiers\r
+ (split-string (js2-string-node-value node) "\\." t)\r
+ (list (js2-string-node-value node))))))\r
\r
(defun js2-imenu-record-extend-first-arg (point pred qname-fn)\r
(let* ((node (js2-node-at-point point))\r
(js2-compute-nested-prop-get subject)\r
(js2-node-abs-pos methods)))))))\r
\r
+(defun js2-imenu-record-enyo-kind ()\r
+ (let* ((node (js2-node-at-point (1- (point))))\r
+ (args (js2-call-node-args node))\r
+ (options (first args)))\r
+ (when (js2-object-node-p options)\r
+ (let ((name-value\r
+ (loop for elem in (js2-object-node-elems options)\r
+ thereis\r
+ (let ((key (js2-object-prop-node-left elem))\r
+ (value (js2-object-prop-node-right elem)))\r
+ (when (and (equal\r
+ (cond ((js2-name-node-p key)\r
+ (js2-name-node-name key))\r
+ ((js2-string-node-p key)\r
+ (js2-string-node-value key)))\r
+ "name")\r
+ (js2-string-node-p value))\r
+ (js2-string-node-value value))))))\r
+ (when name-value\r
+ (js2-record-object-literal options\r
+ (if js2-imenu-split-string-identifiers\r
+ (split-string name-value "\\.")\r
+ (list name-value))\r
+ (js2-node-abs-pos options)))))))\r
+\r
(defun js2-imenu-walk-ast ()\r
(js2-visit-ast\r
js2-mode-ast\r
(js2-imenu-record-module-pattern node)))\r
t))))\r
\r
+(defun js2-imenu-parent-key-names (node)\r
+ "Get the list of parent key names of NODE.\r
+\r
+For example, for code\r
+\r
+ {rules: {password: {required: function() {}}}}\r
+\r
+when NODE is the inner `js2-object-prop-mode',\r
+it returns `(\"rules\" \"password\")'."\r
+ (let (rlt (n node))\r
+ (while (setq n (js2-imenu-parent-prop-node n))\r
+ (push (js2-prop-node-name (js2-object-prop-node-left n)) rlt))\r
+ rlt))\r
+\r
+(defun js2-imenu-parent-prop-node (node)\r
+ "When the parent of NODE is `js2-object-node',\r
+and the grandparent is `js2-object-prop-node',\r
+return the grandparent."\r
+ ;; Suppose the code is:\r
+ ;; {parent-key: {required: function() {}}}\r
+ ;; NODE is `required: function() {}'.\r
+ (let (p2 p3)\r
+ ;; Parent is `{required: function() {}}'.\r
+ (setq p2 (js2-node-parent node))\r
+ ;; GP is `parent-key: {required: function() {}}'.\r
+ (when (and p2 (js2-object-node-p p2))\r
+ (setq p3 (js2-node-parent p2))\r
+ (if (and p3 (js2-object-prop-node-p p3)) p3))))\r
+\r
(defun js2-imenu-record-orphan-function (node)\r
"Record orphan function when it's the value of NODE.\r
NODE must be `js2-object-prop-node'."\r
(let ((fn-node (js2-object-prop-node-right node)))\r
(unless (and js2-imenu-function-map\r
(gethash fn-node js2-imenu-function-map))\r
- (let ((key-node (js2-object-prop-node-left node)))\r
- (js2-record-imenu-entry fn-node\r
- (list js2-imenu-other-functions-ns\r
- (js2-prop-node-name key-node))\r
+ (let ((key-node (js2-object-prop-node-left node))\r
+ (parent-prop-node (js2-imenu-parent-prop-node node))\r
+ chain)\r
+ (setq chain (nconc (js2-imenu-parent-key-names node)\r
+ (list (js2-prop-node-name key-node))))\r
+ (push js2-imenu-other-functions-ns chain)\r
+ (js2-record-imenu-entry fn-node chain\r
(js2-node-abs-pos key-node)))))))\r
\r
(defun js2-imenu-record-module-pattern (node)\r