comparison lisp/oobr/br-java-ft.el @ 24:4103f0995bd7 r19-15b95

Import from CVS: tag r19-15b95
author cvs
date Mon, 13 Aug 2007 08:51:03 +0200
parents 376386a54a3c
children 131b0175ea99
comparison
equal deleted inserted replaced
23:0edd3412f124 24:4103f0995bd7
1 ;;!emacs 1 ;;!emacs
2 ;; 2 ;;
3 ;; FILE: br-java-ft.el 3 ;; FILE: br-java-ft.el
4 ;; SUMMARY: Java OO-Browser class and member functions. 4 ;; SUMMARY: Java OO-Browser class and member functions.
5 ;; USAGE: GNU Emacs Lisp Library 5 ;; USAGE: GNU Emacs Lisp Library
6 ;; KEYWORDS: java, oop, tools 6 ;; KEYWORDS: c, oop, tools
7 ;; 7 ;;
8 ;; AUTHOR: Bob Weiner 8 ;; AUTHOR: Bob Weiner
9 ;; ORG: Motorola Inc. 9 ;; ORG: InfoDock Associates
10 ;; 10 ;;
11 ;; ORIG-DATE: 01-Aug-95 11 ;; ORIG-DATE: 01-Aug-95
12 ;; LAST-MOD: 4-Oct-95 at 13:41:34 by Bob Weiner 12 ;; LAST-MOD: 13-Nov-96 at 00:08:46 by Bob Weiner
13 ;; 13 ;;
14 ;; Copyright (C) 1995 Free Software Foundation, Inc. 14 ;; Copyright (C) 1995, 1996 Free Software Foundation, Inc.
15 ;; See the file BR-COPY for license information. 15 ;; See the file BR-COPY for license information.
16 ;; 16 ;;
17 ;; This file is part of the OO-Browser. 17 ;; This file is part of the OO-Browser.
18 ;; 18 ;;
19 ;; DESCRIPTION: 19 ;; DESCRIPTION:
27 27
28 ;;; ************************************************************************ 28 ;;; ************************************************************************
29 ;;; Public variables 29 ;;; Public variables
30 ;;; ************************************************************************ 30 ;;; ************************************************************************
31 31
32 (defvar java-cpp-include-dirs '("/usr/include/")
33 "*Ordered list of include directories by default searched by C preprocessor.
34 Each directory must end with a directory separator. See also
35 'java-include-dirs'.")
36
37 (defvar java-include-dirs nil
38 "*Ordered list of directories to search for java include files.
39 Each directory must end with a directory separator. Directories normally
40 searched by the java pre-processor should be set instead in
41 'java-cpp-include-dirs'.")
42
43 (defconst java-return-type-identifier 32 (defconst java-return-type-identifier
44 (concat "\\([\[a-zA-Z]" 33 (concat "\\([\[a-zA-Z][][" java-return-type-chars "]*"
45 "\\|[\[a-zA-Z][]" java-return-type-chars "]*" 34 "[][" java-return-type-chars "]+\\|[\[a-zA-Z]\\)"
46 "[]" java-return-type-chars "]+\\)"
47 "[ \t\n\^M]*")) 35 "[ \t\n\^M]*"))
48 36
49 (defconst java-type-identifier 37 (defconst java-type-identifier
50 (concat "\\([\[a-zA-Z][]" java-identifier-chars "]*[ \t\n\^M]+\\)")) 38 (concat "\\([\[a-zA-Z][][" java-identifier-chars "]*[ \t\n\^M]+\\)"))
51 39
52 (defconst java-type-tag-separator "@" 40 (defconst java-type-tag-separator "@"
53 "String that separates a tag's type from its normalized definition form. 41 "String that separates a tag's type from its normalized definition form.
54 This should be a single character which is unchanged when quoted for use as a 42 This should be a single character which is unchanged when quoted for use as a
55 literal in a regular expression.") 43 literal in a regular expression.")
56 44
57 (defconst java-tag-fields-regexp 45 (defconst java-tag-fields-regexp
58 ;; The \\\\? below is necessary because we sometimes use this expression to 46 ;; The \\\\? below is necessary because we sometimes use this expression to
59 ;; test against a string that has been regexp-quoted and some of the 47 ;; test against a string that has been regexp-quoted and some of the
60 ;; characters in br-feature-type-regexp will then be preceded by \\. 48 ;; characters in br-feature-type-regexp will then be preceded by \\.
61 (format "\\`\\([^%s \n]+\\)%s\\\\?\\(%s \\)\\([^%s\n]+\\)%s" 49 (format "\\`\\([^%s \n]+\\)%s\\\\?\\(%s \\)\\([^%s\n]+\\)%s?"
62 java-type-tag-separator java-type-tag-separator 50 java-type-tag-separator java-type-tag-separator
63 br-feature-type-regexp java-type-tag-separator 51 br-feature-type-regexp java-type-tag-separator
64 java-type-tag-separator) 52 java-type-tag-separator)
65 "Regexp matching the fields of a java feature tag line. 53 "Regexp matching the fields of a java feature tag line.
66 Group 1 is the class of the feature. Group 2 is the prefix preceding the 54 Group 1 is the class of the feature. Group 2 is the prefix preceding the
110 of desired search start. 98 of desired search start.
111 Optional REGEXP-FLAG means FEATURE-TAG is a regular expression." 99 Optional REGEXP-FLAG means FEATURE-TAG is a regular expression."
112 ;; Match to function definitions, not declarations, except for abstract 100 ;; Match to function definitions, not declarations, except for abstract
113 ;; methods which are declared, not defined, and so end with a ';'. 101 ;; methods which are declared, not defined, and so end with a ';'.
114 ;; 102 ;;
115 ;; First move to the proper class implementation if feature-tag does not 103 ;; First move to the proper class implementation if this is not a
116 ;; include a <class>:: part and this is not a [default-class], so that if 104 ;; [default-class], so that if two classes in the same file have the same
117 ;; two classes in the same file have the same feature signature, we still 105 ;; feature signature, we still end up at the right one.
118 ;; end up at the right one. 106 (let ((found t) (start))
119 (if (string-match java-tag-fields-regexp feature-tag) 107 (if (string-match java-tag-fields-regexp feature-tag)
120 (let ((class (substring feature-tag (match-beginning 1) (match-end 1)))) 108 (let ((class (substring feature-tag (match-beginning 1) (match-end 1))))
121 (setq feature-tag (substring feature-tag (match-end 0))) 109 (setq feature-tag (substring feature-tag (match-end 0))
122 (if regexp-flag 110 found (re-search-forward
123 (if (not (string-match "\\`\\\\\\[\\|::" feature-tag)) 111 (java-class-definition-regexp class regexp-flag) nil t))))
124 (re-search-forward (java-class-definition-regexp class t) 112
125 nil t)) 113 ;; If class was searched for and not found, return nil.
126 (if (not (string-match "\\`\\[\\|::" feature-tag)) 114 (if (not found)
127 (re-search-forward (java-class-definition-regexp class) 115 nil
128 nil t))))) 116 ;; Otherwise, look for feature expression.
129 ;; Now look for feature expression. 117 (or regexp-flag (setq feature-tag
130 (let ((found) (start)) 118 (java-feature-signature-to-regexp feature-tag)))
131 (or regexp-flag (setq feature-tag 119 (while (and (re-search-forward feature-tag nil t)
132 (java-feature-signature-to-regexp feature-tag))) 120 (setq start (match-beginning 0))
133 (while (and (re-search-forward feature-tag nil t) 121 (not (setq found (not
134 (setq start (match-beginning 0)) 122 (if (c-within-comment-p)
135 (not (setq found (not 123 (progn (search-forward "*/" nil t)
136 (if (c-within-comment-p) 124 t)))))))
137 (progn (search-forward "*/" nil t) 125 (if found
138 t))))))) 126 (progn (goto-char start)
139 (if found 127 (skip-chars-forward " \t\n\^M")
140 (progn (goto-char start) 128 (java-to-comments-begin)
141 (skip-chars-forward " \t\n") 129 (recenter 0)
142 (java-to-comments-begin) 130 (goto-char start)
143 (recenter 0) 131 t)))))
144 (goto-char start) 132
145 t)))) 133 (defun java-feature-map-class-tags (function class)
134 "Apply FUNCTION to all feature tags from CLASS and return a list of the results.
135 Feature tags come from the file named by br-feature-tags-file."
136 (let ((obuf (current-buffer))
137 (class-tag (concat "\n" class java-type-tag-separator))
138 (results)
139 start end)
140 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file))
141 (goto-char 1)
142 (if (not (search-forward class-tag nil t))
143 nil
144 (setq start (match-beginning 0)
145 end (if (search-forward "\^L\n" nil t)
146 (match-beginning 0)
147 (point-max)))
148 (goto-char start)
149 ;; Feature defs can occur only within a single file.
150 (while (search-forward class-tag end t)
151 (setq results (cons (funcall function) results))
152 ;; Might have deleted current tag and would miss next tag unless point
153 ;; is moved backwards.
154 (backward-char)))
155 (set-buffer obuf)
156 results))
146 157
147 (defun java-feature-name-to-regexp (name) 158 (defun java-feature-name-to-regexp (name)
148 "Converts routine NAME into a regular expression matching the routine's name tag." 159 "Converts routine NAME into a regular expression matching the routine's name tag."
149 (setq name (java-feature-signature-to-regexp name)) 160 (java-feature-signature-to-regexp name))
150 (aset name (1- (length name)) ?\() ;; Match only to functions
151 name)
152 161
153 (defun java-feature-signature-to-name (signature &optional with-class for-display) 162 (defun java-feature-signature-to-name (signature &optional with-class for-display)
154 "Extracts the feature name from SIGNATURE. 163 "Extracts the feature name from SIGNATURE.
155 The feature's class name is dropped from signature unless optional WITH-CLASS 164 The feature's class name is dropped from signature unless optional WITH-CLASS
156 is non-nil. If optional FOR-DISPLAY is non-nil, a feature type character is 165 is non-nil. If optional FOR-DISPLAY is non-nil, a feature type character is
162 (setq name (substring signature (match-beginning (if for-display 2 3)) 171 (setq name (substring signature (match-beginning (if for-display 2 3))
163 (match-end 3))) 172 (match-end 3)))
164 (if with-class 173 (if with-class
165 (setq name (concat 174 (setq name (concat
166 (substring signature (match-beginning 1) (match-end 1)) 175 (substring signature (match-beginning 1) (match-end 1))
167 "." name))) 176 java-type-tag-separator name)))
168 ;; Remove any trailing whitespace. 177 ;; Remove any trailing whitespace.
169 (br-delete-space name)) 178 (br-delete-space name))
170 ;; 179 ;;
171 ;; unknown 180 ;; unknown
172 (t ;; Remove any trailing whitespace and add display prefix. 181 (t ;; Remove any trailing whitespace and add display prefix.
191 (t 200 (t
192 (concat pat (char-to-string c)))) 201 (concat pat (char-to-string c))))
193 i (1+ i))) 202 i (1+ i)))
194 (setq pat (concat prefix-info pat))))) 203 (setq pat (concat prefix-info pat)))))
195 204
205 (defun java-feature-tag-regexp (class feature-name)
206 "Return a regexp that matches to the feature tag entry for CLASS' FEATURE-NAME."
207 (concat "^" (regexp-quote class) java-type-tag-separator
208 br-feature-type-regexp " "
209 (regexp-quote feature-name) java-type-tag-separator))
210
196 (defun java-feature-tree-command-p (class-or-signature) 211 (defun java-feature-tree-command-p (class-or-signature)
197 "Display definition of CLASS-OR-SIGNATURE if a signature and return t, else return nil." 212 "Display definition of CLASS-OR-SIGNATURE if a signature and return t, else return nil."
198 (if (java-routine-p class-or-signature) 213 ;; A class name won't contain a space.
214 (if (string-match " " class-or-signature)
199 (progn 215 (progn
200 (if (br-in-browser) (br-to-view-window)) 216 (if (br-in-browser) (br-to-view-window))
201 (br-feature-found-p (br-feature-file class-or-signature) 217 (br-feature-found-p (br-feature-file class-or-signature)
202 class-or-signature)))) 218 class-or-signature))))
203 219
204 (defun java-list-features (class &optional indent) 220 (defun java-list-features (class &optional indent)
205 "Return sorted list of java feature tags lexically defined in CLASS." 221 "Return sorted list of Java feature tags lexically defined in CLASS.
206 (let ((obuf (current-buffer)) 222 Optional INDENT is unused but is required for multi-language OO-Browser conformance."
207 (features) 223 ;; Use nreverse here so that stable sort ends up leaving same named
208 (class-tag (concat "\n" class java-type-tag-separator)) 224 ;; features in the order they were defined in the source file.
209 feature) 225 (java-sort-features
210 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file)) 226 (nreverse (java-feature-map-class-tags 'br-feature-current class))))
211 (goto-char 1) 227
212 (if (or (null indent) (<= indent 2)) 228 (defun java-sort-features (feature-list)
213 ;; Include all features. 229 (sort feature-list 'java-feature-lessp))
214 (while (search-forward class-tag nil t)
215 (setq features (cons (br-feature-current) features)))
216 (while (search-forward class-tag nil t)
217 (setq feature (br-feature-current))
218 (setq features (cons feature features))))
219 (set-buffer obuf)
220 (java-sort-features (nreverse features))))
221
222 (defun java-routine-p (str)
223 (string-match "([^\)]*)" str))
224
225 (defun java-sort-features (routine-list)
226 (sort routine-list 'java-feature-lessp))
227 230
228 (defun java-to-definition (&optional other-win) 231 (defun java-to-definition (&optional other-win)
229 "If point is within a declaration, try to move to its definition. 232 "If point is within a declaration, try to move to its definition.
230 With OTHER-WIN non-nil, show it in another window." 233 With OTHER-WIN non-nil, show it in another window."
231 (interactive) 234 (interactive)
232 (let ((opoint (point))) 235 (let ((opoint (point)))
233 (cond 236 (cond
234 ((java-include-file other-win))
235 ((br-check-for-class (java-class-decl-p) other-win)) 237 ((br-check-for-class (java-class-decl-p) other-win))
236 ((java-feature other-win)) 238 ((java-feature other-win))
237 ((and (goto-char opoint) 239 ((and (goto-char opoint)
238 (br-check-for-class (java-find-class-name) other-win))) 240 (br-check-for-class (java-find-class-name) other-win)))
239 (t (beep) 241 (t (beep)
263 class)))) 265 class))))
264 266
265 (defun java-feature (&optional other-win) 267 (defun java-feature (&optional other-win)
266 "Move point to definition of member given by declaration at point. 268 "Move point to definition of member given by declaration at point.
267 Return nil if point is not within a member declaration." 269 Return nil if point is not within a member declaration."
268 ;; If '{' follows the feature declaration, then feature is defined right
269 ;; here, within the class definition.
270 (interactive) 270 (interactive)
271 (let ((feature-def) (ftr) (class) (ftr-pat)) 271 (let ((feature-def) (ftr) (class) (ftr-pat))
272 (cond ((java-feature-def-p) 272 (cond ((java-feature-def-p)
273 (recenter 0) 273 (recenter 0)
274 t) 274 t)
275 ;; Now look for feature definition in code (non-header) files. 275 ;; Now look for feature definition in ancestor classes.
276 ((progn (setq feature-def (java-feature-def-pat) 276 ((progn (setq feature-def (java-feature-def-pat)
277 ftr (car (cdr (cdr feature-def))) 277 ftr (car (cdr (cdr feature-def)))
278 class (car (cdr feature-def)) 278 class (car (cdr feature-def))
279 ftr-pat (car feature-def)) 279 ftr-pat (car feature-def))
280 (java-locate-feature ftr class ftr-pat other-win))) 280 (java-locate-feature ftr class ftr-pat other-win)))
287 "Add a browser listing display prefix to FEATURE-NAME from CLASS based on feature's SIGNATURE." 287 "Add a browser listing display prefix to FEATURE-NAME from CLASS based on feature's SIGNATURE."
288 (concat (cond ((string-match java-native-method-regexp signature) 288 (concat (cond ((string-match java-native-method-regexp signature)
289 "/ ") 289 "/ ")
290 ((string-match java-abstract-method-regexp signature) 290 ((string-match java-abstract-method-regexp signature)
291 "> ") 291 "> ")
292 ;; constructors and destructors
292 ((or (string-equal feature-name class) 293 ((or (string-equal feature-name class)
293 (string-equal feature-name "finalize")) 294 (string-equal feature-name "finalize"))
294 "+ ") 295 "+ ")
296 ;; attributes
297 ((string-match "[=;,]\\'" signature)
298 "= ")
299 ;; regular methods
295 (t "- ")) 300 (t "- "))
296 feature-name)) 301 feature-name))
297 302
298 (defun java-feature-decl () 303 (defun java-feature-decl ()
299 (if (looking-at java-class-decl) 304 (if (looking-at java-class-decl)
300 nil 305 nil
301 (looking-at java-feature-decl))) 306 (looking-at java-feature-decl)))
302 307
303 (defun java-feature-def-p () 308 (defun java-feature-def-p ()
304 "Return nil unless point is within a member definition. 309 "Return nil unless point is within a member declaration.
305 Commented member definitions also return nil. 310 Commented member declarations also return nil.
306 Leaves point at start of statement for visual clarity." 311 Leaves point at start of statement for visual clarity."
307 (java-skip-to-statement) 312 (java-skip-to-statement)
308 (save-excursion 313 (and (not (c-within-comment-p))
309 (and (not (c-within-comment-p)) 314 (save-excursion (beginning-of-line)
310 (save-excursion (beginning-of-line) 315 (not (looking-at "[ \t]*//")))
311 (not (looking-at "[ \t]*//"))) 316 (not (looking-at java-class-decl))
312 (not (looking-at java-class-decl)) 317 (looking-at (concat java-at-feature-regexp "[=;,{]"))
313 (looking-at (concat java-at-feature-regexp "[{;,]")) 318 (or (= ?\{ (char-after (1- (match-end 0))))
314 (or (= ?\{ 319 (if (not (match-end java-feature-parens-grpn))
315 (save-excursion (goto-char (match-end 0)) 320 ;; This is an attribute.
316 (preceding-char))) 321 t
317 ;; If ends with a '[;,]' then it must be a native or abstract 322 ;; If this is a native or abstract method, alert user that
318 ;; method to be a definition. 323 ;; its definition is elsewhere.
319 (if (match-end java-feature-parens-grpn) 324 (save-restriction
320 (save-restriction 325 (narrow-to-region (match-beginning 0) (match-end 0))
321 (narrow-to-region (match-beginning 0) (match-end 0)) 326 (cond ((looking-at "\\s *\\<abstract\\>[^;{}]+;")
322 (if (looking-at 327 (message "(OO-Browser): Abstract method, definition deferred to descendants.")
323 "\\(^\\|[ \t\n\^M]\\)\\(abstract\\|native\\)[ \t\n\^M][^;{}]+;") 328 t)
324 (progn (message "(OO-Browser): Abstract function, definition deferred to descendants.") 329 ((looking-at "\\s *\\<native\\>[^;{}]+;")
325 t)))))))) 330 (message "(OO-Browser): Native method, defined in an external language.")
331 t)))))))
332
326 333
327 (defun java-feature-def-pat () 334 (defun java-feature-def-pat ()
328 "Return (list <feature-def-pat> <feature-class> <feature-name>) associated with declaration at point." 335 "Return (list <feature-def-pat> <feature-class> <feature-name>) associated with declaration at point."
329 (and (java-skip-to-statement) 336 (and (java-skip-to-statement)
330 (java-feature-decl) 337 (java-feature-decl)
344 (match-beginning java-feature-name-grpn))) 351 (match-beginning java-feature-name-grpn)))
345 (concat (br-quote-match 352 (concat (br-quote-match
346 java-feature-type-grpn))))) 353 java-feature-type-grpn)))))
347 (func-args (if (match-end java-feature-parens-grpn) 354 (func-args (if (match-end java-feature-parens-grpn)
348 (cons (match-beginning java-feature-parens-grpn) 355 (cons (match-beginning java-feature-parens-grpn)
349 (match-end java-feature-parens-grpn)))) 356 (match-end java-feature-parens-grpn)))))
350 (base-cl-args (match-end java-feature-parens-grpn)))
351 357
352 (and member-type (string-match "[ \t]+$" member-type) 358 (and member-type (string-match "[ \t]+$" member-type)
353 (setq member-type (substring member-type 0 359 (setq member-type (substring member-type 0
354 (match-beginning 0)))) 360 (match-beginning 0))))
355 (and (stringp member-type) 361 (and (stringp member-type)
388 "[ \t\n]*" 394 "[ \t\n]*"
389 (if func-args 395 (if func-args
390 (concat "\\(" (java-func-args-regexp func-args) 396 (concat "\\(" (java-func-args-regexp func-args)
391 "\\|" (java-func-args-string func-args) 397 "\\|" (java-func-args-string func-args)
392 "\\)")) 398 "\\)"))
393 ;; If is a constructor member function, then can have some 399 "[ \t\n]*")))
394 ;; arguments for base class constructors after a ':'
395 ;; but preceding the '{'.
396 "[ \t\n]*"
397 (and base-cl-args
398 (equal member-name class)
399 "\\(:[^;{}]*\\)?"))))
400 (list 400 (list
401 (` (lambda (class) 401 (` (lambda (class)
402 (concat "^" (br-regexp-quote class) 402 (concat "^" (br-regexp-quote class)
403 (, (concat 403 (, (concat
404 java-type-tag-separator 404 java-type-tag-separator
408 pre-member-regexp)) 408 pre-member-regexp))
409 (br-regexp-quote class) 409 (br-regexp-quote class)
410 (, post-member-regexp)))) 410 (, post-member-regexp))))
411 class member-name))))) 411 class member-name)))))
412 412
413 (defun java-feature-lessp (routine1 routine2) 413 (defun java-feature-display (class-list ftr-pat &optional other-win)
414 (string-lessp (java-feature-signature-to-name routine1) 414 "Display feature declaration derived from CLASS-LIST, matching FTR-PAT.
415 (java-feature-signature-to-name routine2))) 415 Use feature tags table to locate a match. Caller must use 'set-buffer'
416
417 (defun java-feature-matches (regexp)
418 "Return an unsorted list of feature tags whose names match in part or whole to REGEXP."
419 ;; Ensure match to feature names only; also handle "^" and "$" meta-chars
420 (setq regexp
421 (concat (format "^[^%s \n]+%s%s "
422 java-type-tag-separator java-type-tag-separator
423 br-feature-type-regexp)
424 (if (equal (substring regexp 0 1) "^")
425 (progn (setq regexp (substring regexp 1)) nil)
426 java-identifier-chars)
427 (if (equal (substring regexp -1) "$")
428 (substring regexp 0 -1)
429 (concat regexp java-identifier-chars))
430 java-type-tag-separator))
431 (save-excursion
432 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file))
433 (goto-char 1)
434 (let ((features))
435 (while (re-search-forward regexp nil t)
436 (setq features (cons (br-feature-current) features)))
437 features)))
438
439 (defun java-feature-normalize (routine class name)
440 (setq class (br-delete-space class)
441 name (java-feature-add-prefix name class routine)
442 routine (concat class java-type-tag-separator
443 name java-type-tag-separator
444 (br-delete-space routine)))
445 (let* ((len (length routine))
446 (normal-feature (make-string len ?\ ))
447 (n 0) (i 0)
448 (space-list '(?\ ?\t ?\n ?\^M))
449 (space-regexp "[ \t\n\^M]+")
450 chr)
451 (while (< i len)
452 (setq chr (aref routine i))
453 (cond
454 ;; Convert sequences of space characters to a single space.
455 ((memq chr space-list)
456 (aset normal-feature n ?\ )
457 (if (string-match space-regexp routine i)
458 (setq i (match-end 0)
459 n (1+ n))
460 (setq i (1+ i)
461 n (1+ n))))
462 ;;
463 ;; Remove // style comments
464 ((and (= chr ?/)
465 (< (1+ i) len)
466 (= (aref routine (1+ i)) ?/))
467 (setq i (+ i 2))
468 (while (and (< i len) (/= (aref routine i) ?\n))
469 (setq i (1+ i))))
470 (t ;; Normal character
471 (aset normal-feature n chr)
472 (setq i (1+ i)
473 n (1+ n)))))
474 (substring normal-feature 0 n)))
475
476 (defun java-feature-tag-class (signature)
477 "Extract the class name from SIGNATURE."
478 (cond ((string-match java-type-tag-separator signature)
479 (substring signature 0 (match-beginning 0)))
480 ((string-match "\\([^ \t]+\\)\." signature)
481 (substring signature (match-beginning 1) (match-end 1)))
482 (t "")))
483
484 (defun java-feature-tags-lookup (class-list ftr-pat &optional other-win)
485 "Display routine definition derived from CLASS-LIST, matching FTR-PAT.
486 Use routine tags table to locate a match. Caller must use 'set-buffer'
487 to restore prior buffer when a match is not found." 416 to restore prior buffer when a match is not found."
488 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file)) 417 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file))
489 (let ((classes class-list) 418 (let ((classes class-list)
490 (found-ftr) 419 (found-ftr)
491 (ftr-regexp) 420 (ftr-regexp)
496 (while (and (not found-ftr) classes) 425 (while (and (not found-ftr) classes)
497 (setq class (car classes) 426 (setq class (car classes)
498 ftr-regexp (funcall ftr-pat class) 427 ftr-regexp (funcall ftr-pat class)
499 ftr-path (br-feature-def-file ftr-regexp) 428 ftr-path (br-feature-def-file ftr-regexp)
500 found-ftr (if ftr-path 429 found-ftr (if ftr-path
501 (br-edit-feature (br-feature-current) 430 (br-edit-feature-from-tag (br-feature-current)
502 ftr-path other-win)) 431 ftr-path other-win))
503 classes (if found-ftr nil (cdr classes)))) 432 classes (if found-ftr nil (cdr classes))))
504 (if found-ftr 433 (if found-ftr
505 (or class t) 434 (or class t)
506 (java-feature-tags-lookup 435 (java-feature-display
507 (apply 'append (mapcar (function (lambda (cl) (br-get-parents cl))) 436 (apply 'append (mapcar (function (lambda (cl) (br-get-parents cl)))
508 class-list)) 437 class-list))
509 ftr-pat))))) 438 ftr-pat)))))
439
440 (defun java-feature-lessp (routine1 routine2)
441 (string-lessp (java-feature-signature-to-name routine1)
442 (java-feature-signature-to-name routine2)))
443
444 (defun java-feature-map-tags (function regexp)
445 "Apply FUNCTION to all current feature tags that match REGEXP and return a list of the results.
446 Feature tags come from the file named by br-feature-tags-file."
447 ;; Ensure match to feature names only; also handle "^" and "$" meta-chars
448 (let ((identifier-chars (concat "[" java-identifier-chars "]*"))
449 (results))
450 (setq regexp
451 (concat (format "^[^%s \n]+%s%s "
452 java-type-tag-separator java-type-tag-separator
453 br-feature-type-regexp)
454 (if (equal (substring regexp 0 1) "^")
455 (progn (setq regexp (substring regexp 1)) nil)
456 identifier-chars)
457 (if (equal (substring regexp -1) "$")
458 (substring regexp 0 -1)
459 (concat regexp identifier-chars))
460 java-type-tag-separator))
461 (save-excursion
462 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file))
463 (goto-char 1)
464 (while (re-search-forward regexp nil t)
465 (setq results (cons (funcall function) results))))
466 results))
467
468 (defun java-feature-matches (regexp)
469 "Return an unsorted list of feature tags whose names match in part or whole to REGEXP.
470 ^ and $ characters may be used to match to the beginning and end of a feature name,
471 respectively."
472 (java-feature-map-tags 'br-feature-current regexp))
473
474 (defun java-feature-normalize (feature class name)
475 (setq class (br-delete-space class)
476 name (java-feature-add-prefix name class feature)
477 feature (concat class java-type-tag-separator
478 name java-type-tag-separator
479 (br-delete-space feature)))
480 (let* ((len (length feature))
481 (normal-feature (make-string len ?\ ))
482 (n 0) (i 0)
483 (space-list '(?\ ?\t ?\n ?\^M))
484 (space-regexp "[ \t\n\^M]+")
485 chr)
486 (while (< i len)
487 (setq chr (aref feature i))
488 (cond
489 ;; Convert sequences of space characters to a single space.
490 ((memq chr space-list)
491 (aset normal-feature n ?\ )
492 (if (string-match space-regexp feature i)
493 (setq i (match-end 0)
494 n (1+ n))
495 (setq i (1+ i)
496 n (1+ n))))
497 ;;
498 ;; Remove // style comments
499 ((and (= chr ?/)
500 (< (1+ i) len)
501 (= (aref feature (1+ i)) ?/))
502 (setq i (+ i 2))
503 (while (and (< i len) (/= (aref feature i) ?\n))
504 (setq i (1+ i))))
505 ;;
506 (t ;; Normal character
507 (aset normal-feature n chr)
508 (setq i (1+ i)
509 n (1+ n)))))
510 (substring normal-feature 0 n)))
511
512 (defun java-feature-tag-class (signature)
513 "Extract the class name from SIGNATURE."
514 (cond ((string-match java-type-tag-separator signature)
515 (substring signature 0 (match-beginning 0)))
516 ((string-match "\\([^ \t]+\\)\." signature)
517 (substring signature (match-beginning 1) (match-end 1)))
518 (t "")))
510 519
511 (defun java-files-with-source (class) 520 (defun java-files-with-source (class)
512 "Use CLASS to compute set of files that match to a java source file regexp. 521 "Use CLASS to compute set of files that match to a java source file regexp.
513 Return as a list." 522 Return as a list."
514 (let ((file (if class (br-class-path class) buffer-file-name))) 523 (let ((file (if class (br-class-path class) buffer-file-name)))
527 (let ((obuf (current-buffer))) 536 (let ((obuf (current-buffer)))
528 (prog1 537 (prog1
529 (if (and br-feature-tags-file 538 (if (and br-feature-tags-file
530 (file-exists-p br-feature-tags-file) 539 (file-exists-p br-feature-tags-file)
531 (file-readable-p br-feature-tags-file)) 540 (file-readable-p br-feature-tags-file))
532 (java-feature-tags-lookup class-list ftr-pat other-win) 541 (java-feature-display class-list ftr-pat other-win)
533 ;; Only works if features are in same directory as class def. 542 ;; Only works if features are in same directory as class def.
534 (java-scan-ancestors-feature class-list ftr-pat other-win)) 543 (java-scan-ancestors-feature class-list ftr-pat other-win))
535 (set-buffer obuf)))) 544 (set-buffer obuf))))
536 545
537 (defun java-find-class-name () 546 (defun java-find-class-name ()
542 (pat (concat "^" ignore))) 551 (pat (concat "^" ignore)))
543 (forward-char 1) 552 (forward-char 1)
544 (skip-chars-backward ignore) 553 (skip-chars-backward ignore)
545 (skip-chars-backward pat) 554 (skip-chars-backward pat)
546 (setq start (point)) 555 (setq start (point))
547 (skip-chars-forward (concat pat ":")) 556 (skip-chars-forward pat)
548 (buffer-substring start (point))))) 557 (buffer-substring start (point)))))
549 558
550 (defun java-func-args-regexp (func-args) 559 (defun java-func-args-regexp (func-args)
551 (let* ((space "\\\\\\s-*") 560 (let* ((space "\\\\\\s-*")
552 (obuf (current-buffer)) 561 (obuf (current-buffer))
700 ;; Ensure that declaration occurs within class definition. 709 ;; Ensure that declaration occurs within class definition.
701 (forward-list) 710 (forward-list)
702 (and (> (point) opoint) 711 (and (> (point) opoint)
703 class)))))) 712 class))))))
704 713
705 (defun java-get-feature-tags (routine-file &optional routine-list) 714 (defun java-get-feature-tags (feature-file &optional feature-list)
706 "Scan java ROUTINE-FILE and hold routine tags in 'br-feature-tags-file'. 715 "Scan java FEATURE-FILE and hold feature tags in 'br-feature-tags-file'.
707 Assume ROUTINE-FILE has already been read into a buffer and that 716 Assume FEATURE-FILE has already been read into a buffer and that
708 'br-feature-tags-init' has been called. Optional ROUTINE-LIST can be 717 'br-feature-tags-init' has been called. Optional FEATURE-LIST can be
709 provided so that a non-standard scan function can be used before calling 718 provided so that a non-standard scan function can be used before calling
710 this function." 719 this function."
711 (interactive) 720 (interactive)
712 (let ((obuf (current-buffer))) 721 (let ((obuf (current-buffer)))
713 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file)) 722 (set-buffer (funcall br-find-file-noselect-function br-feature-tags-file))
714 (goto-char 1) 723 (goto-char 1)
715 ;; Delete any prior routine tags associated with routine-file 724 ;; Delete any prior feature tags associated with feature-file
716 (if (search-forward routine-file nil 'end) 725 (if (search-forward feature-file nil 'end)
717 (progn (forward-line -1) 726 (progn (forward-line -1)
718 (let ((start (point))) 727 (let ((start (point)))
719 (search-forward "\^L" nil 'end 2) 728 (search-forward "\^L" nil 'end 2)
720 (backward-char 1) 729 (backward-char 1)
721 (delete-region start (point)) 730 (delete-region start (point))
722 ))) 731 )))
723 (if routine-list 732 (if feature-list
724 (progn (insert "\^L\n" routine-file "\n") 733 (progn (insert "\^L\n" feature-file "\n")
725 (mapcar (function (lambda (tag) (insert tag "\n"))) 734 (mapcar (function (lambda (tag) (insert tag "\n")))
726 routine-list) 735 feature-list)
727 )) 736 ))
728 (set-buffer obuf))) 737 (set-buffer obuf)))
729
730 (defun java-include-file (&optional other-win)
731 "If point is on an include file line, try to display file.
732 Return non-nil iff an include file line, even if file is not found.
733 Look for include file in 'java-cpp-include-dirs' and in directory list
734 'java-include-dirs'."
735 (let ((opoint (point)))
736 (beginning-of-line)
737 (if (looking-at java-include-regexp)
738 (let ((incl-type (string-to-char
739 (buffer-substring (match-beginning 1)
740 (1+ (match-beginning 1)))))
741 (file (buffer-substring (match-beginning 2) (match-end 2)))
742 (path)
743 (dir-list java-include-dirs)
744 (found))
745 (goto-char opoint)
746 (setq dir-list (if (= incl-type ?<)
747 (append dir-list java-cpp-include-dirs)
748 (cons (file-name-directory buffer-file-name)
749 dir-list)))
750 (while dir-list
751 (setq path (concat (car dir-list) file)
752 dir-list (if (setq found (file-exists-p path))
753 nil
754 (cdr dir-list))))
755 ;;
756 ;; If not found in normal include dirs, check all Env paths also.
757 ;;
758 (if (not found)
759 (let ((paths (delq nil (hash-map 'cdr br-paths-htable))))
760 (while paths
761 (setq path (car paths))
762 (if (string-equal (file-name-nondirectory path) file)
763 (setq found t paths nil)
764 (setq paths (cdr paths))))))
765 ;;
766 ;; If found, display file
767 ;;
768 (if found
769 (if (file-readable-p path)
770 (progn
771 (funcall br-edit-file-function path other-win)
772 (if (not (fboundp 'br-lang-mode))
773 (java-mode-setup))
774 (br-major-mode))
775 (beep)
776 (message "(OO-Browser): Include file '%s' unreadable." path))
777 (beep)
778 (message "(OO-Browser): Include file '%s' not found." file))
779 path)
780 (goto-char opoint)
781 nil)))
782 738
783 (defun java-locate-feature (ftr class ftr-pat &optional other-win) 739 (defun java-locate-feature (ftr class ftr-pat &optional other-win)
784 ;; 'class' may = nil, implying non-member function 740 ;; 'class' may = nil, implying non-member function
785 (or class (setq class "[function]")) 741 (or class (setq class "[function]"))
786 (let ((def-class)) 742 (let ((def-class))
793 "Member `%s` of class '%s' inherited from class '%s'." 749 "Member `%s` of class '%s' inherited from class '%s'."
794 ftr class def-class)) 750 ftr class def-class))
795 t)))) 751 t))))
796 752
797 (defun java-scan-ancestors-feature (class-list ftr-pat &optional other-win) 753 (defun java-scan-ancestors-feature (class-list ftr-pat &optional other-win)
798 "Display routine definition derived from CLASS-LIST, matching FTR-PAT. 754 "Display feature definition derived from CLASS-LIST, matching FTR-PAT.
799 Scan files with same base name as class file." 755 Scan files with same base name as class file."
800 (let ((classes class-list) 756 (let ((classes class-list)
801 (found-ftr) 757 (found-ftr)
802 (code-def-files) 758 (code-def-files)
803 (file) 759 (file)
821 (apply 'append (mapcar (function (lambda (cl) (br-get-parents cl))) 777 (apply 'append (mapcar (function (lambda (cl) (br-get-parents cl)))
822 class-list)) 778 class-list))
823 ftr-pat))))) 779 ftr-pat)))))
824 780
825 (defun java-scan-features (class start end) 781 (defun java-scan-features (class start end)
826 "Return reverse ordered list of java routine definitions within CLASS def. 782 "Return reverse ordered list of java feature declarations within CLASS def.
827 START and END give buffer region to search." 783 START and END give buffer region to search.
784
785 Multiple declarations with only one type, e.g. float a, b;
786 are missed, because that would require too much effort right now.
787 Use the clearer style with a type keyword for each feature defined."
828 (setq class (br-delete-space class)) 788 (setq class (br-delete-space class))
829 (save-excursion 789 (save-excursion
830 (save-restriction 790 (save-restriction
831 (narrow-to-region start end) 791 (narrow-to-region start end)
832 (goto-char start) 792 (goto-char start)
833 (let ((routines) rout name) 793 (let ((features) ftr name)
834 ;; 794 ;;
835 ;; Get member definitions and abstract method declarations. 795 ;; Get member definitions and abstract method declarations.
836 ;; 796 (while (re-search-forward java-feature-decl nil t)
837 (while (re-search-forward java-routine-def nil t)
838 (setq start (match-beginning 0) 797 (setq start (match-beginning 0)
839 name (buffer-substring 798 name (buffer-substring
840 (match-beginning java-feature-name-grpn) 799 (match-beginning java-feature-name-grpn)
841 (match-end java-feature-name-grpn)) 800 (match-end java-feature-name-grpn))
842 rout (buffer-substring (match-beginning 0) (match-end 0))) 801 ftr (buffer-substring (match-beginning 0) (match-end 0)))
843 ;; This is necessary to remove a possible double expression match 802 ;; This is necessary to remove a possible double expression match
844 ;; where there is a blank line within the match. 803 ;; where there is a blank line within the match.
845 (if (string-match "[\n\^M]\\([ \t]*[\n\^M]\\)+" rout) 804 (if (string-match "[\n\^M]\\([ \t]*[\n\^M]\\)+" ftr)
846 (progn (setq rout (substring rout (match-end 0))) 805 (progn (setq ftr (substring ftr (match-end 0)))
847 (goto-char (+ start (match-end 0)))) 806 (goto-char (+ start (match-end 0))))
848 (if (c-within-comment-p) 807 (if (c-within-comment-p)
849 (search-forward "*/" nil t) 808 (search-forward "*/" nil t)
850 ;; Move point to precede feature opening brace or abstract 809 ;; Move point to precede the feature match termination character.
851 ;; method declaration semicolon.
852 (backward-char) 810 (backward-char)
853 (if (= (following-char) ?\{) 811 (cond ((= (following-char) ?\{)
854 (condition-case () 812 (condition-case ()
855 ;; Move to end of feature but ignore any error if braces 813 ;; Move to end of feature but ignore any error if braces
856 ;; are unbalanced. Let the compiler tell the user about 814 ;; are unbalanced. Let the compiler tell the user about
857 ;; this. 815 ;; this.
858 (forward-sexp) 816 (forward-sexp)
859 (error nil))) 817 (error nil)))
860 (setq rout (java-feature-normalize rout class name) 818 ((= (following-char) ?=)
861 routines (cons rout routines))))) 819 (skip-chars-forward "^;")))
862 routines)))) 820 (setq ftr (java-feature-normalize ftr class name)
821 features (cons ftr features)))))
822 features))))
863 823
864 (defun java-skip-to-statement () 824 (defun java-skip-to-statement ()
865 (if (re-search-backward "\\(^\\|[;{}]\\)[ \t]*" nil t) 825 (if (re-search-backward "\\(^\\|[;{}]\\)[ \t]*" nil t)
866 (progn (goto-char (match-end 0)) 826 (progn (goto-char (match-end 0))
867 (skip-chars-forward " \t") 827 (skip-chars-forward " \t")
869 829
870 ;;; ************************************************************************ 830 ;;; ************************************************************************
871 ;;; Private variables 831 ;;; Private variables
872 ;;; ************************************************************************ 832 ;;; ************************************************************************
873 833
874 (defconst java-code-file-regexp "\\.java$" 834 (defconst java-code-file-regexp "\\.java?$"
875 "Regular expression matching a unique part of java source (non-header) file name and no others.") 835 "Regular expression matching a unique part of a Java source file name and no others.")
876
877 (defconst java-include-regexp
878 "[ \t/*]*import[ \t]+\\([^;]+\\)"
879 "Regexp to match to java include file lines. File name is grouping 2. Type
880 of include, user-specified via double quote, or system-related starting with
881 '<' is given by grouping 1.")
882 836
883 (defconst java-type-def-modifier 837 (defconst java-type-def-modifier
884 "\\(const\\|final\\|static\\|abstract\\|public\\|protected\\|private\\)") 838 "\\(const\\|final\\|static\\|abstract\\|public\\|protected\\|private\\)")
885 839
886 (defconst java-type-modifier-keyword 840 (defconst java-type-modifier-keyword
887 (concat "\\(\\(public\\|protected\\|private\\|const\\|abstract\\|" 841 (concat "\\(\\(public\\|protected\\|private\\|const\\|abstract\\|"
888 "synchronized\\|final\\|static\\|threadsafe\\|transient\\|" 842 "synchronized\\|final\\|static\\|transient\\|"
889 "native\\)[ \t\n\^M]+\\)")) 843 "native\\|volatile\\)[ \t\n\^M]+\\)"))
890 844
891 (defconst java-type-identifier-group 845 (defconst java-type-identifier-group
892 (concat "\\(\\(" java-return-type-identifier "\\)[ \t\n\^M]+\\)")) 846 (concat "\\(\\(" java-return-type-identifier "\\)[ \t\n\^M]+\\)"))
893 847
894 (defconst java-function-identifier (concat 848 (defconst java-function-identifier (concat
902 (defconst java-feature-decl-or-def 856 (defconst java-feature-decl-or-def
903 (concat "^[ \t]*\\(" java-type-modifier-keyword "*" 857 (concat "^[ \t]*\\(" java-type-modifier-keyword "*"
904 java-type-identifier-group "\\)?" 858 java-type-identifier-group "\\)?"
905 "\\(" java-type-identifier "[ \t\n\^M]*\\)?" 859 "\\(" java-type-identifier "[ \t\n\^M]*\\)?"
906 "\\(" java-function-identifier "\\|" java-identifier "\\)" 860 "\\(" java-function-identifier "\\|" java-identifier "\\)"
907 ;; It's hard to tell arguments from parenthesized initializing 861 ;; It is hard to tell arguments from parenthesized initializing
908 ;; expressions. 862 ;; expressions.
909 "[ \t\n\^M]*(\\([^);{}]*\\))\\([][]*\\)" 863 "[ \t\n\^M]*\\(([^\);{}]*)\\)?\\([][ \t]*\\)"
910 ;; Optional exceptions that a feature can throw. 864 ;; Optional exceptions that a method can throw.
911 "\\([ \t\n\^M]+throws[ \t\n\^M]+\\(" 865 "\\([ \t\n\^M]*\\<throws\\>[ \t\n\^M]*\\("
912 java-identifier "[, \t\n\^M]*\\)+\\)?" 866 java-identifier "[, \t\n\^M]*\\)+\\)?"
913 ) 867 )
914 "Regexp matching a java member declaration or definition. 868 "Regexp matching a java member declaration or definition.
915 Member modifier keywords are grouped expression 'java-feature-mode-grpn'. 869 Member modifier keywords are grouped expression 'java-feature-mode-grpn'.
916 Member type is grouped expression 'java-feature-type-grpn'. Member name is 870 Member type is grouped expression 'java-feature-type-grpn'. Member name is
921 (defconst java-feature-mod-grpn 2) 875 (defconst java-feature-mod-grpn 2)
922 (defconst java-feature-type-grpn 5) 876 (defconst java-feature-type-grpn 5)
923 (defconst java-feature-name-grpn 9) 877 (defconst java-feature-name-grpn 9)
924 (defconst java-feature-parens-grpn 11) 878 (defconst java-feature-parens-grpn 11)
925 (defconst java-feature-exceptions-grpn 14) 879 (defconst java-feature-exceptions-grpn 14)
880 (defconst java-feature-terminator-grpn 15)
926 881
927 (defconst java-at-feature-regexp 882 (defconst java-at-feature-regexp
928 (concat java-feature-decl-or-def "[ \t\n]*") 883 (concat java-feature-decl-or-def "[ \t\n]*")
929 "See documentation of 'java-feature-decl-or-def' for grouping expressions.") 884 "See documentation of 'java-feature-decl-or-def' for grouping expressions.")
930 885
931 (defconst java-feature-decl 886 (defconst java-feature-decl
932 (concat java-at-feature-regexp "[;{]") 887 (concat java-at-feature-regexp "\\([=;{]\\)")
933 "See documentation of 'java-feature-decl-or-def' for grouping expressions.") 888 "See documentation of 'java-feature-decl-or-def' for grouping expressions.
934 889 'java-feature-terminator-grpn' holds the equal-sign, semi-color or opening brace
935 (defconst java-routine-def-terminator-regexp 890 that triggers the end of the match.")
936 ;; Also matches to abstract method declarations.
937 ;; Only native and abstract functions end with a semi-colon.
938 "\\({\\|;\\)")
939 891
940 (defconst java-routine-def 892 (defconst java-routine-def
941 (concat java-at-feature-regexp java-routine-def-terminator-regexp) 893 (concat java-at-feature-regexp "\\([;{]\\)")
942 "See documentation of 'java-feature-decl-or-def' for grouping expressions.") 894 "See documentation of 'java-feature-decl-or-def' for grouping expressions.
895 'java-feature-terminator-grpn' holds the opening brace that terminates the
896 feature declaration or the semi-colon that terminates native and abstract
897 method declarations.")
943 898
944 (defconst java-class-decl 899 (defconst java-class-decl
945 (concat java-class-modifier-keyword 900 (concat java-class-modifier-keyword
946 java-class-keyword java-identifier "[ \t]*[;,]") 901 java-class-keyword java-identifier "[ \t]*[;,]")
947 "Regexp matching a java class declaration. 902 "Regexp matching a java class declaration.
948 Class name is grouping 'java-class-name-grpn'.") 903 Class name is grouping 'java-class-name-grpn'.")
949 904
950 (defconst java-class-name-grpn 4) 905 (defconst java-class-name-grpn 4)
951 906
952 ;; Old def was: "\\(^\\|[ \t\n\^M]\\)abstract[ \t\n\^M][^;{}]+;" 907 (defconst java-abstract-method-regexp "\\<abstract\\>[^;{}]+;"
953 (defconst java-abstract-method-regexp ";\\'"
954 "Regexp matching a Java abstract method signature.") 908 "Regexp matching a Java abstract method signature.")
955 909
956 (defconst java-native-method-regexp "\\(^\\|[ \t\n\^M]\\)native[ \t\n\^M][^;{}]+;" 910 (defconst java-native-method-regexp "\\<native\\>[^;{}]+;"
957 "Regexp matching a Java native method signature, one implemented in another language.") 911 "Regexp matching a Java native method signature, one implemented in another language.")
958 912
959 (provide 'br-java-ft) 913 (provide 'br-java-ft)