diff options
| author | Fabián Ezequiel Gallina | 2013-04-18 23:31:09 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2013-04-18 23:31:09 -0300 |
| commit | adc3121366c4cc6d90b0122036bdfb0eb6308e3f (patch) | |
| tree | 502e58d0fa27c68dd1afa0f380b26c3f864dfb4c | |
| parent | 7e00831f518cf4c9ca505ec3e8767bf0787766b4 (diff) | |
| download | emacs-adc3121366c4cc6d90b0122036bdfb0eb6308e3f.tar.gz emacs-adc3121366c4cc6d90b0122036bdfb0eb6308e3f.zip | |
New faster Imenu implementation.
* lisp/progmodes/python.el:
(python-imenu-prev-index-position):
(python-imenu-format-item-label-function)
(python-imenu-format-parent-item-label-function)
(python-imenu-format-parent-item-jump-label-function):
New vars.
(python-imenu-format-item-label)
(python-imenu-format-parent-item-label)
(python-imenu-format-parent-item-jump-label)
(python-imenu--put-parent, python-imenu--build-tree)
(python-imenu-create-index, python-imenu-create-flat-index)
(python-util-popn): New functions.
(python-mode): Set imenu-create-index-function to
python-imenu-create-index.
* test/automated/python-tests.el (python-imenu-prev-index-position-1):
Removed test.
(python-imenu-create-index-1, python-imenu-create-flat-index-1):
New tests.
Fixes: debbugs:14058
| -rw-r--r-- | lisp/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/progmodes/python.el | 234 | ||||
| -rw-r--r-- | test/ChangeLog | 7 | ||||
| -rw-r--r-- | test/automated/python-tests.el | 143 |
4 files changed, 343 insertions, 59 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 98ba110ab33..bc409171fb2 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | 2013-04-19 Fabián Ezequiel Gallina <fgallina@gnu.org> | ||
| 2 | |||
| 3 | New faster Imenu implementation (bug#14058). | ||
| 4 | * progmodes/python.el: | ||
| 5 | (python-imenu-prev-index-position): | ||
| 6 | (python-imenu-format-item-label-function) | ||
| 7 | (python-imenu-format-parent-item-label-function) | ||
| 8 | (python-imenu-format-parent-item-jump-label-function): | ||
| 9 | New vars. | ||
| 10 | (python-imenu-format-item-label) | ||
| 11 | (python-imenu-format-parent-item-label) | ||
| 12 | (python-imenu-format-parent-item-jump-label) | ||
| 13 | (python-imenu--put-parent, python-imenu--build-tree) | ||
| 14 | (python-imenu-create-index, python-imenu-create-flat-index) | ||
| 15 | (python-util-popn): New functions. | ||
| 16 | (python-mode): Set imenu-create-index-function to | ||
| 17 | python-imenu-create-index. | ||
| 18 | |||
| 1 | 2013-04-18 Stefan Monnier <monnier@iro.umontreal.ca> | 19 | 2013-04-18 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 20 | ||
| 3 | * winner.el (winner-active-region): Use region-active-p, activate-mark | 21 | * winner.el (winner-active-region): Use region-active-p, activate-mark |
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 53aff94ae0e..06d07d6ee3c 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -177,12 +177,14 @@ | |||
| 177 | ;; might guessed you should run `python-shell-send-buffer' from time | 177 | ;; might guessed you should run `python-shell-send-buffer' from time |
| 178 | ;; to time to get better results too. | 178 | ;; to time to get better results too. |
| 179 | 179 | ||
| 180 | ;; Imenu: This mode supports Imenu in its most basic form, letting it | 180 | ;; Imenu: There are two index building functions to be used as |
| 181 | ;; build the necessary alist via `imenu-default-create-index-function' | 181 | ;; `imenu-create-index-function': `python-imenu-create-index' (the |
| 182 | ;; by having set `imenu-extract-index-name-function' to | 182 | ;; default one, builds the alist in form of a tree) and |
| 183 | ;; `python-info-current-defun' and | 183 | ;; `python-imenu-create-flat-index'. See also |
| 184 | ;; `imenu-prev-index-position-function' to | 184 | ;; `python-imenu-format-item-label-function', |
| 185 | ;; `python-imenu-prev-index-position'. | 185 | ;; `python-imenu-format-parent-item-label-function', |
| 186 | ;; `python-imenu-format-parent-item-jump-label-function' variables for | ||
| 187 | ;; changing the way labels are formatted in the tree version. | ||
| 186 | 188 | ||
| 187 | ;; If you used python-mode.el you probably will miss auto-indentation | 189 | ;; If you used python-mode.el you probably will miss auto-indentation |
| 188 | ;; when inserting newlines. To achieve the same behavior you have | 190 | ;; when inserting newlines. To achieve the same behavior you have |
| @@ -1194,7 +1196,7 @@ Returns nil if point is not in a def or class." | |||
| 1194 | 1196 | ||
| 1195 | (defun python-nav--syntactically (fn poscompfn &optional contextfn) | 1197 | (defun python-nav--syntactically (fn poscompfn &optional contextfn) |
| 1196 | "Move point using FN avoiding places with specific context. | 1198 | "Move point using FN avoiding places with specific context. |
| 1197 | FN must take no arguments. POSCOMPFN is a two arguments function | 1199 | FN must take no arguments. POSCOMPFN is a two arguments function |
| 1198 | used to compare current and previous point after it is moved | 1200 | used to compare current and previous point after it is moved |
| 1199 | using FN, this is normally a less-than or greater-than | 1201 | using FN, this is normally a less-than or greater-than |
| 1200 | comparison. Optional argument CONTEXTFN defaults to | 1202 | comparison. Optional argument CONTEXTFN defaults to |
| @@ -3008,15 +3010,192 @@ Interactively, prompt for symbol." | |||
| 3008 | 3010 | ||
| 3009 | ;;; Imenu | 3011 | ;;; Imenu |
| 3010 | 3012 | ||
| 3011 | (defun python-imenu-prev-index-position () | 3013 | (defvar python-imenu-format-item-label-function |
| 3012 | "Python mode's `imenu-prev-index-position-function'." | 3014 | 'python-imenu-format-item-label |
| 3013 | (let ((found)) | 3015 | "Imenu function used to format an item label. |
| 3014 | (while (and (setq found | 3016 | It must be a function with two arguments: TYPE and NAME.") |
| 3015 | (re-search-backward python-nav-beginning-of-defun-regexp nil t)) | 3017 | |
| 3016 | (not (python-info-looking-at-beginning-of-defun)))) | 3018 | (defvar python-imenu-format-parent-item-label-function |
| 3017 | (and found | 3019 | 'python-imenu-format-parent-item-label |
| 3018 | (python-info-looking-at-beginning-of-defun) | 3020 | "Imenu function used to format a parent item label. |
| 3019 | (python-info-current-defun)))) | 3021 | It must be a function with two arguments: TYPE and NAME.") |
| 3022 | |||
| 3023 | (defvar python-imenu-format-parent-item-jump-label-function | ||
| 3024 | 'python-imenu-format-parent-item-jump-label | ||
| 3025 | "Imenu function used to format a parent jump item label. | ||
| 3026 | It must be a function with two arguments: TYPE and NAME.") | ||
| 3027 | |||
| 3028 | (defun python-imenu-format-item-label (type name) | ||
| 3029 | "Return imenu label for single node using TYPE and NAME." | ||
| 3030 | (format "%s (%s)" name type)) | ||
| 3031 | |||
| 3032 | (defun python-imenu-format-parent-item-label (type name) | ||
| 3033 | "Return imenu label for parent node using TYPE and NAME." | ||
| 3034 | (format "%s..." (python-imenu-format-item-label type name))) | ||
| 3035 | |||
| 3036 | (defun python-imenu-format-parent-item-jump-label (type name) | ||
| 3037 | "Return imenu label for parent node jump using TYPE and NAME." | ||
| 3038 | (if (string= type "class") | ||
| 3039 | "*class definition*" | ||
| 3040 | "*function definition*")) | ||
| 3041 | |||
| 3042 | (defun python-imenu--put-parent (type name pos num-children tree &optional root) | ||
| 3043 | "Add the parent with TYPE, NAME, POS and NUM-CHILDREN to TREE. | ||
| 3044 | Optional Argument ROOT must be non-nil when the node being | ||
| 3045 | processed is the root of the TREE." | ||
| 3046 | (let ((label | ||
| 3047 | (funcall python-imenu-format-item-label-function type name)) | ||
| 3048 | (jump-label | ||
| 3049 | (funcall python-imenu-format-parent-item-jump-label-function type name))) | ||
| 3050 | (if root | ||
| 3051 | ;; This is the root, everything is a children. | ||
| 3052 | (cons label (cons (cons jump-label pos) tree)) | ||
| 3053 | ;; This is node a which may contain some children. | ||
| 3054 | (cons | ||
| 3055 | (cons label (cons (cons jump-label pos) | ||
| 3056 | ;; Append all the children | ||
| 3057 | (python-util-popn tree num-children))) | ||
| 3058 | ;; All previous non-children nodes. | ||
| 3059 | (nthcdr num-children tree))))) | ||
| 3060 | |||
| 3061 | (defun python-imenu--build-tree (&optional min-indent prev-indent num-children tree) | ||
| 3062 | "Recursively build the tree of nested definitions of a node. | ||
| 3063 | Arguments MIN-INDENT PREV-INDENT NUM-CHILDREN and TREE are | ||
| 3064 | internal and should not be passed explicitly unless you know what | ||
| 3065 | you are doing." | ||
| 3066 | (setq num-children (or num-children 0) | ||
| 3067 | min-indent (or min-indent 0)) | ||
| 3068 | (let* ((pos (python-nav-backward-defun)) | ||
| 3069 | (type) | ||
| 3070 | (name (when (and pos (looking-at python-nav-beginning-of-defun-regexp)) | ||
| 3071 | (let ((split (split-string (match-string-no-properties 0)))) | ||
| 3072 | (setq type (car split)) | ||
| 3073 | (cadr split)))) | ||
| 3074 | (label (when name | ||
| 3075 | (funcall python-imenu-format-item-label-function type name))) | ||
| 3076 | (indent (current-indentation))) | ||
| 3077 | (cond ((not pos) | ||
| 3078 | ;; No defun found, nothing to add. | ||
| 3079 | tree) | ||
| 3080 | ((equal indent 0) | ||
| 3081 | (if (> num-children 0) | ||
| 3082 | ;; Append it as the parent of everything collected to | ||
| 3083 | ;; this point. | ||
| 3084 | (python-imenu--put-parent type name pos num-children tree t) | ||
| 3085 | ;; There are no children, this is a lonely defun. | ||
| 3086 | (cons label pos))) | ||
| 3087 | ((equal min-indent indent) | ||
| 3088 | ;; Stop collecting nodes after moving to a position with | ||
| 3089 | ;; indentation equaling min-indent. This is specially | ||
| 3090 | ;; useful for navigating nested definitions recursively. | ||
| 3091 | tree) | ||
| 3092 | (t | ||
| 3093 | (python-imenu--build-tree | ||
| 3094 | min-indent | ||
| 3095 | indent | ||
| 3096 | ;; Add another children, either when this is the | ||
| 3097 | ;; first call or when indentation is | ||
| 3098 | ;; less-or-equal than previous. And do not | ||
| 3099 | ;; discard the number of children, because the | ||
| 3100 | ;; way code is scanned, all children are | ||
| 3101 | ;; collected until a root node yet to be found | ||
| 3102 | ;; appears. | ||
| 3103 | (if (or (not prev-indent) | ||
| 3104 | (and | ||
| 3105 | (> indent min-indent) | ||
| 3106 | (<= indent prev-indent))) | ||
| 3107 | (1+ num-children) | ||
| 3108 | num-children) | ||
| 3109 | (cond ((not prev-indent) | ||
| 3110 | ;; First call to the function: append this | ||
| 3111 | ;; defun to the index. | ||
| 3112 | (list (cons label pos))) | ||
| 3113 | ((= indent prev-indent) | ||
| 3114 | ;; Add another defun with the same depth | ||
| 3115 | ;; as the previous. | ||
| 3116 | (cons (cons label pos) tree)) | ||
| 3117 | ((and (< indent prev-indent) | ||
| 3118 | (< 0 num-children)) | ||
| 3119 | ;; There are children to be appended and | ||
| 3120 | ;; the previous defun had more | ||
| 3121 | ;; indentation, the current one must be a | ||
| 3122 | ;; parent. | ||
| 3123 | (python-imenu--put-parent type name pos num-children tree)) | ||
| 3124 | ((> indent prev-indent) | ||
| 3125 | ;; There are children defuns deeper than | ||
| 3126 | ;; current depth. Fear not, we already | ||
| 3127 | ;; know how to treat them. | ||
| 3128 | (cons | ||
| 3129 | (prog1 | ||
| 3130 | (python-imenu--build-tree | ||
| 3131 | prev-indent indent 1 (list (cons label pos))) | ||
| 3132 | ;; Adjustment: after scanning backwards | ||
| 3133 | ;; for all deeper children, we need to | ||
| 3134 | ;; continue our scan for a parent from | ||
| 3135 | ;; the current defun we are looking at. | ||
| 3136 | (python-nav-forward-defun)) | ||
| 3137 | tree)))))))) | ||
| 3138 | |||
| 3139 | (defun python-imenu-create-index () | ||
| 3140 | "Return tree Imenu alist for the current python buffer. | ||
| 3141 | Change `python-imenu-format-item-label-function', | ||
| 3142 | `python-imenu-format-parent-item-label-function', | ||
| 3143 | `python-imenu-format-parent-item-jump-label-function' to | ||
| 3144 | customize how labels are formatted." | ||
| 3145 | (goto-char (point-max)) | ||
| 3146 | (let ((index) | ||
| 3147 | (tree)) | ||
| 3148 | (while (setq tree (python-imenu--build-tree)) | ||
| 3149 | (setq index (cons tree index))) | ||
| 3150 | index)) | ||
| 3151 | |||
| 3152 | (defun python-imenu-create-flat-index (&optional alist prefix) | ||
| 3153 | "Return flat outline of the current python buffer for Imenu. | ||
| 3154 | Optional Argument ALIST is the tree to be flattened, when nil | ||
| 3155 | `python-imenu-build-index' is used with | ||
| 3156 | `python-imenu-format-parent-item-jump-label-function' | ||
| 3157 | `python-imenu-format-parent-item-label-function' | ||
| 3158 | `python-imenu-format-item-label-function' set to (lambda (type | ||
| 3159 | name) name). Optional Argument PREFIX is used in recursive calls | ||
| 3160 | and should not be passed explicitly. | ||
| 3161 | |||
| 3162 | Converts this: | ||
| 3163 | |||
| 3164 | \((\"Foo\" . 103) | ||
| 3165 | (\"Bar\" . 138) | ||
| 3166 | (\"decorator\" | ||
| 3167 | (\"decorator\" . 173) | ||
| 3168 | (\"wrap\" | ||
| 3169 | (\"wrap\" . 353) | ||
| 3170 | (\"wrapped_f\" . 393)))) | ||
| 3171 | |||
| 3172 | To this: | ||
| 3173 | |||
| 3174 | \((\"Foo\" . 103) | ||
| 3175 | (\"Bar\" . 138) | ||
| 3176 | (\"decorator\" . 173) | ||
| 3177 | (\"decorator.wrap\" . 353) | ||
| 3178 | (\"decorator.wrapped_f\" . 393))" | ||
| 3179 | (apply | ||
| 3180 | 'nconc | ||
| 3181 | (mapcar | ||
| 3182 | (lambda (item) | ||
| 3183 | (let ((name (if prefix | ||
| 3184 | (concat prefix "." (car item)) | ||
| 3185 | (car item))) | ||
| 3186 | (pos (cdr item))) | ||
| 3187 | (cond ((or (numberp pos) (markerp pos)) | ||
| 3188 | (list (cons name pos))) | ||
| 3189 | ((listp pos) | ||
| 3190 | (message "%S" item) | ||
| 3191 | (cons | ||
| 3192 | (cons name (cdar pos)) | ||
| 3193 | (python-imenu-create-flat-index (cddr item) name)))))) | ||
| 3194 | (or alist | ||
| 3195 | (let ((python-imenu-format-item-label-function (lambda (type name) name)) | ||
| 3196 | (python-imenu-format-parent-item-label-function (lambda (type name) name)) | ||
| 3197 | (python-imenu-format-parent-item-jump-label-function (lambda (type name) name))) | ||
| 3198 | (python-imenu-create-index)))))) | ||
| 3020 | 3199 | ||
| 3021 | 3200 | ||
| 3022 | ;;; Misc helpers | 3201 | ;;; Misc helpers |
| @@ -3337,6 +3516,22 @@ Optional argument DIRECTION defines the direction to move to." | |||
| 3337 | (goto-char comment-start)) | 3516 | (goto-char comment-start)) |
| 3338 | (forward-comment factor))) | 3517 | (forward-comment factor))) |
| 3339 | 3518 | ||
| 3519 | (defun python-util-popn (lst n) | ||
| 3520 | "Return LST first N elements. | ||
| 3521 | N should be an integer, when it's a natural negative number its | ||
| 3522 | opposite is used. When N is bigger than the length of LST, the | ||
| 3523 | list is returned as is." | ||
| 3524 | (let* ((n (min (abs n))) | ||
| 3525 | (len (length lst)) | ||
| 3526 | (acc)) | ||
| 3527 | (if (> n len) | ||
| 3528 | lst | ||
| 3529 | (while (< 0 n) | ||
| 3530 | (setq acc (cons (car lst) acc) | ||
| 3531 | lst (cdr lst) | ||
| 3532 | n (1- n))) | ||
| 3533 | (reverse acc)))) | ||
| 3534 | |||
| 3340 | 3535 | ||
| 3341 | ;;;###autoload | 3536 | ;;;###autoload |
| 3342 | (define-derived-mode python-mode prog-mode "Python" | 3537 | (define-derived-mode python-mode prog-mode "Python" |
| @@ -3382,11 +3577,8 @@ if that value is non-nil." | |||
| 3382 | (add-hook 'post-self-insert-hook | 3577 | (add-hook 'post-self-insert-hook |
| 3383 | 'python-indent-post-self-insert-function nil 'local) | 3578 | 'python-indent-post-self-insert-function nil 'local) |
| 3384 | 3579 | ||
| 3385 | (set (make-local-variable 'imenu-extract-index-name-function) | 3580 | (set (make-local-variable 'imenu-create-index-function) |
| 3386 | #'python-info-current-defun) | 3581 | #'python-imenu-create-index) |
| 3387 | |||
| 3388 | (set (make-local-variable 'imenu-prev-index-position-function) | ||
| 3389 | #'python-imenu-prev-index-position) | ||
| 3390 | 3582 | ||
| 3391 | (set (make-local-variable 'add-log-current-defun-function) | 3583 | (set (make-local-variable 'add-log-current-defun-function) |
| 3392 | #'python-info-current-defun) | 3584 | #'python-info-current-defun) |
diff --git a/test/ChangeLog b/test/ChangeLog index c8cb8ee3b54..0c240394c5c 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | 2013-04-19 Fabián Ezequiel Gallina <fgallina@gnu.org> | ||
| 2 | |||
| 3 | * automated/python-tests.el (python-imenu-prev-index-position-1): | ||
| 4 | Removed test. | ||
| 5 | (python-imenu-create-index-1, python-imenu-create-flat-index-1): | ||
| 6 | New tests. | ||
| 7 | |||
| 1 | 2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org> | 8 | 2013-04-17 Fabián Ezequiel Gallina <fgallina@gnu.org> |
| 2 | 9 | ||
| 3 | * automated/python-tests.el (python-nav-backward-defun-2) | 10 | * automated/python-tests.el (python-nav-backward-defun-2) |
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index 15089e6b393..8462a863b84 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el | |||
| @@ -1673,66 +1673,133 @@ Using `python-shell-interpreter' and | |||
| 1673 | 1673 | ||
| 1674 | 1674 | ||
| 1675 | ;;; Imenu | 1675 | ;;; Imenu |
| 1676 | (ert-deftest python-imenu-prev-index-position-1 () | 1676 | |
| 1677 | (require 'imenu) | 1677 | (ert-deftest python-imenu-create-index-1 () |
| 1678 | (python-tests-with-temp-buffer | 1678 | (python-tests-with-temp-buffer |
| 1679 | " | 1679 | " |
| 1680 | def decoratorFunctionWithArguments(arg1, arg2, arg3): | 1680 | class Foo(models.Model): |
| 1681 | pass | ||
| 1682 | |||
| 1683 | |||
| 1684 | class Bar(models.Model): | ||
| 1685 | pass | ||
| 1686 | |||
| 1687 | |||
| 1688 | def decorator(arg1, arg2, arg3): | ||
| 1681 | '''print decorated function call data to stdout. | 1689 | '''print decorated function call data to stdout. |
| 1682 | 1690 | ||
| 1683 | Usage: | 1691 | Usage: |
| 1684 | 1692 | ||
| 1685 | @decoratorFunctionWithArguments('arg1', 'arg2') | 1693 | @decorator('arg1', 'arg2') |
| 1686 | def func(a, b, c=True): | 1694 | def func(a, b, c=True): |
| 1687 | pass | 1695 | pass |
| 1688 | ''' | 1696 | ''' |
| 1689 | 1697 | ||
| 1690 | def wwrap(f): | 1698 | def wrap(f): |
| 1691 | print 'Inside wwrap()' | 1699 | print ('wrap') |
| 1692 | def wrapped_f(*args): | 1700 | def wrapped_f(*args): |
| 1693 | print 'Inside wrapped_f()' | 1701 | print ('wrapped_f') |
| 1694 | print 'Decorator arguments:', arg1, arg2, arg3 | 1702 | print ('Decorator arguments:', arg1, arg2, arg3) |
| 1695 | f(*args) | 1703 | f(*args) |
| 1696 | print 'After f(*args)' | 1704 | print ('called f(*args)') |
| 1697 | return wrapped_f | 1705 | return wrapped_f |
| 1698 | return wwrap | 1706 | return wrap |
| 1699 | 1707 | ||
| 1700 | def test(): # Some comment | ||
| 1701 | 'This is a test function' | ||
| 1702 | print 'test' | ||
| 1703 | 1708 | ||
| 1704 | class C(object): | 1709 | class Baz(object): |
| 1705 | 1710 | ||
| 1706 | def m(self): | 1711 | def a(self): |
| 1707 | self.c() | 1712 | pass |
| 1708 | 1713 | ||
| 1709 | def b(): | 1714 | def b(self): |
| 1710 | pass | 1715 | pass |
| 1711 | 1716 | ||
| 1712 | def a(): | 1717 | class Frob(object): |
| 1718 | |||
| 1719 | def c(self): | ||
| 1713 | pass | 1720 | pass |
| 1721 | " | ||
| 1722 | (goto-char (point-max)) | ||
| 1723 | (should (equal | ||
| 1724 | (list | ||
| 1725 | (cons "Foo (class)" (copy-marker 2)) | ||
| 1726 | (cons "Bar (class)" (copy-marker 38)) | ||
| 1727 | (list | ||
| 1728 | "decorator (def)" | ||
| 1729 | (cons "*function definition*" (copy-marker 74)) | ||
| 1730 | (list | ||
| 1731 | "wrap (def)" | ||
| 1732 | (cons "*function definition*" (copy-marker 254)) | ||
| 1733 | (cons "wrapped_f (def)" (copy-marker 294)))) | ||
| 1734 | (list | ||
| 1735 | "Baz (class)" | ||
| 1736 | (cons "*class definition*" (copy-marker 519)) | ||
| 1737 | (cons "a (def)" (copy-marker 539)) | ||
| 1738 | (cons "b (def)" (copy-marker 570)) | ||
| 1739 | (list | ||
| 1740 | "Frob (class)" | ||
| 1741 | (cons "*class definition*" (copy-marker 601)) | ||
| 1742 | (cons "c (def)" (copy-marker 626))))) | ||
| 1743 | (python-imenu-create-index))))) | ||
| 1744 | |||
| 1745 | (ert-deftest python-imenu-create-flat-index-1 () | ||
| 1746 | (python-tests-with-temp-buffer | ||
| 1747 | " | ||
| 1748 | class Foo(models.Model): | ||
| 1749 | pass | ||
| 1714 | 1750 | ||
| 1715 | def c(self): | 1751 | |
| 1752 | class Bar(models.Model): | ||
| 1753 | pass | ||
| 1754 | |||
| 1755 | |||
| 1756 | def decorator(arg1, arg2, arg3): | ||
| 1757 | '''print decorated function call data to stdout. | ||
| 1758 | |||
| 1759 | Usage: | ||
| 1760 | |||
| 1761 | @decorator('arg1', 'arg2') | ||
| 1762 | def func(a, b, c=True): | ||
| 1763 | pass | ||
| 1764 | ''' | ||
| 1765 | |||
| 1766 | def wrap(f): | ||
| 1767 | print ('wrap') | ||
| 1768 | def wrapped_f(*args): | ||
| 1769 | print ('wrapped_f') | ||
| 1770 | print ('Decorator arguments:', arg1, arg2, arg3) | ||
| 1771 | f(*args) | ||
| 1772 | print ('called f(*args)') | ||
| 1773 | return wrapped_f | ||
| 1774 | return wrap | ||
| 1775 | |||
| 1776 | |||
| 1777 | class Baz(object): | ||
| 1778 | |||
| 1779 | def a(self): | ||
| 1780 | pass | ||
| 1781 | |||
| 1782 | def b(self): | ||
| 1716 | pass | 1783 | pass |
| 1784 | |||
| 1785 | class Frob(object): | ||
| 1786 | |||
| 1787 | def c(self): | ||
| 1788 | pass | ||
| 1717 | " | 1789 | " |
| 1718 | (let ((expected | 1790 | (goto-char (point-max)) |
| 1719 | '(("*Rescan*" . -99) | 1791 | (should (equal |
| 1720 | ("decoratorFunctionWithArguments" . 2) | 1792 | (list (cons "Foo" (copy-marker 2)) |
| 1721 | ("decoratorFunctionWithArguments.wwrap" . 224) | 1793 | (cons "Bar" (copy-marker 38)) |
| 1722 | ("decoratorFunctionWithArguments.wwrap.wrapped_f" . 273) | 1794 | (cons "decorator" (copy-marker 74)) |
| 1723 | ("test" . 500) | 1795 | (cons "decorator.wrap" (copy-marker 254)) |
| 1724 | ("C" . 575) | 1796 | (cons "decorator.wrap.wrapped_f" (copy-marker 294)) |
| 1725 | ("C.m" . 593) | 1797 | (cons "Baz" (copy-marker 519)) |
| 1726 | ("C.m.b" . 628) | 1798 | (cons "Baz.a" (copy-marker 539)) |
| 1727 | ("C.m.a" . 663) | 1799 | (cons "Baz.b" (copy-marker 570)) |
| 1728 | ("C.c" . 698)))) | 1800 | (cons "Baz.Frob" (copy-marker 601)) |
| 1729 | (mapc | 1801 | (cons "Baz.Frob.c" (copy-marker 626))) |
| 1730 | (lambda (elt) | 1802 | (python-imenu-create-flat-index))))) |
| 1731 | (should (= (cdr (assoc-string (car elt) expected)) | ||
| 1732 | (if (markerp (cdr elt)) | ||
| 1733 | (marker-position (cdr elt)) | ||
| 1734 | (cdr elt))))) | ||
| 1735 | (imenu--make-index-alist))))) | ||
| 1736 | 1803 | ||
| 1737 | 1804 | ||
| 1738 | ;;; Misc helpers | 1805 | ;;; Misc helpers |