Mike Bowler wrote:
>
> JDE 2.1.6 final / NT Emacs 20.6 / Windows NT 4.0
>
> Some methods are still not showing up in the classes menu. The code
> below shows which combinations of modifiers are being parsed correctly
> and which ones aren't.
>
> Mike
> [EMAIL PROTECTED]
> ==================
>
> public class foo {
> // All of these are ok
> private int a;
> private final int b = 0;
> private transient int c;
> private transient final int d = 0;
> private static int e;
> static int f;
> private static transient int g;
> static int h;
>
> // All of these fail to show up in the menu
> private volatile int j;
> private static volatile int k;
> private static transient volatile int m;
>
> // ok
> public foo() {
> }
>
> // fail
> public foo( int someInts[] ) {
> }
>
> // ok
> public void one() {
> }
>
> // fail
> public void two( int anInt[] ) {
> }
>
> //fail
> public void three( final int anInt ) {
> }
>
> //fail
> public final void four( int anInt ) {
> }
>
> // ok
> public synchronized void five() {
> }
> }
Hello,
Attached is a patch to java.bnf to add the missing "volatile" keyword to
variable modifiers. I have attached too the jde-parse.el file modified
with the new grammar. It seems to work well now :-)
Hope this will help.
Sincerely,
David
;;; jde-parse.el
;; $Revision: 1.12 $
;; Author: Paul Kinnucan <[EMAIL PROTECTED]>
;; Maintainer: Paul Kinnucan
;; Keywords: java, tools
;; Copyright (C) 1997, 1998 Paul Kinnucan.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
(require 'semantic)
(require 'semantic-sb)
(require 'semantic-bnf)
(defcustom jde-enable-classes-index-menu t
"Enables creation of a classes index menu in the Emacs menubar."
:group 'jde-project
:type 'boolean)
(defvar jde-parse-bovine-java-grammar
`((bovine-toplevel
( package)
( import)
( class)
( interface)
) ; end bovine-toplevel
(qualified-name
( symbol punctuation "\\." qualified-name
,(lambda (vals start end)
(append (list ( concat (nth 0 vals) (nth 1 vals) ( car (nth 2
vals))))
(list start end))))
( symbol
,(lambda (vals start end)
(append (list (nth 0 vals))
(list start end))))
) ; end qualified-name
(package
( symbol "package" qualified-name punctuation ";"
,(lambda (vals start end)
(append (nth 1 vals) (list 'package nil)
(list start end))))
) ; end package
(import
( symbol "import" qualified-name punctuation ";"
,(lambda (vals start end)
(append (nth 1 vals) (list 'include nil)
(list start end))))
( symbol "import" qualified-name punctuation "\\." punctuation "\\*" punctuation
";"
,(lambda (vals start end)
(append (list ( concat ( car (nth 1 vals)) (nth 2 vals) (nth 3
vals)) 'include nil)
(list start end))))
) ; end import
(qualified-name-list
( qualified-name punctuation "," qualified-name-list)
( qualified-name)
) ; end qualified-name-list
(method-modifier
( symbol
"\\(public\\|protected\\|private\\|static\\|synchronized\\|native\\|abstract\\|final\\)")
) ; end method-modifier
(method-modifiers
( method-modifier method-modifiers)
( method-modifier)
()
) ; end method-modifiers
(scalar-type
( symbol "\\(void\\|int\\|long\\|char\\|float\\|double\\|byte\\|boolean\\)"
,(lambda (vals start end)
(append (list (nth 0 vals))
(list start end))))
( qualified-name
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
) ; end scalar-type
(object-type
( scalar-type opt-array
,(lambda (vals start end)
(append (list ( concat ( car (nth 0 vals)) ( car (nth 1 vals))))
(list start end))))
) ; end object-type
(variable-modifier
( symbol
"\\(public\\|protected\\|private\\|static\\|final\\|transient\\|volatile\\)")
) ; end variable-modifier
(variable-modifier-list
( variable-modifier variable-modifier-list)
( variable-modifier)
()
) ; end variable-modifier-list
(opt-array
( semantic-list "\\[.*]" opt-array
,(lambda (vals start end)
(append (list ( concat (nth 0 vals) ( car (nth 1 vals))))
(list start end))))
(
,(lambda (vals start end)
(append (list nil)
(list start end))))
) ; end opt-array
(parameter
( variable-modifier-list object-type symbol opt-array
,(lambda (vals start end)
(append (list (nth 2 vals) 'variable ( car (nth 1
vals)))
(list start end))))
) ; end parameter
(argument-list
( open-paren "(" close-paren ")"
,(lambda (vals start end)
(append (list nil)
(list start end))))
( open-paren "(" argument-list
,(lambda (vals start end)
(append (nth 1 vals)
(list start end))))
( parameter punctuation "," argument-list
,(lambda (vals start end)
(append ( cons (nth 0 vals) (nth 2 vals))
(list start end))))
( parameter close-paren ")"
,(lambda (vals start end)
(append (list (nth 0 vals))
(list start end))))
) ; end argument-list
(method-arguments
( semantic-list
,(lambda (vals start end)
(semantic-bovinate-from-nonterminal (car (nth 0 vals)) (cdr (nth 0 vals))
'argument-list)
))
) ; end method-arguments
(method-body
( semantic-list
,(lambda (vals start end)
(append (list nil)
(list start end))))
) ; end method-body
(throws
( symbol "throws" qualified-name-list
,(lambda (vals start end)
(append (nth 1 vals)
(list start end))))
()
) ; end throws
(method
( method-modifiers object-type symbol method-arguments throws method-body
,(lambda (vals start end)
(append (list (nth 2 vals) 'function) (nth 1 vals) (list
(nth 3 vals) nil)
(list start end))))
( method-modifiers object-type symbol method-arguments throws punctuation ";"
,(lambda (vals start end)
(append (list (nth 2 vals) 'function) (nth 1 vals) (list
(nth 3 vals) nil)
(list start end))))
) ; end method
(constructor-modifier
( symbol "\\(public\\|protected\\|private\\)")
) ; end constructor-modifier
(constructor
( constructor-modifier symbol method-arguments throws method-body
,(lambda (vals start end)
(append (list (nth 1 vals) 'function nil (nth 2 vals)
nil)
(list start end))))
) ; end constructor
(class-modifier
( symbol "<\\(public\\|abstract\\)>")
) ; end class-modifier
(class-modifier-list
( class-modifier class-modifier-list)
( class-modifier)
) ; end class-modifier-list
(expression
( symbol "new" qualified-name semantic-list "\\(.*\\)"
,(lambda (vals start end)
(append (list nil)
(list start end))))
( symbol semantic-list
,(lambda (vals start end)
(append (list nil)
(list start end))))
( symbol
,(lambda (vals start end)
(append (list nil)
(list start end))))
) ; end expression
(opt-expression
( expression)
(
,(lambda (vals start end)
(append (list nil)
(list start end))))
) ; end opt-expression
(opt-assign
( punctuation "=" expression
,(lambda (vals start end)
(append (list (nth 1 vals))
(list start end))))
(
,(lambda (vals start end)
(append (list nil)
(list start end))))
) ; end opt-assign
(field
( variable-modifier-list object-type symbol opt-assign punctuation ";"
,(lambda (vals start end)
(append (list (nth 2 vals) 'variable) (nth 1 vals)
(list nil)
(list start end))))
) ; end field
(class-members
( class
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
( constructor
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
( method
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
( field
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
) ; end class-members
(class-body
( semantic-list
,(lambda (vals start end)
(append
(semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0
vals)) 'class-members)
(list start end))))
) ; end class-body
(extends
( symbol "extends" qualified-name
,(lambda (vals start end)
(append (nth 1 vals)
(list start end))))
()
) ; end extends
(implements
( symbol "implements" qualified-name-list
,(lambda (vals start end)
(append (nth 1 vals)
(list start end))))
()
) ; end implements
(class
( symbol "class" qualified-name extends implements class-body
,(lambda (vals start end)
(append (nth 1 vals) (list 'type "class" (nth 4 vals) (nth 2 vals)
nil)
(list start end))))
( symbol "class" qualified-name implements extends class-body
,(lambda (vals start end)
(append (nth 1 vals) (list 'type "class" (nth 4 vals) (nth 3 vals)
nil)
(list start end))))
) ; end class
(method-prototype
( method-modifiers object-type symbol method-arguments throws method-body
,(lambda (vals start end)
(append (list (nth 2 vals) 'function) (nth 1 vals) (list
(nth 3 vals) nil)
(list start end))))
( method-modifiers object-type symbol method-arguments throws punctuation ";"
,(lambda (vals start end)
(append (list (nth 2 vals) 'function) (nth 1 vals) (list
(nth 3 vals) nil)
(list start end))))
) ; end method-prototype
(interface-members
( method-prototype
,(lambda (vals start end)
(append (nth 0 vals)
(list start end))))
) ; end interface-members
(interface-body
( semantic-list
,(lambda (vals start end)
(append
(semantic-bovinate-from-nonterminal-full (car (nth 0 vals)) (cdr (nth 0
vals)) 'interface-members)
(list start end))))
) ; end interface-body
(interface
( symbol "interface" qualified-name extends interface-body
,(lambda (vals start end)
(append (nth 1 vals) (list 'type (nth 0 vals) (nth 3 vals) (nth 2
vals) nil)
(list start end))))
) ; end interface
)
"Grammar used by the semantic library to parse Java source
buffers. This grammar is a Lisp version of the BNF grammar stored in
java.bnf. The Lisp grammar is generated automatically from the BNF
source. For this reason, you should never modify this variable
directly. See `bovinate' for more information.")
(defun jde-imenu-index-class (tokens)
"Creates an imenu index for a class."
(let ((methods (semantic-find-nonterminal-by-token 'function tokens))
(fields (semantic-find-nonterminal-by-token 'variable tokens))
(classes (semantic-find-nonterminal-by-token 'type tokens))
index)
(while methods
(let* ((method-token (car methods))
(method-name (car method-token))
(method-pos (nth (- (length method-token) 2) method-token)))
(setq index
(append
index (list (cons (concat method-name "()") method-pos)))))
(setq methods (cdr methods)))
(while fields
(let* ((field-token (car fields))
(field-name (car field-token))
(field-pos (nth (- (length field-token) 2) field-token)))
(setq index
(append
index (list (cons field-name field-pos)))))
(setq fields (cdr fields)))
(while classes
(let* ((class-token (car classes))
(class-name (car class-token))
(parts (semantic-token-type-parts class-token))
(class-index (jde-imenu-index-class parts)))
(setq index
(append
index
(list (cons (concat "class " class-name) class-index)))))
(setq classes (cdr classes)))
index))
(defun jde-create-imenu-index ()
"Creates an imenu index for a Java source buffer.
This function uses the semantic bovinator to index the buffer."
(let* ((tokens (semantic-bovinate-toplevel nil nil t))
(packages (semantic-find-nonterminal-by-token 'package tokens))
(depends (semantic-find-nonterminal-by-token 'include tokens))
(classes (semantic-find-nonterminal-by-token 'type tokens))
depend-index
index)
(while classes
(let* ((class-token (car classes))
(class-name (car class-token))
(parts (semantic-token-type-parts class-token))
(class-index (jde-imenu-index-class parts)))
(setq index
(append
index
(list (cons (concat "class " class-name) class-index)))))
(setq classes (cdr classes)))
(while depends
(let* ((depend-token (car depends))
(depend-name (car depend-token))
(depend-pos (nth (- (length depend-token) 2) depend-token)))
(setq depend-index (append depend-index (list (cons depend-name
depend-pos)))))
(setq depends (cdr depends)))
(if depend-index
(setq index (append index (list (cons "Imports" depend-index)))))
(while packages
(let* ((package-token (car packages))
(package-name (car package-token))
(package-pos (nth (- (length package-token) 2) package-token)))
(setq index
(append
index
(list (cons (concat "package " package-name) package-pos)))))
(setq packages (cdr packages)))
index))
(add-hook
'jde-mode-hook
(lambda ()
(make-local-variable 'semantic-toplevel-bovine-table)
(setq semantic-toplevel-bovine-table jde-parse-bovine-java-grammar)
(when jde-enable-classes-index-menu
(setq imenu-create-index-function 'jde-create-imenu-index)
(imenu-add-to-menubar "Classes"))))
(defun jde-get-java-source-buffers ()
"Get a list of the Java source buffers open in the
current session."
(mapcan (lambda (buffer)
(save-excursion
(set-buffer buffer)
(if (string= mode-name "JDE")
(list buffer))))
(buffer-list)))
(defun jde-parse-get-package-name ()
"Gets the name of the package in which the Java source file in the
current buffer resides."
(let ((package-re "package[ \t]+\\(.*\\)[ \t]*;"))
(save-excursion
(goto-char (point-max))
(when (re-search-backward package-re (point-min) t)
(looking-at package-re)
(buffer-substring-no-properties
(match-beginning 1)
(match-end 1))))))
(defun jde-parse-get-package-from-name (class-name)
"Gets the package portion of a qualified class name."
(substring
class-name 0
(let ((pos (position ?. class-name :from-end t)))
(if pos
pos
0))))
(defun jde-parse-get-unqualified-name (name)
"Gets the last name in a qualified name."
(string-match "[^.]+$" name)
(substring name (match-beginning 0) (match-end 0)))
(defun jde-parse-get-class-at-point ()
(let ((class-re "class[ \t]+\\([a-zA-z]+[a-zA-Z0-9._]*\\).*[ \n]*"))
(save-excursion
(let ((open-brace-pos
(scan-lists (point) -1 1)))
(when open-brace-pos
(goto-char open-brace-pos)
(when (re-search-backward class-re (point-min) t)
(looking-at class-re)
(buffer-substring-no-properties
(match-beginning 1)
(match-end 1))))))))
(defun jde-parse-in-comment-p ()
)
(defun jde-parse-get-innermost-class-at-point ()
"Get the innermost class containing point.
If point is in a class, this function returns
(CLASS_NAME . CLASS_POSITION), where CLASS_NAME is the
name of the class and CLASS_POSITION is the position
of the first character of the class keyword. Otherwise,
this function returns nil."
;; (interactive)
(let ((left-paren-pos (c-parse-state)))
(if left-paren-pos
(save-excursion
(catch 'class-found
(let ((left-paren-index 0)
(left-paren-count (length left-paren-pos)))
(while (< left-paren-index left-paren-count)
(let ((paren-pos (nth left-paren-index left-paren-pos)))
(unless (consp paren-pos)
(goto-char paren-pos)
(if (looking-at "{")
(let* ((search-end-pos
(if (< left-paren-index (1- left-paren-count))
(let ((pos (nth (1+ left-paren-index)
left-paren-pos)))
(if (consp pos)
(cdr pos)
pos))
(point-min)))
(case-fold-search nil)
(class-re "^[
\t]*\\(\\(public\\|abstract\\|final\\|static\\|strictfp\\|protected\\)[ \t]+\\)*[
\t]*class[ \t]+\\([^ \t\n{]*\\).*")
(class-pos (re-search-backward class-re search-end-pos
t)))
(if class-pos
(progn
(looking-at class-re)
(throw
'class-found
(cons
(buffer-substring-no-properties
(match-beginning 3)
(match-end 3))
class-pos))))))))
(setq left-paren-index (1+ left-paren-index)))))))))
(defun jde-parse-test ()
(interactive)
(message (car (jde-parse-get-innermost-class-at-point))))
(defun jde-parse-get-class-at-point ()
(let ((class-info (jde-parse-get-innermost-class-at-point))
class-name)
(while class-info
(let ((name (car class-info))
(pos (cdr class-info)))
(if (not class-name)
(setq class-name name)
(setq class-name (concat name "." class-name)))
(save-excursion
(goto-char pos)
(setq class-info (jde-parse-get-innermost-class-at-point)))))
class-name))
(defun jde-parse-get-classes-at-point ()
(interactive)
(let ((class (jde-parse-get-innermost-class-at-point)))
(if class (message "%s %s" (car class) (cdr class) ) (message "no class")))
;; (goto-char (aref (c-search-uplist-for-classkey (c-parse-state)) 0))
)
(defun jde-parse-qualified-name-at-point ()
"Returns (cons QUALIFIER NAME) where NAME is the symbol at point and
QUALIFIER is the symbol's qualifier. For example, suppose the name at
point is
int i = error.msg.length()
^
In this case, this function returns (cons \"error.msg\" \"length\").
This function works only for qualified names that do not contain
white space. It returns null if there is no qualified name at point."
(let ((symbol-at-point (thing-at-point 'symbol)))
(when symbol-at-point
(thing-at-point-looking-at "[^ \n\t();,:+]+")
(let ((qualified-name
(buffer-substring-no-properties
(match-beginning 0)
(match-end 0))))
(string-match "\\(.+[.]\\)*\\([^.]+\\)" qualified-name)
(let ((qualifier (if (match-beginning 1)
(substring qualified-name
(match-beginning 1) (match-end 1))))
(name (substring qualified-name
(match-beginning 2) (match-end 2))))
(if qualifier
(setq qualifier (substring qualifier 0 (1- (length qualifier)))))
(cons qualifier name))))))
(defun jde-parse-double-backslashes (name)
(mapconcat (lambda (x) (if (eq x ?\\)
"\\\\"
(string x)))
name ""))
(defun jde-parse-valid-declaration-at (point varname)
"Verify that a POINT starts a valid java declaration
for the VARNAME variable."
(save-excursion
(goto-char point)
(if (looking-at (concat "\\([A-Za-z0-9_.\177-\377]+\\)[ \t\n\r]+"
(jde-parse-double-backslashes varname)
"[ \t\n\r]*[;=]"))
(match-string 1)
nil)))
(defun jde-parse-declared-type-of (name)
"Find in the current buffer the java type of the variable NAME. The
function returns a string containing the name of the class, or nil
otherwise. This function does not give the fully-qualified java class
name, it just returns the type as it is declared."
(save-excursion
(let (found res pos orgpt resname)
(setq orgpt (point))
(while (and (not found)
(search-backward name nil t))
(setq pos (point))
(backward-word 1)
(setq resname (jde-parse-valid-declaration-at (point) name))
(goto-char pos)
(forward-char -1)
(if (not (null resname))
(progn (setq res resname)
(setq found t))))
(goto-char orgpt)
(while (and (not found)
(search-forward name nil t))
(setq pos (point))
(backward-word 2)
(setq resname (jde-parse-valid-declaration-at (point) name))
(goto-char pos)
(forward-char 1)
(if (not (null resname))
(progn (setq res resname)
(setq found t))))
res)))
(defun jde-display-parse-error (error)
(let* ((parser-buffer-name "*Java Parser*")
(buf (get-buffer parser-buffer-name)))
(if (not buf)
(setq buf (get-buffer-create parser-buffer-name)))
(set-buffer buf)
(erase-buffer)
(insert error)
(pop-to-buffer buf)))
(defun jde-parse ()
"*Parses the Java source file displayed in the current buffer.
If the source file parses successfully, this command displays
a success message in the minibuffer. Otherwise, it displays an error
message in the Java Parser buffer. If the Java Parser buffer does
not exist, this command creates it.
Note. This command uses an external Java parser implemented in
Java to parse Java source files. This command uses the JDE's integrated
Java source interpreter, the BeanShell, to invoke the parser. If the
BeanShell is not running, this command starts the BeanShell. Thus,
the first time you invoke the parser you may notice a slight delay
before getting a response. Thereafter, the response should be very
fast."
(interactive)
(save-some-buffers (not compilation-ask-about-save) nil)
(let ((parse-error
(bsh-eval-r (concat "jde.parser.ParserMain.parseFile(\"" (buffer-file-name)
"\");"))))
(if parse-error
(jde-display-parse-error parse-error)
(message "Parsed %s successfully" (buffer-name)))))
;; Thanks to Eric D. Friedman <[EMAIL PROTECTED]> for this function.
(defun jde-parse-comment-or-quoted-p ()
"Returns t if point is in a comment or a quoted string. nil otherwise"
(interactive "p")
;; limit our analysis to the current line.
(let ((beg (save-excursion (beginning-of-line) (point))))
(if
(or
;; are we in a javadoc comment?
(save-excursion
(re-search-backward
"^[ \t]*/?\\*"
beg t))
;; are we in a '//' or a '/*' style comment?
;; note that /* or /** on a line with only leading whitespace
;; will have matched in the previous regex. We check again here
;; because the above case needs to allow for a line with
;; the continuation of a comment (using only a '*') whereas this
;; requires the presence of a '/' in front of the '*' so as to
;; distinguish a comment from a '*' operator.
;; To make a long story short,
;; the first regex matches
;; /* a comment */
;; and
;; /**
;; * a comment
;; */
;; while the second one matches
;; System.out.println(foo); /* a comment */
;; but not
;; i = 3 * 5;
;; if you do something like following, you're on your own:
;; i = 3
;; * 5;
;; Suggestions for improving the robustness of this algorithm
;; gratefully accepted.
(save-excursion
(re-search-backward
"\\(//\\|/\\*\\)"
beg t))
;; are we in a quoted string?
(save-excursion
(re-search-backward
"\"" ;;
beg t)))
t ;; return true if we had any matches; nil otherwise
nil)))
(provide 'jde-parse)
;; $Log: jde-parse.el,v $
;; Revision 1.12 2000/05/26 09:14:10 paulk
;; Updated grammar to handle argument variables with modifiers and array arguments.
;;
;; Revision 1.11 2000/05/16 04:08:55 paulk
;; Adds a Classes index menu to the Emacs menubar.
;;
;; Revision 1.10 2000/05/11 03:07:17 paulk
;; Updated bovinator grammar.
;;
;; Revision 1.9 2000/05/11 01:24:40 paulk
;; Added support for Eric Ludlam's semantic bovinator. Moved regular expression-based
imenu indexer to this file.
;;
;; Revision 1.8 2000/03/16 05:18:11 paulk
;; Miscellaneous small bug fixes and enhancements.
;;
;; Revision 1.7 2000/03/08 03:47:02 paulk
;; Fixed regular expression in jde-parse-get-innermost-class-at-point to handle more
cases. Thanks to Steve Haflich <[EMAIL PROTECTED]> for reporting the problem and providing
a starting point for the fix.
;;
;; Revision 1.6 2000/02/16 04:40:33 paulk
;; Implemented Cygwin/XEmacs compatiblity fixes provided by Fred Hart
;; <[EMAIL PROTECTED]> in bsh-internal.
;;
;; Revision 1.5 2000/02/14 06:21:32 paulk
;; Fixed find innermost class regular expression.
;;
;; Revision 1.4 2000/02/09 05:18:10 paulk
;; Added methods for parsing symbol at point.
;;
;; Revision 1.3 2000/02/01 04:10:48 paulk
;; Fixed regular expression for classes to handle case where point is in
;; a constructor. Thanks to Francois Cogne <[EMAIL PROTECTED]>.
;;
;; Revision 1.2 1999/08/20 00:52:14 paulk
;; Added jde-parse-get-package-from-name function.
;;
;; Revision 1.1 1999/04/27 16:25:46 paulk
;; Initial revision
;;
*** jde/lisp/java.bnf Fri Jun 2 12:13:56 2000
--- java.bnf Thu Jun 8 09:12:52 2000
***************
*** 68,74 ****
((concat (car $1) (car $2)))
;
! variable-modifier : symbol
"\\(public\\|protected\\|private\\|static\\|final\\|transient\\)"
;
variable-modifier-list : variable-modifier variable-modifier-list
--- 68,74 ----
((concat (car $1) (car $2)))
;
! variable-modifier : symbol
"\\(public\\|protected\\|private\\|static\\|final\\|transient\\|volatile\\)"
;
variable-modifier-list : variable-modifier variable-modifier-list