1 ;;; semantic-java.el --- Semantic functions for Java
3 ;;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
6 ;; Author: David Ponce <david@dponce.com>
7 ;; X-RCS: $Id: semantic-java.el,v 1.1 2007-11-26 15:11:56 michaels Exp $
9 ;; This file is not part of GNU Emacs.
11 ;; semantic-java is free software; you can redistribute it and/or
12 ;; modify it under the terms of the GNU General Public License as
13 ;; published by the Free Software Foundation; either version 2, or (at
14 ;; your option) any later version.
16 ;; This software is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
28 ;; Common function for Java parsers.
35 (require 'semantic-ctxt)
36 (require 'semantic-doc)
40 (defconst semantic-java-number-regexp
43 "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
45 "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>"
47 "\\<[0-9]+[.][fFdD]\\>"
51 "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>"
53 "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>"
55 "\\<0[xX][0-9a-fA-F]+[lL]?\\>"
57 "\\<[0-9]+[lLfFdD]?\\>"
60 "Lexer regexp to match Java number terminals.
61 Following is the specification of Java number literals.
73 <DECIMAL_LITERAL>[lL]?
75 | <OCTAL_LITERAL>[lL]?
80 FLOATING_POINT_LITERAL:
81 [0-9]+[.][0-9]*<EXPONENT>?[fFdD]?
82 | [.][0-9]+<EXPONENT>?[fFdD]?
83 | [0-9]+<EXPONENT>[fFdD]?
84 | [0-9]+<EXPONENT>?[fFdD]
89 (defsubst semantic-java-dim (id)
90 "Split ID string into a pair (NAME . DIM).
91 NAME is ID without trailing brackets: \"[]\".
92 DIM is the dimension of NAME deduced from the number of trailing
93 brackets, or 0 if there is no trailing brackets."
94 (let ((dim (string-match "\\(\\[]\\)+\\'" id)))
96 (cons (substring id 0 dim)
97 (/ (length (match-string 0 id)) 2))
100 (defsubst semantic-java-type (tag)
101 "Return the type of TAG, taking care of array notation."
102 (let ((type (semantic-tag-type tag))
103 (dim (semantic-tag-get-attribute tag :dereference)))
106 (setq type (concat type "[]")
110 (defun semantic-java-expand-tag (tag)
111 "Expand compound declarations found in TAG into separate tags.
112 TAG contains compound declarations when its class is `variable', and
113 its name is a list of elements (NAME START . END), where NAME is a
114 compound variable name, and START/END are the bounds of the
115 corresponding compound declaration."
116 (let* ((class (semantic-tag-class tag))
117 (elts (semantic-tag-name tag))
118 dim type dim0 elt clone start end xpand)
120 ((and (eq class 'function)
121 (> (cdr (setq dim (semantic-java-dim elts))) 0))
122 (setq clone (semantic-tag-clone tag (car dim))
123 xpand (cons clone xpand))
124 (semantic-tag-put-attribute clone :dereference (cdr dim)))
125 ((eq class 'variable)
126 (or (consp elts) (setq elts (list (list elts))))
127 (setq dim (semantic-java-dim (semantic-tag-get-attribute tag :type))
131 ;; For each compound element, clone the initial tag with the
132 ;; name and bounds of the compound variable declaration.
135 start (if elts (cadr elt) (semantic-tag-start tag))
136 end (if xpand (cddr elt) (semantic-tag-end tag))
137 dim (semantic-java-dim (car elt))
138 clone (semantic-tag-clone tag (car dim))
139 xpand (cons clone xpand))
140 (semantic-tag-put-attribute clone :type type)
141 (semantic-tag-put-attribute clone :dereference (+ dim0 (cdr dim)))
142 (semantic-tag-set-bounds clone start end)))
151 (define-mode-local-override semantic-ctxt-scoped-types
152 java-mode (&optional point)
153 "Return a list of type names currently in scope at POINT."
154 (mapcar 'semantic-tag-name
155 (semantic-find-tags-by-class
156 'type (semantic-find-tag-by-overlay point))))
160 (defun semantic-java-prototype-function (tag &optional parent color)
161 "Return a function (method) prototype for TAG.
162 Optional argument PARENT is a parent (containing) item.
163 Optional argument COLOR indicates that color should be mixed in.
164 See also `semantic-format-prototype-tag'."
165 (let ((name (semantic-tag-name tag))
166 (type (semantic-java-type tag))
167 (tmpl (semantic-tag-get-attribute tag :template-specifier))
168 (args (semantic-tag-function-arguments tag))
174 (if (semantic-tag-p arg)
176 (semantic--format-colorize-text
177 (semantic-java-type arg) 'type)
178 (semantic-java-type arg))
179 argp (concat argp argt (if args "," "")))))
182 (setq type (semantic--format-colorize-text type 'type)))
183 (setq name (semantic--format-colorize-text name 'function)))
184 (concat (or tmpl "") (if tmpl " " "")
185 (or type "") (if type " " "")
188 (defun semantic-java-prototype-variable (tag &optional parent color)
189 "Return a variable (field) prototype for TAG.
190 Optional argument PARENT is a parent (containing) item.
191 Optional argument COLOR indicates that color should be mixed in.
192 See also `semantic-format-prototype-tag'."
193 (let ((name (semantic-tag-name tag))
194 (type (semantic-java-type tag)))
196 (semantic--format-colorize-text type 'type)
200 (semantic--format-colorize-text name 'variable)
203 (defun semantic-java-prototype-type (tag &optional parent color)
204 "Return a type (class/interface) prototype for TAG.
205 Optional argument PARENT is a parent (containing) item.
206 Optional argument COLOR indicates that color should be mixed in.
207 See also `semantic-format-prototype-tag'."
208 (let ((name (semantic-tag-name tag))
209 (type (semantic-tag-type tag))
210 (tmpl (semantic-tag-get-attribute tag :template-specifier)))
213 (semantic--format-colorize-text name 'type)
217 (define-mode-local-override semantic-format-prototype-tag
218 java-mode (tag &optional parent color)
219 "Return a prototype for TOKEN.
220 Optional argument PARENT is a parent (containing) item.
221 Optional argument COLOR indicates that color should be mixed in."
222 (let ((f (intern-soft (format "semantic-java-prototype-%s"
223 (semantic-tag-class tag)))))
224 (funcall (if (fboundp f)
226 'semantic-format-tag-prototype-default)
229 (semantic-alias-obsolete 'semantic-java-prototype-nonterminal
230 'semantic-format-prototype-tag-java-mode)
232 ;; Documentation handler
234 (defsubst semantic-java-skip-spaces-backward ()
235 "Move point backward, skipping Java whitespaces."
236 (skip-chars-backward " \n\r\t"))
238 (defsubst semantic-java-skip-spaces-forward ()
239 "Move point forward, skipping Java whitespaces."
240 (skip-chars-forward " \n\r\t"))
242 (define-mode-local-override semantic-documentation-for-tag
243 java-mode (&optional tag nosnarf)
244 "Find documentation from TAG and return it as a clean string.
245 Java have documentation set in a comment preceeding TAG's definition.
246 Attempt to strip out comment syntactic sugar, unless optional argument
248 If NOSNARF is 'lex, then return the semantic lex token."
249 (when (or tag (setq tag (semantic-current-tag)))
250 (with-current-buffer (semantic-tag-buffer tag)
252 ;; Move the point at token start
253 (goto-char (semantic-tag-start tag))
254 (semantic-java-skip-spaces-forward)
255 ;; If the point already at "/**" (this occurs after a doc fix)
256 (if (looking-at "/\\*\\*")
258 ;; Skip previous spaces
259 (semantic-java-skip-spaces-backward)
260 ;; Ensure point is after "*/" (javadoc block comment end)
264 (when (looking-at "\\*/")
265 ;; Move the point backward across the comment
266 (forward-char 2) ; return just after "*/"
267 (forward-comment -1) ; to skip the entire block
269 ;; Verify the point is at "/**" (javadoc block comment start)
270 (if (looking-at "/\\*\\*")
272 (c (semantic-doc-snarf-comment-for-tag 'lex)))
274 ;; Verify that the token just following the doc
275 ;; comment is the current one!
276 (goto-char (semantic-lex-token-end c))
277 (semantic-java-skip-spaces-forward)
278 (when (eq tag (semantic-current-tag))
280 (semantic-doc-snarf-comment-for-tag nosnarf)))))
283 ;;; Javadoc facilities
288 (defvar semantic-java-doc-line-tags nil
289 "Valid javadoc line tags.
290 Ordered following Sun's Tag Convention at
291 <http://java.sun.com/products/jdk/javadoc/writingdoccomments/index.html>")
293 (defvar semantic-java-doc-with-name-tags nil
294 "Javadoc tags which have a name.")
296 (defvar semantic-java-doc-with-ref-tags nil
297 "Javadoc tags which have a reference.")
299 ;; Optional javadoc tags by classes of semantic tag
301 (defvar semantic-java-doc-extra-type-tags nil
302 "Optional tags used in class/interface documentation.
303 Ordered following Sun's Tag Convention.")
305 (defvar semantic-java-doc-extra-function-tags nil
306 "Optional tags used in method/constructor documentation.
307 Ordered following Sun's Tag Convention.")
309 (defvar semantic-java-doc-extra-variable-tags nil
310 "Optional tags used in field documentation.
311 Ordered following Sun's Tag Convention.")
313 ;; All javadoc tags by classes of semantic tag
315 (defvar semantic-java-doc-type-tags nil
316 "Tags allowed in class/interface documentation.
317 Ordered following Sun's Tag Convention.")
319 (defvar semantic-java-doc-function-tags nil
320 "Tags allowed in method/constructor documentation.
321 Ordered following Sun's Tag Convention.")
323 (defvar semantic-java-doc-variable-tags nil
324 "Tags allowed in field documentation.
325 Ordered following Sun's Tag Convention.")
327 ;; Access to Javadoc elements
329 (defmacro semantic-java-doc-tag (name)
330 "Return doc tag from NAME.
334 (defsubst semantic-java-doc-tag-name (tag)
335 "Return name of the doc TAG symbol.
336 That is TAG `symbol-name' without the leading '@'."
337 (substring (symbol-name tag) 1))
339 (defun semantic-java-doc-keyword-before-p (k1 k2)
340 "Return non-nil if javadoc keyword K1 is before K2."
341 (let* ((t1 (semantic-java-doc-tag k1))
342 (t2 (semantic-java-doc-tag k2))
343 (seq1 (and (semantic-lex-keyword-p t1)
344 (plist-get (semantic-lex-keyword-get t1 'javadoc)
346 (seq2 (and (semantic-lex-keyword-p t2)
347 (plist-get (semantic-lex-keyword-get t2 'javadoc)
349 (if (and (numberp seq1) (numberp seq2))
351 ;; Unknown tags (probably custom ones) are always after official
352 ;; ones and are not themselves ordered.
354 (and (not seq1) (not seq2))))))
356 (defun semantic-java-doc-keywords-map (fun &optional property)
357 "Run function FUN for each javadoc keyword.
358 Return the list of FUN results. If optional PROPERTY is non nil only
359 call FUN for javadoc keyword which have a value for PROPERTY. FUN
360 receives two arguments: the javadoc keyword and its associated
361 'javadoc property list. It can return any value. Nil values are
362 removed from the result list."
366 (let* ((tag (semantic-java-doc-tag k))
367 (plist (semantic-lex-keyword-get tag 'javadoc)))
368 (if (or (not property) (plist-get plist property))
369 (funcall fun k plist))))
370 semantic-java-doc-line-tags)))
376 (defun semantic-java-doc-setup ()
377 "Lazy initialization of javadoc elements."
378 (or semantic-java-doc-line-tags
379 (setq semantic-java-doc-line-tags
380 (sort (mapcar #'semantic-java-doc-tag-name
381 (semantic-lex-keywords 'javadoc))
382 #'semantic-java-doc-keyword-before-p)))
384 (or semantic-java-doc-with-name-tags
385 (setq semantic-java-doc-with-name-tags
386 (semantic-java-doc-keywords-map
391 (or semantic-java-doc-with-ref-tags
392 (setq semantic-java-doc-with-ref-tags
393 (semantic-java-doc-keywords-map
398 (or semantic-java-doc-extra-type-tags
399 (setq semantic-java-doc-extra-type-tags
400 (semantic-java-doc-keywords-map
402 (if (memq 'type (plist-get p 'usage))
406 (or semantic-java-doc-extra-function-tags
407 (setq semantic-java-doc-extra-function-tags
408 (semantic-java-doc-keywords-map
410 (if (memq 'function (plist-get p 'usage))
414 (or semantic-java-doc-extra-variable-tags
415 (setq semantic-java-doc-extra-variable-tags
416 (semantic-java-doc-keywords-map
418 (if (memq 'variable (plist-get p 'usage))
422 (or semantic-java-doc-type-tags
423 (setq semantic-java-doc-type-tags
424 (semantic-java-doc-keywords-map
426 (if (memq 'type (plist-get p 'usage))
429 (or semantic-java-doc-function-tags
430 (setq semantic-java-doc-function-tags
431 (semantic-java-doc-keywords-map
433 (if (memq 'function (plist-get p 'usage))
436 (or semantic-java-doc-variable-tags
437 (setq semantic-java-doc-variable-tags
438 (semantic-java-doc-keywords-map
440 (if (memq 'variable (plist-get p 'usage))
445 (provide 'semantic-java)
447 ;;; semantic-java.el ends here