Initial Commit
[packages] / xemacs-packages / jde / lisp / jde-javadoc.el
1 ;;; jde-javadoc.el --- JDE javadoc autodoc
2 ;; $Revision: 1.31 $
3
4 ;; Copyright (C) 1998-2004 by David Ponce
5
6 ;; Author: David Ponce <david@dponce.com>
7 ;; Maintainer: David Ponce <david@dponce.com>
8 ;;             Paul Kinnucan <paulk@mathworks.com>
9
10 ;; Keywords: java, tools
11 ;;
12 ;; This file is not part of Emacs
13
14 ;; This program is free software; you can redistribute it and/or
15 ;; modify it under the terms of the GNU General Public License as
16 ;; published by the Free Software Foundation; either version 2, or (at
17 ;; your option) any later version.
18
19 ;; This program is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 ;; General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program; see the file COPYING.  If not, write to
26 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
28
29 ;;; Commentary:
30 ;;
31 ;; This library provides a javadoc comment checker and generator to
32 ;; help handling of Java source documentation.
33
34 ;;; History:
35 ;;
36 ;; See at end of this file.
37
38 ;;; Code:
39
40 (require 'tempo)
41 (require 'semantic-java)
42 (require 'regexp-opt)
43
44 (eval-when-compile
45   (require 'jde)
46   (require 'jde-parse))
47
48 ;;;; Customization
49 ;;;; -------------
50
51 (defgroup jde-javadoc nil
52   "JDE javadoc utilities"
53   :group 'jde
54   :prefix "jde-javadoc-")
55
56 ;; IMPORTANT: This function must be defined before the following
57 ;; defcustoms because it is used in their :set clause.
58 (defun jde-javadoc-define-template (sym val)
59   "Define a template (see `tempo-define-template').
60 The template name is the `symbol-name' of SYM from which the
61 '-template' suffix has been removed, prefixed by 'tempo-template-'.
62 VAL is the template value.  If VAL is a string it is converted to a
63 list of template elements."
64   (let* ((name (symbol-name sym))
65          (template-name
66           (if (string-match "\\(.*\\)-template$" name)
67               (match-string 1 name)
68             (error "Invalid template variable name: %S" name)))
69          (template-val
70           (if (stringp val)
71               (car (read-from-string (format "(%s)" val)))
72             val)))
73     (tempo-define-template template-name template-val nil name)
74     (set-default sym val)))
75
76 (defcustom jde-javadoc-describe-class-template
77   "\"* Describe class \" (jde-javadoc-code name) \" here.\""
78   "*Line template used to describe a class.
79 If nil the line is not inserted.
80 The variable 'name' is set to the class name.
81 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
82 variable `tempo-template-jde-javadoc-describe-class'."
83   :group 'jde-javadoc
84   :type '(choice :tag "Template form"
85                  (text :format "%t\n%v" :tag "String")
86                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
87   :set 'jde-javadoc-define-template)
88
89 (defcustom jde-javadoc-describe-interface-template
90   "\"* Describe interface \" (jde-javadoc-code name) \" here.\""
91   "*Line template used to describe an interface.
92 If nil the line is not inserted.
93 The variable 'name' is set to the interface name.
94 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
95 variable `tempo-template-jde-javadoc-describe-interface'."
96   :group 'jde-javadoc
97   :type '(choice :tag "Template form"
98                  (text :format "%t\n%v" :tag "String")
99                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
100   :set 'jde-javadoc-define-template)
101
102 (defcustom jde-javadoc-describe-constructor-template
103   "\"* Creates a new \" (jde-javadoc-code name) \" instance.\""
104   "*Line template used to describe a constructor.
105 If nil the line is not inserted.
106 The variable 'name' is set to the constructor name (that is the class
107 name).  See `jde-javadoc-autodoc-at-line' for usage.  Define the
108 template variable `tempo-template-jde-javadoc-describe-constructor'."
109   :group 'jde-javadoc
110   :type '(choice :tag "Template form"
111                  (text :format "%t\n%v" :tag "String")
112                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
113   :set 'jde-javadoc-define-template)
114
115 (defcustom jde-javadoc-describe-method-template
116   "\"* Describe \" (jde-javadoc-code name) \" method here.\""
117   "*Line template used to describe a method.
118 If nil the line is not inserted.
119 The variable 'name' is set to the method name.
120 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
121 variable `tempo-template-jde-javadoc-describe-method'."
122   :group 'jde-javadoc
123   :type '(choice :tag "Template form"
124                  (text :format "%t\n%v" :tag "String")
125                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
126   :set 'jde-javadoc-define-template)
127
128 (defcustom jde-javadoc-describe-field-template
129   "\"* Describe \" (jde-javadoc-field-type modifiers)
130  \" \" (jde-javadoc-code name) \" here.\""
131   "*Line template used to describe a method.
132 If nil the line is not inserted.
133 The variable 'name' is set to the field name.
134 The variable 'type' is set to the field type.
135 The variable 'modifiers' is set to the field modifiers.
136 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
137 variable `tempo-template-jde-javadoc-describe-field'."
138   :group 'jde-javadoc
139   :type '(choice :tag "Template form"
140                  (text :format "%t\n%v" :tag "String")
141                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
142   :set 'jde-javadoc-define-template)
143
144 (defcustom jde-javadoc-param-tag-template
145   "\"* @param \" name \" \" (jde-javadoc-a type)
146  \" \" (jde-javadoc-code type) \" value\""
147   "*Line template used to describe a parameter.
148 If nil the line is not inserted.
149 The variable 'name' is set to the parameter name.
150 The variable 'type' is set to the parameter type.
151 A line is inserted for each parameter.
152 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
153 variable `tempo-template-jde-javadoc-param-tag'."
154   :group 'jde-javadoc
155   :type '(choice :tag "Template form"
156                  (text :format "%t\n%v" :tag "String")
157                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
158   :set 'jde-javadoc-define-template)
159
160 (defcustom jde-javadoc-return-tag-template
161   "\"* @return \" (jde-javadoc-a type)
162  \" \" (jde-javadoc-code type) \" value\""
163   "*Line template used to describe a returned value.
164 If nil the line is not inserted.
165 The variable 'type' is set to the returned type.
166 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
167 variable `tempo-template-jde-javadoc-return-tag'."
168   :group 'jde-javadoc
169   :type '(choice :tag "Template form"
170                  (text :format "%t\n%v" :tag "String")
171                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
172   :set 'jde-javadoc-define-template)
173
174 (defcustom jde-javadoc-exception-tag-template
175   "\"* @exception \" type \" if an error occurs\""
176   "*Line template used to describe an exception.
177 If nil the line is not inserted.
178 The variable 'type' is set to the exception type.
179 A line is inserted for each exception in the 'throws' clause.
180 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
181 variable `tempo-template-jde-javadoc-exception-tag'."
182   :group 'jde-javadoc
183   :type '(choice :tag "Template form"
184                  (text :format "%t\n%v" :tag "String")
185                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
186   :set 'jde-javadoc-define-template)
187
188 (defcustom jde-javadoc-author-tag-template
189   "\"* @author <a href=\\\"mailto:\" user-mail-address
190  \"\\\">\" user-full-name \"</a>\""
191   "*Line template used to give an author.
192 If nil the line is not inserted.
193 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
194 variable `tempo-template-jde-javadoc-author-tag'."
195   :group 'jde-javadoc
196   :type '(choice :tag "Template form"
197                  (text :format "%t\n%v" :tag "String")
198                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
199   :set 'jde-javadoc-define-template)
200
201 (defcustom jde-javadoc-version-tag-template
202   "\"* @version 1.0\""
203   "*Line template used to give a version.
204 If nil the line is not inserted.
205 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
206 variable `tempo-template-jde-javadoc-version-tag'."
207   :group 'jde-javadoc
208   :type '(choice :tag "Template form"
209                  (text :format "%t\n%v" :tag "String")
210                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
211   :set 'jde-javadoc-define-template)
212
213 ;; (defcustom jde-javadoc-see-tag-template
214 ;;   '("* @see " ref)
215 ;;   "*Line template used to give a reference.
216 ;; If nil the line is not inserted.
217 ;; The variable 'ref' is set to the class or interface name.
218 ;; A line is inserted for each name in the 'extends' then 'implements'
219 ;; clauses.  See `jde-javadoc-autodoc-at-line' for usage.  Define the
220 ;; template variable `tempo-template-jde-javadoc-see-tag'."
221 ;;   :group 'jde-javadoc
222 ;;   :type '(choice :tag "Template form"
223 ;;                  (text :format "%t\n%v" :tag "String")
224 ;;                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
225 ;;   :set 'jde-javadoc-define-template)
226
227 ;; (defcustom jde-javadoc-since-tag-template
228 ;;   '("* @since 1.0")
229 ;;   "*Line template used to give a since reference.
230 ;; If nil the line is not inserted.
231 ;; See `jde-javadoc-autodoc-at-line' for usage.  Define the template
232 ;; variable `tempo-template-jde-javadoc-since-tag'."
233 ;;   :group 'jde-javadoc
234 ;;   :type '(choice :tag "Template form"
235 ;;                  (text :format "%t\n%v" :tag "String")
236 ;;                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
237 ;;   :set 'jde-javadoc-define-template)
238
239 (defcustom jde-javadoc-end-block-template
240   nil
241   "*Javadoc end comment block characters.
242 If nil \"*/\" is inserted.
243 See `jde-javadoc-autodoc-at-line' for usage.  Define the template
244 variable `tempo-template-jde-javadoc-end-block'."
245   :group 'jde-javadoc
246   :type '(choice :tag "Template form"
247                  (text :format "%t\n%v" :tag "String")
248                  (repeat :tag "Lisp Expressions" (sexp :tag "")))
249   :set 'jde-javadoc-define-template)
250
251 ;;;; Utilities
252 ;;;; ---------
253 (defmacro jde-javadoc-status-forms (message donestr &rest forms)
254   "Wrapper for `working-status-forms'.
255 See `working-status-forms' for details on MESSAGE, DONESTR and FORMS
256 arguments.  Does not override an outer `working-status-forms'
257 MESSAGE."
258   `(working-status-forms (or working-message ,message) ,donestr
259      ,@forms))
260
261 (defun jde-javadoc-dynamic-status (&rest args)
262   "Wrapper for `working-dynamic-status'.
263 Does nothing if not called within the macro `working-status-forms'.
264 See `working-dynamic-status' for meaning of ARGS."
265   (and working-message
266        (apply #'working-dynamic-status args)))
267
268 (defalias 'jde-javadoc-skip-spaces-forward
269   'semantic-java-skip-spaces-forward)
270
271 (defalias 'jde-javadoc-indent-line 'c-indent-line)
272
273 (defun jde-javadoc-indent-region (start end)
274   "Indent region between START and END."
275   (save-excursion
276     (goto-char end)
277     (setq end (point-marker))
278     (goto-char start)
279     (while (< (point) end)
280       (jde-javadoc-dynamic-status)
281       (or (and (bolp) (eolp))
282           (jde-javadoc-indent-line))
283       (forward-line 1))
284     (move-marker end nil)))
285
286 (defun jde-javadoc-map (f l &rest args)
287   "Apply F to each element of L.
288 F receives optional ARGS after the current element of L."
289   (while l
290     (apply f (car l) args)
291     (setq l (cdr l))))
292                 
293 (defun jde-javadoc-window-lines ()
294   "Return the number of lines of the selected window.
295 This number may be greater than the number of actual lines in the
296 buffer if any wrap on the display due to their length."
297   (let ((start (point-min))
298         (end   (point-max)))
299     (if (= start end)
300         0
301       (save-excursion
302         (save-restriction
303           (widen)
304           (narrow-to-region start end)
305           (goto-char start)
306           (vertical-motion (buffer-size)))))))
307
308 (defun jde-javadoc-adjust-window (window)
309   "Adjust WINDOW height to fit its buffer contents."
310   (save-selected-window
311     (select-window window)
312     (let ((height (window-height))
313           (lines  (+ 3 (jde-javadoc-window-lines))))
314       ;; ensure window will not be deleted if too small
315       (if (< lines window-min-height)
316           (setq lines window-min-height))
317       (enlarge-window (- lines height)))))
318
319 (defsubst jde-javadoc-variable-name (name)
320   "Return canonical variable name from NAME.
321 That is strip any array brackets from NAME."
322   (if (string-match "\\`\\([^[]+\\)[[]" name)
323       (match-string 1 name)
324     name))
325
326 (defcustom jde-javadoc-check-undeclared-exception-flag nil
327   "*non-nil means to check for undeclared exceptions.
328 When an exception is implicitly declared (inherits from
329 RuntimeException) any associated @exception/@throws tag that already
330 exists will be just kept without issuing a warning.  Other extra tags
331 are automatically removed.
332
333 If nil extra @exception/@throws tags are never removed but warnings
334 are issued for (maybe) undeclared exceptions."
335   :group 'jde-javadoc
336   :type 'boolean)
337
338 (defun jde-javadoc-implicit-exception-p (type)
339   "Return non-nil if TYPE is an implicitly declared exception.
340 That is if TYPE inherits from java.lang.RuntimeException or if Java
341 reflection failed to process TYPE."
342   (condition-case nil
343       (jde-jeval-r
344        (format "jde.util.Completion.isAncestorOf(%S,%S);"
345                "java.lang.RuntimeException"
346                (jde-parse-get-qualified-name type)))
347     (error t)))
348
349 ;;;; Text helpers
350 ;;;; ------------
351
352 (defun jde-javadoc-field-type (modifiers)
353   "Return field category.
354 That is \"constant\" if field MODIFIERS contains \"static\" and
355 \"final\" or \"variable\" otherwise.  Useful to generate field
356 description."
357   (if (and (member "static" modifiers) (member "final" modifiers))
358       "constant"
359     "variable"))
360
361 (defun jde-javadoc-a (word)
362   "Return \"an\" if WORD begin with a vowel or \"a\" otherwise.
363 Useful to generate description like \"an int value\" or \"a long value\"."
364   (if (string-match "^[aeiouyAEIOUY]" word)
365       "an" "a"))
366
367 (defun jde-javadoc-code (text)
368   "Return \"<code>TEXT</code>\".
369 Useful to generate HTML code style."
370   (concat "<code>" text "</code>"))
371
372 ;;;; Javadoc comment parser
373 ;;;; ----------------------
374
375 ;; tags and matchers (many are provided by Semantic)
376 ;;
377 (defconst jde-javadoc-desc-tag
378   "*DESCRIPTION*"
379   "Special internal tag associated to descriptions.")
380
381 (defconst jde-javadoc-start-tag-regexp
382   "[\r\n][ \t]*\\(/\\*\\*\\|\\*?\\)[ \t]*@"
383   "Regexp matching the beginning of a tag.")
384
385 (defconst jde-javadoc-end-tag-regexp
386   (concat "\\(" jde-javadoc-start-tag-regexp
387           "\\|[ \n\r\t]*\\*/\\)")
388   "Regexp matching the end of a tag or description.")
389
390 ;; Core comment parser
391 ;;
392 (defun jde-javadoc-normalize-description (desc)
393   "Ensure DESC text begins with '\\n* ' and ends with '\\n*\\n'."
394   (let ((i (string-match "[^ *\n\r\t]" desc)))
395     (if i
396         (setq desc (concat "\n* " (substring desc i))))
397     ;; TODO: ensure empty line at end
398     desc))
399
400 (defun jde-javadoc-normalize-ref (val)
401   "Strip any [* \\n\\r\\t] from VAL."
402   (let* ((keep "[^* \n\r\t]+")
403          (ref  "")
404          (i    (string-match keep val))
405          j)
406     (while i
407       (jde-javadoc-dynamic-status)
408       (setq j   (match-end 0)
409             ref (concat ref (substring val i j))
410             i   (string-match keep val j)))
411     ref))
412
413 (defun jde-javadoc-parse-description (docstring)
414   "Return the description from DOCSTRING or nil if not found.
415 The returned value has the form ((DESC)).  See also
416 `jde-javadoc-parse-tag-values'."
417   (let ((matcher "/\\*\\*")
418         (i 0)
419         j tag-val)
420     (when (string-match matcher docstring)
421       (jde-javadoc-dynamic-status)
422       (setq j (match-end 0))
423       (setq i (string-match jde-javadoc-end-tag-regexp docstring j))
424       (setq tag-val (if i
425                         (substring docstring j i)
426                       (substring docstring j)))
427       ;; Ensure that a valid description exists
428       (if (not (string-equal ""
429                              (jde-javadoc-normalize-ref tag-val)))
430           (list (list tag-val))))))
431
432 (defun jde-javadoc-parse-tag-values (docstring tag &optional with-key)
433   "Return from DOCSTRING the list of TAG values or nil if not found.
434 Each value is a pair (VALUE-STRING . VALUE-KEY).  If optional WITH-KEY
435 is 'name VALUE-KEY is the first word of VALUE-STRING.  If optional
436 WITH-KEY is 'ref VALUE-KEY is a normalized VALUE-STRING reference (see
437 `jde-javadoc-normalize-ref').  Otherwise VALUE-KEY is nil."
438   (let ((matcher (concat jde-javadoc-start-tag-regexp tag))
439         (i 0)
440         j tag-val key tag-list)
441     (while (string-match matcher docstring i)
442       (jde-javadoc-dynamic-status)
443       (setq j (match-end 0))
444       (setq i (or (string-match
445                    jde-javadoc-end-tag-regexp docstring j)
446                   (length docstring)))
447       (setq tag-val (substring docstring j i))
448       (cond ((eq with-key 'name)
449              (setq key (and (string-match
450                              "[* \n\r\t]*\\([^ \n\r\t]+\\)" tag-val)
451                             (jde-javadoc-variable-name
452                              (match-string 1 tag-val)))))
453             ((eq with-key 'ref)
454              (setq key (jde-javadoc-normalize-ref tag-val))))
455       (setq tag-list (cons (cons tag-val key) tag-list)))
456     (nreverse tag-list)))
457
458 (defun jde-javadoc-parse-tag (tag docstring)
459   "Return the TAG documentation from DOCSTRING or nil if not found.
460 Documentation has the form (TAG VALUE-LIST).  See also
461 `jde-javadoc-parse-tag-values'."
462   (cond ((string-equal tag jde-javadoc-desc-tag)
463          (jde-javadoc-parse-description docstring))
464         ((member tag semantic-java-doc-with-name-tags)
465          (jde-javadoc-parse-tag-values docstring tag 'name))
466         ((member tag semantic-java-doc-with-ref-tags)
467          (jde-javadoc-parse-tag-values docstring tag 'ref))
468         (t
469          (jde-javadoc-parse-tag-values docstring tag))
470         ))
471
472 (defun jde-javadoc-parse-tag-list (docstring)
473   "Return the list of tag found in DOCSTRING."
474   (let* ((matcher (concat jde-javadoc-start-tag-regexp
475                           "\\([^ \n\r\t]+\\)"))
476          (depth (regexp-opt-depth matcher))
477          (i (string-match matcher docstring))
478          j tag-list)
479     (while i
480       (jde-javadoc-dynamic-status)
481       (setq tag-list (cons (match-string depth docstring) tag-list))
482       (setq i (string-match matcher docstring (match-end depth))))
483     (nreverse tag-list)))
484
485 (defun jde-javadoc-parse-docstring (docstring)
486   "Return the parsed documentation tree from DOCSTRING.
487 Result has the following form: (DOCSTRING TAG-LIST TAG-VALUE-ALIST)."
488   (if docstring
489       (let (tag-list
490             tag-alist l tag
491             throws-assoc except-assoc merged-values)
492         (jde-javadoc-status-forms "Parsing" "done"
493           (jde-javadoc-dynamic-status)
494           (setq tag-list (jde-javadoc-parse-tag-list docstring))
495           (setq l (cons jde-javadoc-desc-tag tag-list))
496           (while l
497             (jde-javadoc-dynamic-status)
498             (setq tag (car l))
499             (if (assoc tag tag-alist)
500                 nil                     ; tag already processed
501               (setq tag-alist
502                     (cons (cons tag
503                                 (jde-javadoc-parse-tag tag docstring))
504                           tag-alist)))
505             (setq l (cdr l)))
506           ;; The 'throws' and 'exception' tags are equivalent, so
507           ;; their values are merged to allow access to 'exception'
508           ;; tag using 'throws' and vice versa.
509           (jde-javadoc-dynamic-status)
510           (setq throws-assoc (assoc "throws"    tag-alist))
511           (jde-javadoc-dynamic-status)
512           (setq except-assoc (assoc "exception" tag-alist))
513           (when (or throws-assoc except-assoc)
514             (jde-javadoc-dynamic-status)
515             (setq merged-values (append (cdr throws-assoc)
516                                         (cdr except-assoc)))
517             (jde-javadoc-dynamic-status)
518             (if throws-assoc
519                 (setcdr throws-assoc merged-values)
520               (setq tag-alist (cons (cons "throws"    merged-values)
521                                     tag-alist)))
522             (jde-javadoc-dynamic-status)
523             (if except-assoc
524                 (setcdr except-assoc merged-values)
525               (setq tag-alist (cons (cons "exception" merged-values)
526                                     tag-alist))))
527           (jde-javadoc-dynamic-status t))
528         (list docstring tag-list tag-alist))))
529
530 ;; Handling of javadoc comment parsed tree
531 ;;
532 (defmacro jde-javadoc-doctree-docstring (doctree)
533   "Return the docstring part of DOCTREE."
534   `(car ,doctree))
535
536 (defmacro jde-javadoc-doctree-tag-list (doctree)
537   "Return the tag-list part of DOCTREE."
538   `(car (cdr ,doctree)))
539
540 (defmacro jde-javadoc-doctree-tag-value-alist (doctree)
541   "Return the tag-value-alist part of DOCTREE."
542   `(car (cdr (cdr ,doctree))))
543
544 (defun jde-javadoc-doctree-tag (doctree tag &optional name)
545   "Return from DOCTREE the list of TAG values.
546 If optional NAME is non-nil return its specific value."
547   (let ((doc (cdr
548               (assoc
549                tag
550                (jde-javadoc-doctree-tag-value-alist doctree)))))
551     (and doc
552          name
553          (setq doc (rassoc name doc))
554          (setq doc (list doc)))
555     doc))
556
557 (defun jde-javadoc-doctree-known-tag-list (doctree)
558   "Return the list of known tags in DOCTREE .
559 That is tags in `semantic-java-doc-line-tags'."
560   (delq nil
561         (mapcar (function
562                  (lambda (tag)
563                    (and (member tag semantic-java-doc-line-tags)
564                         tag)))
565                 (jde-javadoc-doctree-tag-list doctree))))
566
567 (defun jde-javadoc-doctree-unknown-tag-list (doctree)
568   "Return the list of unknown tags in DOCTREE .
569 That is tags not in `semantic-java-doc-line-tags'."
570   (delq nil
571         (mapcar (function
572                  (lambda (tag)
573                    (and (not (member tag semantic-java-doc-line-tags))
574                         tag)))
575                 (jde-javadoc-doctree-tag-list doctree))))
576
577 ;;;; semantic tags stuff
578 ;;;; ---------------------
579
580 (defun jde-javadoc-tag-doctree (tag)
581   "Return the parsed documentation tree from TAG."
582   (jde-javadoc-parse-docstring
583    (semantic-documentation-for-tag tag t)))
584
585 (defun jde-javadoc-replace-documentation (tag &optional docstring)
586   "Replace TAG documentation with DOCSTRING.
587 If DOCSTRING is nil just delete the existing documentation."
588   (let* ((comment (semantic-documentation-for-tag tag 'flex))
589          start end)
590     (when comment
591       (set-buffer (semantic-tag-buffer tag))
592       (setq start (semantic-lex-token-start comment))
593       (setq end   (semantic-lex-token-end   comment))
594       (goto-char start)
595       (save-excursion
596         (goto-char end)
597         (jde-javadoc-skip-spaces-forward)
598         (delete-region start (point))
599         (when docstring
600           (insert docstring)
601           (jde-javadoc-indent-documentation tag))))))
602   
603 (defun jde-javadoc-delete-documentation (tag &optional noconfirm)
604   "Delete TAG documentation.
605 Require confirmation if optional NOCONFIRM is non-nil.  Return non-nil
606 if done."
607   (if (or noconfirm
608           (y-or-n-p (format "Delete '%s' previous documentation? "
609                             (semantic-tag-name tag))))
610       (progn
611         (jde-javadoc-replace-documentation tag)
612         t)))
613
614 (defun jde-javadoc-recenter-documentation (tag &optional arg)
615   "Center TAG documentation in window and redisplay frame.
616 With ARG, put point on line ARG.  See also `recenter'."
617   (let ((comment (semantic-documentation-for-tag tag 'flex))
618         start)
619     (if (not comment)
620         (setq start (semantic-tag-start tag))
621       (set-buffer (semantic-tag-buffer tag))
622       (setq start (semantic-lex-token-start comment)))
623     (goto-char start)
624     (recenter arg)))
625
626 (defun jde-javadoc-indent-documentation (tag)
627   "Indent TAG documentation."
628   (save-excursion
629     (let ((comment (semantic-documentation-for-tag tag 'flex))
630           start end)
631       (when comment
632         (set-buffer (semantic-tag-buffer tag))
633         (setq start (semantic-lex-token-start comment))
634         (setq end   (semantic-lex-token-end   comment))
635         (goto-char end)
636         (jde-javadoc-skip-spaces-forward)
637         (jde-javadoc-indent-region start (point))))))
638
639 ;;;; Doc checker
640 ;;;; -----------
641
642 (defconst jde-javadoc-checker-report-buffer "*jde-javadoc-checker*"
643   "Name of the checker report buffer.")
644
645 (defvar jde-javadoc-checker-tag nil
646   "Current checked tag.
647 Local to checker report buffer.")
648
649 (defvar jde-javadoc-checker-buffer nil
650   "Current checked buffer.
651 Local to checker report buffer.")
652
653 (condition-case nil
654     (require 'jde-java-font-lock)
655   (error nil))
656  
657 (defvar jde-javadoc-checker-report-font-lock-keywords
658   (list
659    ;; References
660    (list "`\\(.*\\)'"
661          1 'font-lock-warning-face)
662    ;; Javadoc tags
663    (list "\\(@[^ \n\r\t]+\\)"
664          1 (cond ((boundp 'jde-java-font-lock-doc-tag-face)
665                   'jde-java-font-lock-doc-tag-face)
666                  ((featurep 'xemacs)
667                   'font-lock-keyword-face)
668                  (t
669                   'font-lock-constant-face)))
670    ;; Misc.
671    (list "\\[\\([fnpq]\\)\\]"
672          1 'font-lock-keyword-face)
673    )
674   "Keywords used to highlight the checker report buffer.")
675
676 (defvar jde-javadoc-checker-report-mode-map nil
677   "Keymap used in `jde-javadoc-checker-report-mode'.")
678
679 (if jde-javadoc-checker-report-mode-map
680     ()
681   (let ((keymap (make-sparse-keymap)))
682     (define-key keymap "q" 'jde-javadoc-checker-quit)
683     (define-key keymap "p" 'jde-javadoc-checker-previous)
684     (define-key keymap "n" 'jde-javadoc-checker-next)
685     (setq jde-javadoc-checker-report-mode-map keymap)))
686
687 (defun jde-javadoc-checker-report-mode ()
688   "Mode used in checker report buffer.
689 \\{jde-javadoc-checker-report-mode-map}"
690   (kill-all-local-variables)
691   (setq major-mode 'jde-javadoc-checker-report-mode)
692   (setq mode-name "jde-javadoc-checker")
693   (set (make-local-variable 'paragraph-start)
694        "[ \t]*$")
695   (set (make-local-variable 'paragraph-separate)
696        paragraph-start)
697   (set (make-local-variable 'font-lock-defaults)
698        '((jde-javadoc-checker-report-font-lock-keywords)
699          t t ((?_ . "w"))))
700   (use-local-map jde-javadoc-checker-report-mode-map)
701   (turn-on-font-lock))
702
703 (defun jde-javadoc-checker-show-report (report tag)
704   "Show the `jde-javadoc-checker' REPORT for TAG."
705   (let ((buffer (semantic-tag-buffer tag)))
706     (with-current-buffer
707         (get-buffer-create jde-javadoc-checker-report-buffer)
708       (setq buffer-read-only nil)
709       (erase-buffer)
710       (jde-javadoc-checker-report-mode)
711       (set (make-local-variable 'jde-javadoc-checker-buffer) buffer)
712       (set (make-local-variable 'jde-javadoc-checker-tag)  tag)
713       (cond
714        (report
715         (define-key (current-local-map) "f" 'jde-javadoc-checker-fix)
716         (insert (car report))
717         (newline 2)
718         (mapcar (function
719                  (lambda (line)
720                    (let* ((from (point))
721                           (to (progn
722                                 (fill-region
723                                  (point)
724                                  (progn
725                                    (insert "  " line)
726                                    (newline)
727                                    (point)))
728                                 (point))))
729                      (goto-char from)
730                      (delete-char 1)
731                      (insert-char ?\* 1)
732                      (goto-char to))))
733                 (cdr report))
734         (newline)
735         (insert "[f]-try to fix  ")
736         )
737        (t
738         (define-key (current-local-map) "f" nil)
739         (insert "Documentation is up-to-date")
740         (newline 2)))
741       (insert "[p]-check previous  [n]-check next  [q]-quit")
742       (goto-char (point-min))
743       (setq buffer-read-only t)
744       (pop-to-buffer (current-buffer))
745       (jde-javadoc-adjust-window
746        (get-buffer-window (current-buffer)))
747       (sit-for 0)
748       (save-selected-window
749         (let ((window (get-buffer-window buffer)))
750           (if (not window)
751               nil
752             (select-window window)
753             (goto-char (semantic-tag-start tag))
754             (jde-javadoc-skip-spaces-forward)
755             (when (looking-at "/\\*\\*")
756               (forward-comment 1)
757               (jde-javadoc-skip-spaces-forward))
758             (recenter -4))))
759       (semantic-momentary-highlight-tag tag))))
760
761 (defun jde-javadoc-check-add-summary (report type name)
762   "Add a summary to REPORT error list, using tag TYPE and NAME."
763   (and (setq report (delq nil report))  ;; Clear empty entries
764        (let* ((count (length report))
765               (eword (if (= count 1) "error" "errors")))
766          (cons (format "%s `%s' has %d documentation %s:"
767                        type name count eword)
768                (nreverse report)))))
769
770 ;; Basic doc checkers
771 ;;
772 (defun jde-javadoc-check-description (doctree)
773   "Return a message if DOCTREE does not contain a description."
774   (if (jde-javadoc-doctree-tag doctree jde-javadoc-desc-tag)
775       nil
776     "Missing description"))
777
778 (defun jde-javadoc-check-required-tags (doctree allowed extra
779                                                 &rest nocheck)
780   "Return a message if DOCTREE is missing a required tag.
781 ALLOWED and EXTRA are respectively the listes of allowed tags and
782 optional ones.  Optional arguments NOCHECK can be a listes of tags
783 that are not checked."
784   (let (tag missing)
785     (while allowed
786       (setq tag     (car allowed)
787             allowed (cdr allowed))
788       (or (member tag extra)
789           (member tag nocheck)
790           (let ((ignored nocheck) ignore)
791             (while (and (not ignore) ignored)
792               (setq ignore  (member tag (car ignored))
793                     ignored (cdr ignored)))
794             ignore)
795 ;;          (member tag semantic-java-doc-with-name-tags)
796           (jde-javadoc-doctree-tag doctree tag)
797           (setq missing (cons tag missing))))
798     (if missing
799         (concat "Missing tag"
800                 (if (> (length missing) 1) "s @" " @")
801                 (mapconcat 'identity missing ", @")))))
802
803 (defun jde-javadoc-check-suggest-tag-order (tag-list reference)
804   "Return a list of tags in suggested order from TAG-LIST.
805 REFERENCE is the list of tags allowed."
806   (let (otl utl)
807     (while tag-list
808       (if (member (car tag-list) semantic-java-doc-line-tags)
809           (and (member (car tag-list) reference)
810                (add-to-list 'otl (car tag-list)))
811         (add-to-list 'utl (car tag-list)))
812       (setq tag-list (cdr tag-list)))
813     (append (sort otl #'semantic-java-doc-keyword-before-p)
814             (nreverse utl))))
815
816 (defun jde-javadoc-check-tag-ordered (doctree reference)
817   "Return a message if tags in DOCTREE are not correctly ordered.
818 REFERENCE is the list of allowed tags in correct order.  See variable
819 `semantic-java-doc-line-tags'."
820   (let* ((tag-list (jde-javadoc-doctree-tag-list doctree))
821          (tag      (car tag-list))
822          (l        (cdr tag-list))
823          (ok       t))
824     (while (and l ok)
825       (jde-javadoc-dynamic-status)
826       (setq ok  (semantic-java-doc-keyword-before-p tag (car l))
827             tag (car l)
828             l   (cdr l)))
829     (if ok
830         nil
831       (concat "Recommended tag order is @"
832               (mapconcat 'identity
833                          (jde-javadoc-check-suggest-tag-order
834                           tag-list reference)
835                          ", @")))))
836
837 (defun jde-javadoc-check-tag-allowed (doctree allowed)
838   "Return a message if some tags in DOCTREE are not in ALLOWED.
839 Third party tags (not in `semantic-java-doc-line-tags') are allways
840 allowed."
841   (let ((invalids
842          (delq nil
843                (mapcar
844                 (function
845                  (lambda (tag)
846                    (jde-javadoc-dynamic-status)
847                    (and (member tag semantic-java-doc-line-tags)
848                         (not (member tag allowed))
849                         tag)))
850                 (jde-javadoc-doctree-tag-list doctree)))))
851     (if (not invalids)
852         nil
853       (concat "Invalid tag"
854               (if (> (length invalids) 1) "s @" " @")
855               (mapconcat 'identity invalids ", @")))))
856
857 ;; Tag based doc checkers
858 ;;
859 (defun jde-javadoc-check-type (tag doctree)
860   "Check doc of 'type' (class or interface) TAG.
861 DOCTREE is the current doctree of TAG.  Return a non-nil report if
862 errors were found."
863   (let ((name (semantic-tag-name tag))
864         (type (semantic-tag-type tag))
865         (main (jde-javadoc-checker-main-type-p tag))
866         report)
867     ;; Check for missing description
868     (jde-javadoc-dynamic-status)
869     (setq report
870           (cons
871            (jde-javadoc-check-description doctree)
872            report))
873     ;; Check for missing tags
874     (jde-javadoc-dynamic-status)
875     (setq report
876           (cons
877            (jde-javadoc-check-required-tags
878             doctree semantic-java-doc-type-tags
879             semantic-java-doc-extra-type-tags
880             (if main
881                 nil
882               ;; Don't check these tags if internal type.
883               '("author" "version" "since")))
884            report))
885     ;; Check for incorrect tag order
886     (jde-javadoc-dynamic-status)
887     (setq report
888           (cons
889            (jde-javadoc-check-tag-ordered
890             doctree semantic-java-doc-type-tags)
891            report))
892     ;; Check for invalid tags
893     (jde-javadoc-dynamic-status)
894     (setq report
895           (cons
896            (jde-javadoc-check-tag-allowed
897             doctree semantic-java-doc-type-tags)
898            report))
899     ;; Setup the error summary
900     (jde-javadoc-dynamic-status)
901     (jde-javadoc-check-add-summary report type name)))
902
903 (defun jde-javadoc-check-variable (tag doctree)
904   "Check doc of 'variable' (field) TAG.
905 DOCTREE is the current doctree of TAG.  Return a non-nil report if
906 errors were found."
907   (let ((name (semantic-tag-name tag))
908         report)
909     ;; Check for missing description
910     (jde-javadoc-dynamic-status)
911     (setq report
912           (cons
913            (jde-javadoc-check-description doctree)
914            report))
915     ;; Check for missing tags
916     (jde-javadoc-dynamic-status)
917     (setq report
918           (cons
919            (jde-javadoc-check-required-tags
920             doctree semantic-java-doc-variable-tags
921             semantic-java-doc-extra-variable-tags)
922            report))
923     ;; Check for incorrect tag order
924     (jde-javadoc-dynamic-status)
925     (setq report
926           (cons
927            (jde-javadoc-check-tag-ordered
928             doctree semantic-java-doc-variable-tags)
929            report))
930     ;; Check for invalid tags
931     (jde-javadoc-dynamic-status)
932     (setq report
933           (cons
934            (jde-javadoc-check-tag-allowed
935             doctree semantic-java-doc-variable-tags)
936            report))
937     ;; Setup the error summary
938     (jde-javadoc-dynamic-status)
939     (jde-javadoc-check-add-summary report "variable" name)))
940
941 (defun jde-javadoc-check-function (tag doctree)
942   "Check doc of 'function' (method or constructor) TAG.
943 DOCTREE is the current doctree of TAG.  Return a non-nil report if
944 errors were found."
945   (let ((name   (semantic-tag-name               tag))
946         (type   (semantic-tag-type               tag))
947         (args   (semantic-tag-function-arguments      tag))
948         (throws (semantic-tag-function-throws    tag))
949         report items item)
950     ;; Check for missing description
951     (jde-javadoc-dynamic-status)
952     (setq report
953           (cons
954            (jde-javadoc-check-description doctree)
955            report))
956     ;; Check for missing tags
957     (jde-javadoc-dynamic-status)
958     (setq report
959           (cons
960            (jde-javadoc-check-required-tags
961             doctree semantic-java-doc-function-tags
962             semantic-java-doc-extra-function-tags
963             ;; Don't check return, param and exception/throws tags.
964             '("return") semantic-java-doc-with-name-tags)
965            report))
966     ;; Check for missing @param tags
967     (setq items nil)
968     (while args
969       (jde-javadoc-dynamic-status)
970       (if (semantic-tag-p (car args))
971           (progn
972             (setq item (jde-javadoc-variable-name
973                         (semantic-tag-name (car args))))
974             (setq items (cons item items))
975             (or (jde-javadoc-doctree-tag doctree "param" item)
976                 (setq report
977                       (cons
978                        (format "Missing @param tag for `%s'" item)
979                        report)))))
980       (setq args (cdr args)))
981     ;; Check for extra @param tags
982     (setq args (jde-javadoc-doctree-tag doctree "param"))
983     (while args
984       (jde-javadoc-dynamic-status)
985       (setq item (jde-javadoc-variable-name (cdr (car args))))
986       (or (member item items)
987           (setq report (cons (format "Invalid @param tag `%s'" item)
988                              report)))
989       (setq args (cdr args)))
990     ;; Check for missing @exception tags
991     (setq items nil)
992     (while throws
993       (jde-javadoc-dynamic-status)
994       (setq item (car throws))
995       (setq items (cons item items))
996       (setq throws (cdr throws))
997       (or (jde-javadoc-doctree-tag doctree "exception" item)
998           (setq report
999                 (cons
1000                  (format "Missing @exception tag for `%s'" item)
1001                  report))))
1002     ;; Check for extra @exception tags
1003     (setq args (jde-javadoc-doctree-tag doctree "exception"))
1004     (while args
1005       (jde-javadoc-dynamic-status)
1006       (setq item (cdr (car args)))
1007       (or (member item items)
1008           (and jde-javadoc-check-undeclared-exception-flag
1009                (jde-javadoc-implicit-exception-p item))
1010           (setq report
1011                 (cons
1012                  (format
1013                   "Extra @exception tag `%s' (maybe not an error)"
1014                   item)
1015                  report)))
1016       (setq args (cdr args)))
1017     ;; Check for missing or extra @return tag
1018     (setq item (jde-javadoc-doctree-tag doctree "return"))
1019     (jde-javadoc-dynamic-status)
1020     (cond ((and (not type) item)
1021            (setq report (cons "Invalid @return tag for constructor"
1022                               report)))
1023           ((and type (string-equal type "void") item)
1024            (setq report (cons "Invalid @return tag for void method"
1025                               report)))
1026           ((and type (not (string-equal type "void")) (not item))
1027            (setq report (cons "Missing @return tag"
1028                               report))))
1029     ;; Check for incorrect tag order
1030     (jde-javadoc-dynamic-status)
1031     (setq report
1032           (cons
1033            (jde-javadoc-check-tag-ordered
1034             doctree semantic-java-doc-function-tags)
1035            report))
1036     ;; Check for invalid tags
1037     (jde-javadoc-dynamic-status)
1038     (setq report
1039           (cons
1040            (jde-javadoc-check-tag-allowed
1041             doctree semantic-java-doc-function-tags)
1042            report))
1043     ;; Setup the error summary
1044     (jde-javadoc-dynamic-status)
1045     (jde-javadoc-check-add-summary report
1046                                    (if type "method" "constructor")
1047                                    name)))
1048
1049 (defun jde-javadoc-checker (tag &optional noreport)
1050   "Call the javadoc checker associated to TAG.
1051 If optional NOREPORT is non-nil does not show error report.  Return a
1052 non-nil report if errors were found."
1053   (let* ((type    (semantic-tag-class tag))
1054          (checker (intern (format "jde-javadoc-check-%s" type))))
1055     (or (fboundp checker)
1056         (error "No checker found to process '%S' tag" type))
1057     (goto-char (semantic-tag-start tag))
1058     (recenter 1)
1059     (let (doctree report)
1060       (jde-javadoc-status-forms "Checking" "done"
1061         (jde-javadoc-dynamic-status)
1062         (setq doctree (jde-javadoc-tag-doctree tag))
1063         (setq report  (funcall checker tag doctree))
1064         (or noreport
1065             (jde-javadoc-checker-show-report report tag))
1066         (jde-javadoc-dynamic-status t))
1067       report)))
1068
1069 (defcustom jde-javadoc-checker-level 'protected
1070   "*Accessibility level to check.
1071 Only 'type, 'function or 'variable tags with this level will be
1072 checked.  The level is defined to be consistent with the javadoc show
1073 options.  That is:
1074
1075 - - public    - check only public classes and members.
1076 - - protected - check only protected and public classes and
1077                 members.  This is the default.
1078 - - package   - check only package, protected, and public classes
1079                 and members.
1080 - - private   - check all classes and members."
1081   :group 'jde-javadoc
1082   :type  '(choice :tag "level"
1083                   (const :tag "public"    public)
1084                   (const :tag "protected" protected)
1085                   (const :tag "package"   package)
1086                   (const :tag "private"   private)))
1087
1088 (defconst jde-javadoc-access-level-weights
1089   '((public    . 8)
1090     (protected . 4)
1091     (package   . 2)
1092     (private   . 0))
1093   "Java access level weights.")
1094
1095 (defun jde-javadoc-access-level-lower-p (l1 l2)
1096   "Return non-nil if access level L1 is lower than L2."
1097   (< (cdr (assq l1 jde-javadoc-access-level-weights))
1098      (cdr (assq l2 jde-javadoc-access-level-weights))))
1099          
1100 (defun jde-javadoc-tag-access-level (tag)
1101   "Return the access level of TAG.
1102 That is 'public 'package 'protected or 'private.  If TAG is included
1103 in other ones its access level is the lowest one found in the
1104 hierarchy."
1105   (let ((deps (semantic-find-tag-by-overlay
1106                (semantic-tag-start tag)
1107                (semantic-tag-buffer tag)))
1108         last-type tag categ modifiers levels)
1109     (while deps
1110       (setq tag (car deps))
1111       (setq deps  (cdr deps))
1112       (setq categ (semantic-tag-class tag))
1113       (setq modifiers
1114             (cond
1115              ((eq categ 'type)
1116               (setq last-type (semantic-tag-type tag))
1117               (semantic-tag-modifiers tag))
1118              ((eq categ 'function)
1119               (if (string-equal last-type "interface")
1120                   (list "public") ;; interface members are always public
1121                 (semantic-tag-modifiers tag)))
1122              ((eq categ 'variable)
1123               (if (string-equal last-type "interface")
1124                   (list "public") ;; interface members are always public
1125                 (semantic-tag-modifiers tag)))
1126              (t ;; must never occurs
1127               (error "Invalid %s tag" categ))))
1128       (setq levels
1129             (cons (cond ((member "public" modifiers)
1130                          'public)
1131                         ((member "protected" modifiers)
1132                          'protected)
1133                         ((member "private" modifiers)
1134                          'private)
1135                         (t
1136                          'package))
1137                   levels)))
1138     (car (sort levels 'jde-javadoc-access-level-lower-p))))
1139
1140 (defun jde-javadoc-checker-at-level-p (tag)
1141   "Return non-nil if checking is allowed for TAG.
1142 That is TAG accessibility level is greater than or equal to the one
1143 specified by `jde-javadoc-checker-level'.  TAG category must be
1144 'type, 'function or 'variable."
1145   (let ((level (or jde-javadoc-checker-level 'protected)))
1146     ;; if level is 'private check all
1147     (or (eq level 'private)
1148         ;; else check if tag access level >= checker level
1149         (not (jde-javadoc-access-level-lower-p
1150               (jde-javadoc-tag-access-level tag)
1151               level)))))
1152
1153 (defun jde-javadoc-checker-main-type-p (&optional tag)
1154   "Return non-nil if TAG is a main type one.
1155 That is not an internal class or interface."
1156   (setq tag (or tag (semantic-current-tag)))
1157   (and (eq (semantic-tag-class tag) 'type)
1158        (memq tag (semantic-brute-find-tag-by-class
1159                     'type (current-buffer)))))
1160
1161 (defun jde-javadoc-checker-do-find-previous-tag (tags &optional
1162                                                           tag prev)
1163   "Visit TAGS and return the tag before TAG.
1164 PREV is the last tag visited or nil at start.  If TAG is nil
1165 return the last tag found.  Return only a 'type 'function or
1166 'variable tag."
1167   (let (current categ)
1168     (while tags
1169       (setq current (car tags))
1170       (setq tags  (cdr tags))
1171       (setq categ   (semantic-tag-class current))
1172       (if (memq categ '(type function variable))
1173           (cond
1174            ((null tag)
1175             (if (null tags)
1176                 (throw 'found prev)))
1177            ((>= (semantic-tag-start current)
1178                 (semantic-tag-start tag))
1179             (throw 'found prev))
1180            (t
1181             (setq prev
1182                   (if (eq categ 'type)
1183                       (jde-javadoc-checker-do-find-previous-tag
1184                        (semantic-tag-type-members current)
1185                        tag current)
1186                     current))))
1187         ))
1188     prev))
1189
1190 (defun jde-javadoc-checker-find-previous-tag (tags
1191                                                 &optional tag)
1192   "Visit TAGS and return the tag before TAG.
1193 If TAG is nil return the last tag found.  Return only a 'type
1194 'function or 'variable tag."
1195   (catch 'found
1196     (jde-javadoc-checker-do-find-previous-tag tags tag)))
1197
1198 (defun jde-javadoc-checker-find-next-tag (tags &optional tag)
1199   "Visit TAGS and return the tag following TAG.
1200 If TAG is nil return the first tag found.  Return only a 'type
1201 'function or 'variable tag."
1202   (let (current next categ)
1203     (while (and tags (not next))
1204       (setq current (car tags))
1205       (setq categ   (semantic-tag-class current))
1206       (if (memq categ '(type function variable))
1207           (if (or (null tag)
1208                   (> (semantic-tag-start current)
1209                      (semantic-tag-start tag)))
1210               (setq next current)
1211             (if (eq categ 'type)
1212                 (setq next (jde-javadoc-checker-find-next-tag
1213                             (semantic-tag-type-members current)
1214                             tag)))))
1215       (setq tags (cdr tags)))
1216     next))
1217
1218 (defun jde-javadoc-checker-previous-tag (buffer &optional tag)
1219   "Report the previous tag in BUFFER with documentation errors.
1220 Start checking before TAG if non-nil or at the last tag found."
1221   (pop-to-buffer buffer)
1222   (let* ((tags (semantic-fetch-tags))
1223          (prev   (jde-javadoc-checker-find-previous-tag
1224                   tags tag))
1225          (report (and prev
1226                       (jde-javadoc-checker-at-level-p prev)
1227                       (jde-javadoc-checker prev t))))
1228     (while (and prev (not report))
1229       (setq prev   (jde-javadoc-checker-find-previous-tag
1230                     tags prev))
1231       (setq report (and prev
1232                         (jde-javadoc-checker-at-level-p prev)
1233                         (jde-javadoc-checker prev t))))
1234     (if report
1235         (jde-javadoc-checker-show-report report prev)
1236       (if tag
1237           (if (y-or-n-p "No more doc error found.  Quit? ")
1238               (jde-javadoc-checker-quit)
1239             (jde-javadoc-checker tag))
1240         (message "No doc errors found")
1241         (jde-javadoc-checker-quit)))))
1242                         
1243 (defun jde-javadoc-checker-next-tag (buffer &optional tag)
1244   "Report the next tag in BUFFER with documentation errors.
1245 Start checking after TAG if non-nil or at the first tag found."
1246   (pop-to-buffer buffer)
1247   (let* ((tags (semantic-fetch-tags))
1248          (next   (jde-javadoc-checker-find-next-tag tags tag))
1249          (report (and next
1250                       (jde-javadoc-checker-at-level-p next)
1251                       (jde-javadoc-checker next t))))
1252     (while (and next (not report))
1253       (setq next   (jde-javadoc-checker-find-next-tag tags next))
1254       (setq report (and next
1255                         (jde-javadoc-checker-at-level-p next)
1256                         (jde-javadoc-checker next t))))
1257     (if report
1258         (jde-javadoc-checker-show-report report next)
1259       (if tag
1260           (if (y-or-n-p "No more doc error found.  Quit? ")
1261               (jde-javadoc-checker-quit)
1262             (jde-javadoc-checker tag))
1263         (message "No doc errors found")
1264         (jde-javadoc-checker-quit)))))
1265                         
1266 ;;;; Doc generator
1267 ;;;; -------------
1268
1269 (defun jde-javadoc-insert (*name* &rest *texts*)
1270   "Insert the template *NAME* or *TEXTS* and a newline.
1271 If *NAME* value is nil *TEXTS* are inserted if non-nil.  If *NAME* and
1272 *TEXTS* are nil the function does nothing.
1273 The name of variables local to this function are enclosed between
1274 \"*\" to avoid conflicts with variables used in templates."
1275   (cond ((and *name* (symbolp *name*) (symbol-value *name*))
1276          (tempo-insert-template *name* nil)
1277          (newline))
1278         (*texts*
1279          (apply #'insert *texts*)
1280          (newline))))
1281
1282 ;; Basic generators
1283 ;;
1284 (defun jde-javadoc-insert-start-block ()
1285   "Insert a javadoc comment block start '/**' at point."
1286   (jde-javadoc-insert nil "/**"))
1287   
1288 (defun jde-javadoc-insert-empty-line ()
1289   "Insert an empty javadoc line '*'."
1290   (jde-javadoc-insert nil "*"))
1291   
1292 (defun jde-javadoc-insert-end-block (&optional indent)
1293   "Insert a javadoc end comment block."
1294   (jde-javadoc-insert 'tempo-template-jde-javadoc-end-block "*/")
1295   (if indent
1296       (jde-javadoc-indent-line))
1297   nil) ;; must return nil to prevent template insertion.
1298
1299 (defun jde-javadoc-insert-previous-description (doctree)
1300   "Insert a javadoc description if it already exists in DOCTREE."
1301   (let ((previous (jde-javadoc-doctree-tag
1302                    doctree jde-javadoc-desc-tag)))
1303     (if previous
1304         (jde-javadoc-insert
1305          nil
1306          "/**"
1307          (jde-javadoc-normalize-description (car (car previous)))))
1308     previous))
1309
1310 (defun jde-javadoc-insert-previous-tag (doctree tag &optional key)
1311   "If it already exists in DOCTREE, insert javadoc TAG value(s).
1312 If optional KEY is non-nil insert its specific value."
1313   (let ((previous (jde-javadoc-doctree-tag doctree tag key)))
1314     (if previous
1315         (jde-javadoc-map
1316          (function
1317           (lambda (item)
1318             (jde-javadoc-dynamic-status)
1319             (jde-javadoc-insert nil "* @" tag (car item))))
1320          previous))
1321     previous))
1322
1323 (defun jde-javadoc-insert-unknown-tags (doctree)
1324   "Insert unknown tags found in DOCTREE.
1325 See `jde-javadoc-doctree-unknown-tag-list'."
1326   (jde-javadoc-map
1327    (function
1328     (lambda (tag)
1329       (jde-javadoc-dynamic-status)
1330       (jde-javadoc-insert-previous-tag doctree tag)))
1331    (jde-javadoc-doctree-unknown-tag-list doctree)))
1332
1333 (defun jde-javadoc-insert-author-tag (doctree)
1334   "Insert javadoc @author tags.
1335 If tags already exist in DOCTREE keep them, else insert a new default
1336 one."
1337   (or (jde-javadoc-insert-previous-tag doctree "author")
1338       (jde-javadoc-insert 'tempo-template-jde-javadoc-author-tag)))
1339
1340 ;; (defun jde-javadoc-insert-since-tag (doctree)
1341 ;;   "Insert a javadoc @since tag.
1342 ;; If tag already exists in DOCTREE keep it, else insert a new default
1343 ;; one."
1344 ;;   (or (jde-javadoc-insert-previous-tag doctree "since")
1345 ;;       (jde-javadoc-insert 'tempo-template-jde-javadoc-since-tag)))
1346
1347 (defun jde-javadoc-insert-version-tag (doctree)
1348   "Insert a javadoc @version tag.
1349 If tag already exists in DOCTREE keep it, else insert a new default
1350 one."
1351   (or (jde-javadoc-insert-previous-tag doctree "version")
1352       (jde-javadoc-insert 'tempo-template-jde-javadoc-version-tag)))
1353
1354 ;; (defun jde-javadoc-insert-see-tag (doctree refs)
1355 ;;   "Insert javadoc @see tags.
1356 ;; If tags already exist in DOCTREE keep them, else insert a new
1357 ;; default one for each item in REFS."
1358 ;;   (or (jde-javadoc-insert-previous-tag doctree "see")
1359 ;;       (jde-javadoc-map
1360 ;;        (function
1361 ;;         (lambda (ref)
1362 ;;           (and ref (not (string= ref ""))
1363 ;;                (jde-javadoc-insert
1364 ;;                 'tempo-template-jde-javadoc-see-tag))))
1365 ;;        refs)))
1366
1367 (defun jde-javadoc-insert-param-tag (doctree type name)
1368   "Insert a javadoc @param tag.
1369 If tag already exists in DOCTREE keep it, else insert a new default
1370 one using parameter TYPE and NAME."
1371   (or (jde-javadoc-insert-previous-tag doctree "param" name)
1372       (and type (not (string= type ""))
1373            name (not (string= name ""))
1374            (jde-javadoc-insert
1375             'tempo-template-jde-javadoc-param-tag))))
1376
1377 (defun jde-javadoc-insert-exception-tag (doctree types)
1378   "Insert javadoc @exception tags.
1379 If tags already exist in DOCTREE keep them, else insert a new default
1380 one for each exception in TYPES."
1381   (jde-javadoc-map
1382    (function
1383     (lambda (type)
1384       (jde-javadoc-dynamic-status)
1385       (or (jde-javadoc-insert-previous-tag doctree "exception" type)
1386           (and type (not (string= type ""))
1387                (jde-javadoc-insert
1388                 'tempo-template-jde-javadoc-exception-tag)))))
1389    types)
1390   ;; Keep extra exception tags (maybe not invalid tags)
1391   (jde-javadoc-map
1392    (function
1393     (lambda (type)
1394       (jde-javadoc-dynamic-status)
1395       (setq type (cdr type))
1396       (or (member type types)
1397           (if (or (not jde-javadoc-check-undeclared-exception-flag)
1398                   (jde-javadoc-implicit-exception-p type))
1399               (jde-javadoc-insert-previous-tag
1400                doctree "exception" type)))))
1401    (jde-javadoc-doctree-tag doctree "exception")))
1402
1403 (defun jde-javadoc-insert-return-tag (doctree type)
1404   "Insert a javadoc @return tag.
1405 If tag already exists in DOCTREE keep it, else insert a new default
1406 one using return TYPE."
1407   (and type (not (string= type "void"))
1408        (or (jde-javadoc-insert-previous-tag doctree "return")
1409            (jde-javadoc-insert
1410             'tempo-template-jde-javadoc-return-tag))))
1411
1412 (defun jde-javadoc-insert-field-desc (doctree modifiers type name)
1413   "Insert a field description.
1414 If a description already exists in DOCTREE keep it, else insert a
1415 default one using field MODIFIERS TYPE and NAME."
1416   (if (jde-javadoc-insert-previous-description doctree)
1417       nil
1418     (jde-javadoc-insert-start-block)
1419     (jde-javadoc-insert 'tempo-template-jde-javadoc-describe-field)
1420     (jde-javadoc-insert-empty-line)))
1421
1422 (defun jde-javadoc-insert-function-desc (doctree type name)
1423   "Insert a method or constructor description.
1424 If a description already exists in DOCTREE keep it, else insert a
1425 default one using method TYPE and NAME.  If TYPE is nil insert a
1426 default constructor description."
1427   (if (jde-javadoc-insert-previous-description doctree)
1428       nil
1429     (jde-javadoc-insert-start-block)
1430     (if (and name (not (string= name "")))
1431         (jde-javadoc-insert
1432          (if (and type (not (string= type "")))
1433              'tempo-template-jde-javadoc-describe-method
1434            'tempo-template-jde-javadoc-describe-constructor)))
1435     (jde-javadoc-insert-empty-line)))
1436
1437 (defun jde-javadoc-insert-class-desc (doctree name)
1438   "Insert a class description.
1439 If a description already exists in DOCTREE keep it, else insert a
1440 default one using class NAME."
1441   (if (jde-javadoc-insert-previous-description doctree)
1442       nil
1443     (jde-javadoc-insert-start-block)
1444     (jde-javadoc-insert 'tempo-template-jde-javadoc-describe-class)
1445     (jde-javadoc-insert-empty-line)))
1446
1447 (defun jde-javadoc-insert-interface-desc (doctree name)
1448   "Insert an interface description.
1449 If a description already exists in DOCTREE keep it, else insert a
1450 default one using interface NAME."
1451   (if (jde-javadoc-insert-previous-description doctree)
1452       nil
1453     (jde-javadoc-insert-start-block)
1454     (jde-javadoc-insert
1455      'tempo-template-jde-javadoc-describe-interface)
1456     (jde-javadoc-insert-empty-line)))
1457
1458 ;; Main generators
1459 ;;
1460 (defun jde-javadoc-type-doc (modifiers type name parents main
1461                                        &optional doctree)
1462   "Document a class or interface using MODIFIERS TYPE NAME PARENTS.
1463 If MAIN is non-nil this is a main class or interface (not internal).
1464 If description and tags already exist in DOCTREE keep them."
1465   ;; description
1466   (jde-javadoc-dynamic-status)
1467   (if (string-equal type "interface")
1468       (jde-javadoc-insert-interface-desc doctree name)
1469     (jde-javadoc-insert-class-desc doctree name))
1470   (when main
1471     ;; author
1472     (jde-javadoc-dynamic-status)
1473     (jde-javadoc-insert-author-tag doctree)
1474     ;; version
1475     (jde-javadoc-dynamic-status)
1476     (jde-javadoc-insert-version-tag doctree))
1477   ;; Keep extra optional tags if they already exist
1478   (jde-javadoc-dynamic-status)
1479   (jde-javadoc-map (function
1480                     (lambda (tag)
1481                       (jde-javadoc-insert-previous-tag doctree tag)))
1482                    semantic-java-doc-extra-type-tags)
1483   ;; Keep unknown (not Sun's) tags
1484   (jde-javadoc-insert-unknown-tags doctree)
1485   ;; The end of comment block
1486   (jde-javadoc-dynamic-status)
1487   (jde-javadoc-insert-end-block t))
1488
1489 (defun jde-javadoc-variable-doc (modifiers type name
1490                                            &optional doctree)
1491   "Document a field using MODIFIERS TYPE NAME.
1492 If description and tags already exist in DOCTREE keep them."
1493   ;; description
1494   (jde-javadoc-insert-field-desc doctree modifiers type name)
1495   ;; Keep extra optional tags if they already exist
1496   (jde-javadoc-map (function
1497                     (lambda (tag)
1498                       (jde-javadoc-insert-previous-tag doctree tag)))
1499                    semantic-java-doc-extra-variable-tags)
1500   ;; Keep unknown (not Sun's) tags
1501   (jde-javadoc-insert-unknown-tags doctree)
1502   ;; The end of comment block
1503   (jde-javadoc-insert-end-block t))
1504
1505 (defun jde-javadoc-function-args-doc (tags &optional doctree)
1506   "Document function arguments in TAGS.
1507 If tags already exist in DOCTREE keep them."
1508   (jde-javadoc-map
1509    (function
1510     (lambda (tag)
1511       (if (semantic-tag-p tag)      ; because TAGS can be (nil)
1512           (let ((modifiers (semantic-tag-modifiers tag))
1513                 (type      (semantic-tag-type               tag))
1514                 (name      (semantic-tag-name               tag)))
1515             (jde-javadoc-insert-param-tag doctree type name)))))
1516    tags))
1517       
1518 (defun jde-javadoc-function-doc (modifiers type name args throws
1519                                            &optional doctree)
1520   "Document a function using MODIFIERS TYPE NAME ARGS THROWS.
1521 If description and tags already exist in DOCTREE keep them."
1522   ;; description
1523   (jde-javadoc-insert-function-desc doctree type name)
1524   ;; param
1525   (jde-javadoc-function-args-doc args doctree)
1526   ;; return
1527   (jde-javadoc-insert-return-tag doctree type)
1528   ;; exception
1529   (jde-javadoc-insert-exception-tag doctree throws)
1530   ;; Keep extra optional tags if they already exist
1531   (jde-javadoc-map (function
1532                     (lambda (tag)
1533                       (jde-javadoc-insert-previous-tag doctree tag)))
1534                    semantic-java-doc-extra-function-tags)
1535   ;; Keep unknown (not Sun's) tags
1536   (jde-javadoc-insert-unknown-tags doctree)
1537   ;; The end of comment block
1538   (jde-javadoc-insert-end-block t))
1539
1540 ;; Main tag based generators
1541 ;;
1542 (defun jde-javadoc-type (tag doctree)
1543   "Document a 'type' (class or interface) TAG.
1544 DOCTREE is the current doctree of TAG."
1545   (let ((modifiers  (semantic-tag-modifiers tag))
1546         (type       (semantic-tag-type               tag))
1547         (name       (semantic-tag-name               tag))
1548         (parents    (semantic-tag-type-superclasses  tag))
1549         (main       (jde-javadoc-checker-main-type-p tag)))
1550     (jde-javadoc-dynamic-status)
1551     (jde-javadoc-type-doc modifiers type name parents main doctree)))
1552
1553 (defun jde-javadoc-variable (tag doctree)
1554   "Document a 'variable' (field) TAG.
1555 DOCTREE is the current doctree of TAG."
1556   (let ((modifiers  (semantic-tag-modifiers tag))
1557         (type       (semantic-tag-type               tag))
1558         (name       (semantic-tag-name               tag)))
1559     (jde-javadoc-dynamic-status)
1560     (jde-javadoc-variable-doc modifiers type name doctree)))
1561
1562 (defun jde-javadoc-function (tag doctree)
1563   "Document a 'function' (method or constructor) TAG.
1564 DOCTREE is the current doctree of TAG."
1565   (let ((modifiers  (semantic-tag-modifiers tag))
1566         (type       (semantic-tag-type               tag))
1567         (name       (semantic-tag-name               tag))
1568         (args       (semantic-tag-function-arguments tag))
1569         (throws     (semantic-tag-function-throws    tag)))
1570     (jde-javadoc-dynamic-status)
1571     (jde-javadoc-function-doc
1572      modifiers type name args throws doctree)))
1573
1574 (defun jde-javadoc-generator (tag &optional noconfirm)
1575   "Call the javadoc generator associated to TAG.
1576 Require confirmation to delete existing documentation if optional
1577 NOCONFIRM is non-nil."
1578   (let* ((type      (semantic-tag-class tag))
1579          (generator (intern (format "jde-javadoc-%s" type)))
1580          (checker   (intern (format "jde-javadoc-check-%s" type))))
1581     (or (fboundp generator)
1582         (error "No generator found to process '%S' tag" type))
1583     (goto-char (semantic-tag-start tag))
1584     (let ((report t) doctree)
1585       (jde-javadoc-status-forms "Updating" "done"
1586         (jde-javadoc-dynamic-status)
1587         (setq doctree (jde-javadoc-tag-doctree tag))
1588         (if (and (fboundp checker)
1589                  (not (funcall checker tag doctree)))
1590             (setq report nil)
1591           (let ((seas semantic-edits-are-safe))
1592             (make-local-variable 'semantic-edits-are-safe)
1593             (unwind-protect
1594                 (progn
1595                   (setq semantic-edits-are-safe t)
1596                   (when (or (not doctree)
1597                             (jde-javadoc-delete-documentation
1598                              tag noconfirm))
1599                     (funcall generator tag doctree)
1600                     (jde-javadoc-indent-documentation tag)))
1601               (setq semantic-edits-are-safe seas))))
1602         (jde-javadoc-dynamic-status t))
1603       (or report
1604           (message "Documentation is up-to-date")))))
1605
1606 ;;;; Misc command auxiliaries
1607 ;;;; ------------------------
1608
1609 (defun jde-javadoc-nonterminal-at-line ()
1610   "Search the bovine table for the tag at the current line."
1611   (save-excursion
1612     ;; Preserve current tags when the lexer fails (when there is an
1613     ;; unclosed block or an unterminated string for example).
1614     (let ((semantic-flex-unterminated-syntax-end-function
1615            #'(lambda (syntax &rest ignore)
1616                (throw 'jde-javadoc-flex-error syntax))))
1617       (catch 'jde-javadoc-flex-error
1618         (semantic-fetch-tags))))
1619   (save-excursion
1620     ;; Move the point to the first non-blank character found.  Skip
1621     ;; spaces, tabs and newlines.
1622     (beginning-of-line)
1623 ;;    (jde-javadoc-skip-spaces-forward)
1624     (forward-comment (point-max))
1625     (semantic-current-tag)))
1626
1627 (defvar jde-javadoc-checkdoc-excursion nil
1628   "Window configuration and point before running doc checker.")
1629 ;; Maybe `jde-javadoc-checkdoc-excursion' could be made buffer local?
1630 ;;(make-variable-buffer-local 'jde-javadoc-checkdoc-excursion)
1631
1632 (defun jde-javadoc-checkdoc-clear-excursion ()
1633   "Clear saved window configuration and point.
1634 See also variable `jde-javadoc-checkdoc-excursion'."
1635   (setq jde-javadoc-checkdoc-excursion nil))
1636
1637 (defun jde-javadoc-checkdoc-save-excursion ()
1638   "Save window configuration and point.
1639 See also function `jde-javadoc-checkdoc-restore-excursion'."
1640   (setq jde-javadoc-checkdoc-excursion
1641         (vector (current-window-configuration)
1642                 (point))))
1643
1644 (defun jde-javadoc-checkdoc-restore-excursion ()
1645   "Restore window configuration and point.
1646 See also function `jde-javadoc-checkdoc-save-excursion'."
1647   (let ((ex jde-javadoc-checkdoc-excursion))
1648     (and (vectorp ex)
1649          (window-configuration-p (aref ex 0))
1650          (integer-or-marker-p    (aref ex 1))
1651          (condition-case nil
1652              (progn
1653                (set-window-configuration (aref ex 0))
1654                (goto-char                (aref ex 1)))
1655            (error nil)))
1656     (jde-javadoc-checkdoc-clear-excursion)))
1657
1658 ;;;; Commands
1659 ;;;; --------
1660
1661 ;;;###autoload
1662 (defun jde-javadoc-checker-previous ()
1663   "Go to the previous tag with doc errors."
1664   (interactive)
1665   (and (eq major-mode 'jde-javadoc-checker-report-mode)
1666        (jde-javadoc-checker-previous-tag
1667         jde-javadoc-checker-buffer jde-javadoc-checker-tag)))
1668
1669 ;;;###autoload
1670 (defun jde-javadoc-checker-next ()
1671   "Goto the next tag with doc errors."
1672   (interactive)
1673   (and (eq major-mode 'jde-javadoc-checker-report-mode)
1674        (jde-javadoc-checker-next-tag jde-javadoc-checker-buffer
1675                                        jde-javadoc-checker-tag)))
1676 ;;;###autoload
1677 (defun jde-javadoc-checker-fix ()
1678   "Fix documentation of checked tag.
1679 Used in `jde-javadoc-checker-report-mode'."
1680   (interactive)
1681   (and (eq major-mode 'jde-javadoc-checker-report-mode)
1682        (let ((tag  jde-javadoc-checker-tag)
1683              (buffer jde-javadoc-checker-buffer))
1684          (when (and tag buffer)
1685            (pop-to-buffer buffer)
1686            (goto-char (semantic-tag-start tag))
1687            ;; do the fix (THE POINT STAY AT TAG START POSITION)
1688            (jde-javadoc-generator tag t)
1689            ;; recheck the tag
1690            (jde-javadoc-checker tag)))))
1691
1692 ;;;###autoload
1693 (defun jde-javadoc-checker-quit ()
1694   "Quit the `jde-javadoc-checker' report buffer.
1695 Used in `jde-javadoc-checker-report-mode'."
1696   (interactive)
1697   (let ((buffer (get-buffer jde-javadoc-checker-report-buffer)))
1698     (if (bufferp buffer)
1699         (kill-buffer buffer))
1700     (jde-javadoc-checkdoc-restore-excursion)))
1701
1702 ;;;###autoload
1703 (defun jde-javadoc-customize ()
1704   "Show the jde-javadoc options panel."
1705   (interactive)
1706   (customize-group "jde-javadoc"))
1707
1708 ;;;###autoload
1709 (defun jde-javadoc-autodoc-at-line ()
1710   "Update javadoc comment block for declaration at current line.
1711
1712 Uses the semantic bovinator parser table to find declarations (see
1713 `jde-javadoc-nonterminal-at-line').
1714
1715 BEFORE EXECUTING THE COMMAND, THE POINT MUST BE LOCATED AT THE FIRST
1716 LINE OF THE CLASS OR METHOD DECLARATION.  IF NOT RESULT IS UNCERTAIN.
1717
1718 In the following examples, point is located at the beginning of the
1719 line, before the word 'public' (but it could be anywhere on this
1720 line):
1721
1722 1- Class example:
1723    -------------
1724
1725 -|-  public class MyClass
1726        extends MySuperClass implements Runnable, java.io.Serializable
1727      {
1728        ...
1729
1730 \\[jde-javadoc-autodoc-at-line] inserts:
1731
1732 +    /**
1733 +     * Describe class <code>MyClass</code> here.
1734 +     *
1735 +     * @author \"David Ponce\" <david.ponce@wanadoo.fr>
1736 +     * @version 1.0
1737 +     * @since 1.0
1738 +     * @see MySuperClass
1739 +     * @see Runnable
1740 +     * @see java.io.Serializable
1741 +     */
1742      public class MyClass
1743        extends MySuperClass implements Runnable, java.io.Serializable
1744      {
1745        ...
1746
1747 2- Method example:
1748    --------------
1749
1750 -|-  public
1751      void   myMethod( int  x,  int y )
1752        throws Exception
1753      {
1754        ...
1755
1756 \\[jde-javadoc-autodoc-at-line] inserts:
1757
1758 +    /**
1759 +     * Describe <code>myMethod</code> method here.
1760 +     *
1761 +     * @param x an <code>int</code> value
1762 +     * @param y a <code>long</code> value
1763 +     * @exception Exception if an error occurs
1764 +     */
1765      public
1766      void   myMethod( int  x,  long y )
1767        throws Exception
1768      {
1769        ...
1770
1771 3- Field example:
1772    --------------
1773
1774 -|-  private static final int SIZE = 10;
1775
1776 \\[jde-javadoc-autodoc-at-line] inserts:
1777
1778 +    /**
1779 +     * Describe constant <code>SIZE</code> here.
1780 +     */
1781      private static final int SIZE = 10;
1782
1783
1784 `tempo' templates are used for each category of javadoc line.  The
1785 following templates are currently defined and fully customizable (see
1786 `tempo-define-template' for the different items that can be used in a
1787 tempo template):
1788
1789 - - `jde-javadoc-author-tag-template'
1790 - - `jde-javadoc-describe-class-template'
1791 - - `jde-javadoc-describe-constructor-template'
1792 - - `jde-javadoc-describe-interface-template'
1793 - - `jde-javadoc-describe-method-template'
1794 - - `jde-javadoc-describe-field-template'
1795 - - `jde-javadoc-exception-tag-template'
1796 - - `jde-javadoc-param-tag-template'
1797 - - `jde-javadoc-return-tag-template'
1798 - - `jde-javadoc-version-tag-template'
1799
1800 For example if you customize `jde-javadoc-describe-class-template'
1801 with the following value:
1802
1803 '(\"* \" (P \"Class description: \"))
1804
1805 you will be asked to enter the class description in the minibuffer.
1806 See also the `jde-javadoc-field-type', `jde-javadoc-a' and
1807 `jde-javadoc-code' helper functions."
1808   (interactive)
1809   (or (eq major-mode 'jde-mode)
1810       (error "Major mode must be 'jde-mode'"))
1811   (let ((found (jde-javadoc-nonterminal-at-line)))
1812     (if found
1813         (jde-javadoc-generator found)
1814       (error "No tag found at point"))))
1815
1816 ;;;###autoload
1817 (defun jde-javadoc-remdoc-at-line (&optional noconfirm)
1818   "Remove javadoc comment block for declaration at current line.
1819 Require confirmation if optional NOCONFIRM is non-nil.
1820 Return non-nil if done.
1821 This uses `jde-javadoc-nonterminal-at-line' to find declarations."
1822   (interactive "P")
1823   (jde-assert-source-buffer)
1824   (let ((found (jde-javadoc-nonterminal-at-line)))
1825     (if (not found)
1826         (error "No tag found at point")
1827       (jde-javadoc-delete-documentation found current-prefix-arg))))
1828
1829 ;;;###autoload
1830 (defun jde-javadoc-checkdoc-at-line ()
1831   "Check javadoc comment block of declaration at current line.
1832
1833 Uses the semantic bovinator parser table to find declarations (see
1834 `jde-javadoc-nonterminal-at-line').
1835
1836 BEFORE EXECUTING THE COMMAND, THE POINT MUST BE LOCATED AT THE FIRST
1837 LINE OF THE CLASS OR METHOD DECLARATION.  IF NOT RESULT IS UNCERTAIN."
1838   (interactive)
1839   (jde-assert-source-buffer)
1840   (let ((found (jde-javadoc-nonterminal-at-line)))
1841     (if (not found)
1842         (error "No tag found at point")
1843       (jde-javadoc-checkdoc-save-excursion)
1844       (jde-javadoc-checker found))))
1845
1846 ;;;###autoload
1847 (defun jde-javadoc-checkdoc ()
1848   "Check doc comments of tags in the current buffer.
1849 Report the next tag with documentation errors."
1850   (interactive)
1851   (jde-assert-source-buffer)
1852   (semantic-fetch-tags)
1853   (jde-javadoc-checkdoc-save-excursion)
1854   (jde-javadoc-checker-next-tag (current-buffer)))
1855
1856 (defalias 'jde-javadoc-autodoc 'jde-javadoc-checkdoc)
1857
1858 ;;; Compatibility
1859 ;;
1860 (defalias 'jde-javadoc-generate-javadoc-template
1861   'jde-javadoc-autodoc-at-line)
1862
1863 ;; Load the javadoc builder
1864 (require 'jde-javadoc-gen)
1865
1866 ;;;###autoload
1867 (defun jde-javadoc-enable-menu-p ()
1868   "Return non-nil if corresponding doc menu item is enabled.
1869 That is point is on the first line of a class, method, or field
1870 definition."
1871   (let ((p (save-excursion (beginning-of-line) (point)))
1872         (tag-at-line (jde-javadoc-nonterminal-at-line))
1873         start end)
1874     (and tag-at-line
1875          (memq (semantic-tag-class tag-at-line)
1876                '(function type variable))
1877          (save-excursion
1878            (setq start
1879                  (progn
1880                    (goto-char (semantic-tag-start tag-at-line))
1881                    (beginning-of-line)
1882                    (point)))
1883            (setq end (or (re-search-forward "[;={]")
1884                          (progn
1885                            (goto-char p)
1886                            (end-of-line)
1887                            (point))))
1888            (and (>= p start) (<= p end))))))
1889
1890 ;; Register and initialize the customization variables defined
1891 ;; by this package.
1892 (jde-update-autoloaded-symbols)
1893
1894 (provide 'jde-javadoc)
1895
1896
1897 ;;
1898 ;; $Log: jde-javadoc.el,v $
1899 ;; Revision 1.31  2004/07/08 12:17:00  paulk
1900 ;; Update to reflect semantic 2.0 tag (previously token) nomenclature. This is necessary to eliminate byte-compilation warnings.
1901 ;;
1902 ;; Revision 1.30  2004/06/03 02:38:04  paulk
1903 ;; Add jde-javadoc-remdoc-at-line command. Thanks to David Ponce.
1904 ;;
1905 ;; Revision 1.29  2004/05/04 04:40:36  paulk
1906 ;; Force reparsing with semantic 1.4.
1907 ;;
1908 ;; Revision 1.28  2004/03/22 06:17:24  paulk
1909 ;; Committed for Martin Schwamberger. Make jde-javadoc-insert-end-block
1910 ;; ready for use in templates.
1911 ;;
1912 ;; Revision 1.27  2003/09/21 03:33:20  paulk
1913 ;; - (jde-javadoc-checker-show-report): Better interaction with
1914 ;;   libraries that use the header-line in GNU Emacs 21.
1915 ;;
1916 ;; - (jde-javadoc-nonterminal-at-line): Use `forward-comment' to skip
1917 ;;    comment at beginning of line.
1918 ;;
1919 ;; Submitted by David Ponce.
1920 ;;
1921 ;; Revision 1.26  2002/11/21 04:18:41  paulk
1922 ;; These packages, when autoloaded, now register and initialize the customization variables
1923 ;; that they define to the values specified in the current project file.
1924 ;;
1925 ;; Revision 1.25  2002/10/11 05:53:22  paulk
1926 ;; Added more packages to the list of packages that are demand loaded. This is intended to reduce the startup time for the JDEE.
1927 ;;
1928 ;; Revision 1.24  2002/09/30 04:54:09  paulk
1929 ;; Made all javadoc commands autoloadable.
1930 ;;
1931 ;; Revision 1.23  2002/09/16 04:42:52  paulk
1932 ;; XEmacs compatibility fix: added require statement for regexp-opt package.
1933 ;;
1934 ;; Revision 1.22  2002/06/23 17:37:36  jslopez
1935 ;; Removes carriage returns.
1936 ;;
1937 ;; Revision 1.21  2002/06/22 06:25:26  paulk
1938 ;; Adds jde-javadoc-check-undeclared-exception-flag option. Thanks to David Ponce.
1939 ;;
1940 ;; Revision 1.20  2001/12/14 03:17:50  paulk
1941 ;; jde-javadoc-nonterminal-at-line preserves current tokens when the
1942 ;; lexer fails (when there is an unclosed block or an unterminated
1943 ;; string for example). This enhancement works only with semantic 1.4
1944 ;; beta 13 (and above). With older versions
1945 ;; jde-javadoc-nonterminal-at-line continues to work as previously.
1946 ;; Thanks to David Ponce.
1947 ;;
1948 ;; Revision 1.19  2001/08/06 05:25:21  paulk
1949 ;; jde-javadoc-parse-tag-values now removes the brackets from
1950 ;; VALUE-STRING when VALUE-KEY is 'name.  This fixes checker error when
1951 ;; it tries to match an array name in javadoc comments and in argument
1952 ;; list. Thanks to David Ponce.
1953 ;;
1954 ;; Revision 1.18  2001/05/19 02:36:00  paulk
1955 ;; Updated to support semantic 1.4. Thanks to David Ponce.
1956 ;;
1957 ;; Revision 1.17  2001/01/27 05:42:07  paulk
1958 ;; Enhancements from David Ponce:
1959 ;;
1960 ;; - Improved `jde-javadoc-start-tag-regexp' and
1961 ;;   `jde-javadoc-end-tag-regexp' regular expressions which fix little
1962 ;;   problems when parsing javadoc tags.  These regexps enforce the
1963 ;;   following rule (from JDK 1.3 documentation "javadoc - The Java
1964 ;;   API Documentation Generator" - Chapter "DOCUMENTATION COMMENTS" -
1965 ;;   "Standard and in-line tags":
1966 ;;
1967 ;;
1968 ;;   "[...] a standard tag must appear at the beginning of a line,
1969 ;;   ignoring leading asterisks, white space and comment separator
1970 ;;   (/**). This means you can use the @ character elsewhere in the
1971 ;;   text and it will not be interpreted as the start of a tag. If you
1972 ;;   want to start a line with the @ character and not have it be
1973 ;;   interpreted, use the HTML entity @. [...]"
1974 ;;
1975 ;;
1976 ;; - `jde-javadoc-checker-report-mode' now turns on `font-lock-mode'.
1977 ;;   This is useful in XEmacs which don't have a
1978 ;;   `global-font-lock-mode'.
1979 ;;
1980 ;;
1981 ;; - Filling of messages in `jde-javadoc-checker-show-report' now
1982 ;;   works with XEmacs too.
1983 ;;
1984 ;; Revision 1.16  2000/12/18 05:22:45  paulk
1985 ;; *** empty log message ***
1986 ;;
1987 ;; Revision 1.15  2000/11/27 06:18:40  paulk
1988 ;; Miscellaneous bug fixes and minor enhancements.
1989 ;;
1990 ;; Revision 1.14  2000/10/25 03:11:57  paulk
1991 ;; Enhancements from David Ponce:
1992 ;;
1993 ;; * It is now possible to check javadoc comments only for tokens with
1994 ;;   a specified access level. The new `jde-javadoc-checker-level'
1995 ;;   option defines the accessibility level to check.
1996 ;;
1997 ;;   Only 'type, 'function or 'variable tokens with this level will be
1998 ;;   checked. The level is defined to be consistent with the javadoc
1999 ;;   show options. That is:
2000 ;;
2001 ;;   - - public    - check only public classes and members.
2002 ;;   - - protected - check only protected and public classes and
2003 ;;                   members. This is the default.
2004 ;;   - - package   - check only package, protected, and public classes
2005 ;;                   and members.
2006 ;;   - - private   - check all classes and members.
2007 ;;
2008 ;;   If a token is included in other ones its access level is the
2009 ;;   lowest one found in the hierarchy.
2010 ;;
2011 ;;   Using `jde-javadoc-checkdoc-at-line' it is always possible to
2012 ;;   check any token regardless of its access level.
2013 ;;
2014 ;; * Changed '[u]-update' action by more appropriate '[f]-try to fix'
2015 ;;   in the checker report dialog.
2016 ;;
2017 ;; * Changed message "Invalid tag order, must be ..." by
2018 ;;   "Recommended tag order is ...".
2019 ;;
2020 ;; Revision 1.13  2000/10/22 07:54:04  paulk
2021 ;; Add menu enabler for javadoc commands.
2022 ;;
2023 ;; Revision 1.12  2000/10/20 04:07:44  paulk
2024 ;; Enhancements from David Ponce.
2025 ;;
2026 ;; Revision 1.11  2000/10/08 12:55:39  paulk
2027 ;; *** empty log message ***
2028 ;;
2029 ;; Revision 1.10 2000/09/23 04:26:13 paulk Adds
2030 ;; jde-javadoc-command-path and jde-javadoc-display-doc
2031 ;; variables. Thanks to "Jason Stell" <Jason.Stell@globalone.net> for
2032 ;; providing the initial version of these changes.
2033 ;;
2034 ;; Revision 1.9  2000/08/19 06:44:02  paulk
2035 ;; Don't quote class names in javadoc command.
2036 ;;
2037 ;; Revision 1.8  2000/08/08 04:49:32  paulk
2038 ;; Fixed the doc for jde-javadoc-make.
2039 ;;
2040 ;; Revision 1.7 2000/08/07 06:09:57 paulk jde-javadoc-make now uses
2041 ;; jde-db-source-directories as the sourcepath for generating doc.
2042 ;;
2043 ;; Revision 1.6 2000/08/07 05:16:10 paulk Adds jde-javadoc-make
2044 ;; command. Thanks to Sergey A Klibanov <sakliban@cs.wustl.edu>.
2045 ;;
2046 ;; Revision 1.5  2000/07/13 05:22:48  paulk
2047 ;; *** empty log message ***
2048 ;;
2049 ;; Revision 1.4  2000/07/08 07:15:41  paulk
2050 ;; Latest updates from David.
2051 ;;
2052 ;; Revision 1.2  2000/06/22 03:36:40  paulk
2053 ;; Fix submitted by David Ponce.
2054 ;;
2055 ;; Revision 1.1  2000/06/12 08:19:03  paulk
2056 ;; Initial revision.
2057 ;;
2058 ;;
2059
2060 ;;; jde-javadoc.el ends here