0
|
1 ;;!emacs
|
|
2 ;;
|
|
3 ;; FILE: br-python.el
|
|
4 ;; SUMMARY: Support routines for Python inheritance browsing.
|
|
5 ;; USAGE: GNU Emacs Lisp Library
|
|
6 ;; KEYWORDS: oop, tools, python
|
|
7 ;;
|
|
8 ;; AUTHOR: Harri Pasanen, based on Smalltalk and C++ browsers
|
|
9 ;; by Bob Weiner
|
|
10 ;; ORG: Tekla Oy
|
|
11 ;;
|
|
12 ;; ORIG-DATE: 5-Apr-96
|
|
13 ;; LAST-MOD: 12-Apr
|
|
14 ;;
|
|
15 ;; Copyright (C) 1990-1995 Free Software Foundation, Inc.
|
|
16 ;; See the file BR-COPY for license information.
|
|
17 ;;
|
|
18 ;; This file is part of the OO-Browser.
|
|
19 ;;
|
|
20 ;; DESCRIPTION:
|
|
21 ;;
|
|
22 ;; See 'python-class-def-regexp' for regular expression that matches class
|
|
23 ;; definitions.
|
|
24 ;;
|
|
25 ;; DESCRIP-END.
|
|
26
|
|
27 ;;; ************************************************************************
|
|
28 ;;; Other required Elisp libraries
|
|
29 ;;; ************************************************************************
|
|
30
|
|
31 (mapcar 'require '(br-lib hypb))
|
|
32
|
|
33 ;;; ************************************************************************
|
|
34 ;;; User visible variables
|
|
35 ;;; ************************************************************************
|
|
36
|
|
37 (defvar python-lib-search-dirs nil
|
|
38 "List of directories below which Python Library source files are found.
|
|
39 Subdirectories of Library source are also searched. A Library is a stable
|
|
40 group of classes.")
|
|
41
|
|
42 (defvar python-sys-search-dirs nil
|
|
43 "List of directories below which Python System source files are found.
|
|
44 Subdirectories of System source are also searched. A System class is one
|
|
45 that is not yet reusable and is likely to change before release.")
|
|
46
|
|
47 (defconst python-narrow-view-to-class nil
|
|
48 "*Non-nil means narrow buffer to just the matching class definition when displayed.")
|
|
49
|
|
50 ;;; following is reserved for future, currently does not work
|
|
51 (defconst python-duplicate-classnames-across-modules nil
|
|
52 "*Non-nil means that the module name is prepended to class names.")
|
|
53
|
|
54 ;;; ************************************************************************
|
|
55 ;;; Internal functions
|
|
56 ;;; ************************************************************************
|
|
57
|
|
58 (defun python-get-classes-from-source (filename &optional skip-tags
|
|
59 skip-tags-cleanup)
|
|
60 "Scans FILENAME and returns cons of class list with parents-class alist.
|
|
61 Handles multiple inheritance. Assumes file existence and readability have
|
|
62 already been checked."
|
|
63 (let ((no-kill (get-file-buffer filename))
|
|
64 classes class parents parent-cons)
|
|
65 (if no-kill
|
|
66 (set-buffer no-kill)
|
|
67 (funcall br-view-file-function filename))
|
|
68 (save-restriction
|
|
69 (save-excursion
|
|
70 (widen)
|
|
71 (goto-char (point-min))
|
|
72 (or skip-tags
|
|
73 (progn (setq signatures (python-scan-features))
|
|
74 (goto-char (point-min))))
|
|
75 (while (re-search-forward python-class-def-regexp nil t)
|
|
76 (setq has-parents
|
|
77 (= ?\( (char-after (point))))
|
|
78 (setq class (buffer-substring (match-beginning 1) (match-end 1))
|
|
79 parent-cons
|
|
80 (cons
|
|
81 ;; Return parents as a list, or nil if no parents
|
|
82 (if has-parents (python-scan-parents))
|
|
83 class))
|
|
84 ;; Assume class name not found within a comment.
|
|
85 (setq classes (cons class classes)
|
|
86 parents (cons parent-cons parents))
|
|
87 (or skip-tags
|
|
88 ;; Scan members defined within class
|
|
89 (setq signatures
|
|
90 (append
|
|
91 signatures
|
|
92 (python-scan-features-in-class class (point)
|
|
93 (python-locate-class-end))
|
|
94 )))))
|
|
95 (if skip-tags
|
|
96 nil
|
|
97 (python-get-feature-tags buffer-file-name (python-sort-features
|
|
98 signatures))
|
|
99 (or skip-tags-cleanup (br-feature-tags-save)))
|
|
100 (or no-kill (kill-buffer (current-buffer)))
|
|
101 (cons classes (delq nil parents)))))
|
|
102
|
|
103
|
|
104 (defun python-scan-parents ()
|
|
105 "Return list of parents names from a Python class definition.
|
|
106 Point must be after the '(' that begins the parent list and before the
|
|
107 first parent entry when this function is called."
|
|
108 (let ((parent-list) (again t)
|
|
109 parent)
|
|
110 (while (and again (re-search-forward python-parent-class-name nil t))
|
|
111 (setq again (= ?, (char-after (point)))
|
|
112 parent (buffer-substring (match-beginning 3)
|
|
113 (match-end 3))
|
|
114 parent-list (cons parent parent-list)))
|
|
115 (nreverse parent-list)))
|
|
116
|
|
117 (defun python-locate-class-end ()
|
|
118 "Look up the end of class. Point is assumed to be in the class definition.
|
|
119 Do this by looking up the first line that begins with python-identifier-chars."
|
|
120 (save-excursion
|
|
121 (let ((result-point (point-max)))
|
|
122 (if (re-search-forward
|
|
123 (concat "^[" python-identifier-chars "]") nil t)
|
|
124 (progn
|
|
125 (setq result-point (- (match-beginning 0) 1))
|
|
126 (if (python-within-string-p)
|
|
127 (python-locate-class-end)
|
|
128 result-point))
|
|
129 result-point))))
|
|
130
|
|
131 (defun python-get-parents-from-source (filename class-name)
|
|
132 "Scan source in FILENAME and return list of parents of CLASS-NAME.
|
|
133 Assume file existence has already been checked."
|
|
134 (or (null class-name)
|
|
135 (car (car (br-rassoc
|
|
136 class-name
|
|
137 (cdr (python-get-classes-from-source filename)))))))
|
|
138
|
|
139 (defun python-select-path (paths-htable-elt &optional feature-p)
|
|
140 "Select proper pathname from PATHS-HTABLE-ELT based upon value of optional FEATURE-P.
|
|
141 Selection is between path of class definition and path for features associated
|
|
142 with the class."
|
|
143 (cdr paths-htable-elt))
|
|
144
|
|
145 (defun python-set-case (type)
|
|
146 "Return string TYPE identifier for use as a class name."
|
|
147 type)
|
|
148
|
|
149 (defun python-set-case-type (class-name)
|
|
150 "Return string CLASS-NAME for use as a type identifier."
|
|
151 class-name)
|
|
152
|
|
153 (defun python-to-comments-begin ()
|
|
154 "Skip back from current point past any preceding Python comments.
|
|
155 Presently NoOp"
|
|
156 )
|
|
157
|
|
158 (defun python-class-definition-regexp (class &optional regexp-flag)
|
|
159 "Return regexp to uniquely match the definition of CLASS name.
|
|
160 Optional REGEXP-FLAG non-nil means CLASS has already been quoted for use in a
|
|
161 regular expression. (not meaningful for Python)"
|
|
162 (concat python-class-name-before class whitespace))
|
|
163
|
|
164 ;;; ************************************************************************
|
|
165 ;;; Internal variables
|
|
166 ;;; ************************************************************************
|
|
167
|
|
168 (defconst python-type-tag-separator "@"
|
|
169 "String that separates a tag's type from its normalized definition form.
|
|
170 This should be a single character which is unchanged when quoted for use as a
|
|
171 literal in a regular expression.")
|
|
172
|
|
173 (defconst python-identifier-chars "a-zA-Z0-9_"
|
|
174 "String of chars and char ranges that may be used within a Python identifier.")
|
|
175
|
|
176 (defconst python-identifier (concat "\\([a-zA-Z_][" python-identifier-chars "]*\\)")
|
|
177 "Regular expression matching a Python identifier.")
|
|
178
|
|
179 (defconst whitespace "[ \t]*")
|
|
180
|
|
181 (defconst python-parent-class-name
|
|
182 (concat whitespace
|
|
183 "\\(" python-identifier "\\.\\)*" ; possible module name precedes
|
|
184 python-identifier whitespace)
|
|
185 "Regular expression matching optional Python parent class")
|
|
186
|
|
187 (defconst python-class-name-before "^class[ \t]+"
|
|
188 "Regexp preceding the class name in a class definition.
|
|
189 Note: this does not allow for nested classes.")
|
|
190
|
|
191 (defconst python-class-name-after
|
|
192 (concat whitespace python-parent-class-name whitespace ":")
|
|
193 "Regexp following the class name in a class definition.")
|
|
194
|
|
195 (defconst python-class-def-regexp
|
|
196 (concat python-class-name-before python-identifier whitespace)
|
|
197 ; (concat python-class-name-before python-identifier python-class-name-after)
|
|
198 "Regular expression used to match to class definitions in source text.
|
|
199 Class name identifier is grouped expression 1. Parent identifier is grouped
|
|
200 expression 2.")
|
|
201
|
|
202
|
|
203 (defconst python-lang-prefix "python-"
|
|
204 "Prefix string that starts \"br-python.el\" symbol names.")
|
|
205
|
|
206 (defconst python-src-file-regexp ".\\.py$"
|
|
207 "Regular expression matching a unique part of Python source file name and no others.")
|
|
208
|
|
209 (defvar python-children-htable nil
|
|
210 "Htable whose elements are of the form: (LIST-OF-CHILD-CLASSES . CLASS-NAME).
|
|
211 Used to traverse Python inheritance graph. 'br-build-children-htable' builds
|
|
212 this list.")
|
|
213 (defvar python-parents-htable nil
|
|
214 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
|
|
215 Used to traverse Python inheritance graph. 'br-build-parents-htable' builds
|
|
216 this list.")
|
|
217 (defvar python-paths-htable nil
|
|
218 "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
|
|
219 FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
|
|
220 'br-build-paths-htable' builds this list.")
|
|
221
|
|
222
|
|
223 (defvar python-lib-parents-htable nil
|
|
224 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
|
|
225 Only classes from stable software libraries are used to build the list.")
|
|
226 (defvar python-lib-paths-htable nil
|
|
227 "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
|
|
228 FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
|
|
229 Only classes from stable software libraries are used to build the list.")
|
|
230
|
|
231 (defvar python-sys-parents-htable nil
|
|
232 "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
|
|
233 Only classes from systems that are likely to change are used to build the list.")
|
|
234 (defvar python-sys-paths-htable nil
|
|
235 "Alist whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
|
|
236 FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
|
|
237 Only classes from systems that are likely to change are used to build the
|
|
238 list.")
|
|
239
|
|
240 (defvar python-lib-prev-search-dirs nil
|
|
241 "Used to check if 'python-lib-classes-htable' must be regenerated.")
|
|
242 (defvar python-sys-prev-search-dirs nil
|
|
243 "Used to check if 'python-sys-classes-htable' must be regenerated.")
|
|
244
|
|
245 (defvar python-env-spec nil
|
|
246 "Non-nil value means Environment specification has been given but not yet built.
|
|
247 Nil means current Environment has been built, though it may still require updating.")
|
|
248
|
|
249 (provide 'br-python)
|
|
250
|
|
251
|
|
252
|
|
253
|
|
254
|
|
255
|