;;; java-font-lock-20a.el --- patch font-lock for Java in Gnu Emacs20

;;; For original, see emacs-20.3.1/lisp/font-lock.el

;; [original] Regexps written with help from Fred White <fwhite@bbn.com> and
;; Anders Lindgren <andersl@csd.uu.se>.
;; ...........................................................................

;;; 1999.03.26 Modifications by CarlManning (caroma@ai.mit.edu):
;;;            at http://www.ai.mit.edu/people/caroma/tools/

;; * Changed so type-modifiers (public, static, final, strictfp, etc.)
;;   are highlighted as keywords, not as types.
;; * Fixed handling of long class type names (e.g., java.io.File) so 
;;   name is highlighted as a type just when used as a type, and the
;;   entire name is highlighted.
;; * Reorganized levels (1999.03.26: back to 3 levels)
;;   level 1: class and method declaration names; comments, strings
;;   level 2: + keywords, primitive types
;;   level 3: + class types, labels, variable declaration names, literals
;; * literals: added numerical and character literals; recognizes only 
;;   valid character escapes; optionally recognizes valid strings 
;;   (checking character escapes in strings depends on java requirement
;;   that java strings must be terminated on same line)
;; * added line breaks to white space so fontifying buffer or block (M-g M-g)
;;   works on most constructs broken across lines.  
;;   (1999.03.26: Now space '1sp' parameterized, easier to change.)
;; * added @throws and other missing JavaDoc tags
;; * other fixes to labels, case, ...
;; 1999.03.26:  restored java-font-lock-extra-types
;; 1999.03.30:  fixes for ".class", default/level-1
;; ...........................................................................

;;; Limitations:

;; * While editing, font-lock only looks at the line being edited, so
;;   breaking a long line into two within a Java construct may remove the
;;   highlighting from the construct on either or both lines.  
;;   --> when done editing lines, run font-lock-fontify-block (M-g M-g)
;;   to re-fontify.  (Or run M-x font-lock-fontify-buffer .) 
;; * Some constructs cannot be disambiguated with regular expressions, which
;;   cannot match numbers of braces, parentheses, brackets, etc.  In
;;   particular, constructor declaration names with no preceding modifiers
;;   (such as "protected") cannot be reliably disambiguated from method calls.
;;   To handle the ambiguous case where "name(" is the first thing on a line,
;;   and thus could be a method call or the start of an unmodified constructor
;;   declaration, this code depends on the conventions that such constructor
;;   declarations are the first text on its line, and that class names are
;;   capitalized while method names are not.  (Alternate code which does not
;;   highlight this case is given in comment.)
;; * use '\"' instead of '"' for java literal of quote character
;; ...........................................................................

;;; Installation: 

;; Load this file from your .emacs file.  If you use JDE [Java Development
;; mode for Emacs], you may want to put its (require 'jde) in your .emacs file
;; before loading this file, so that the patch created here isn't overridden
;; by loading JDE after it.  For example:
;;
;; (require 'jde)  ;; optional
;; (load "java-font-lock20a")
;;   
;; To enable font-locking everywhere:
;;
;; (global-font-lock-mode t) ;; optional
;;
;; Customize colors as described below in 
;; the section titled "Coloring --- Strategies you may wish to keep in mind".
;;
;; Optional:  To customize the font-lock level to level 1, 2, or 3 
;; (described above), use the Help|Customize|Specific Option menus 
;; to customize font-lock-maximum-decoration for java-mode and/or jde-mode.  
;; You may need to m-x revert-buffer in the java buffer to see difference.
;; Once you save for future sessions, it adds something like the folowing to
;; your .emacs file:
;; (custom-set-variables
;;  '(font-lock-maximum-decoration (quote ((java-mode . 1) (jde-mode . 1))))
;;  )
;;
;;   [Note: In jde-2.2.6 (Dec2000), jde-java-font-lock defines a fourth level,
;;    and is broken so that emacs must always display its maximum
;;    fontification.   If you want to choose the levels defined here, then
;;    use the following: 
;;      1. turn off jde's font-lock
;;        (custom-set-variables '(jde-use-font-lock nil))
;;      2. remove jde-mode font-lock-defaults
;;        (flet ((del-jde (keywords-alist)
;;           (delq (assq 'jde-mode keywords-alist) keywords-alist)))
;;          (setq font-lock-keywords-alist (del-jde font-lock-keywords-alist))
;;          (setq font-lock-defaults-alist (del-jde font-lock-defaults-alist)))
;;      3. set jde-mode font-lock-defaults to be shared with java-mode
;;        (push `(jde-mode ,@(cdr (assq 'java-mode font-lock-defaults-alist)))
;;              font-lock-defaults-alist)
;;    End note.]     
;;
;; Very Optional: Java mode uses the standard offset of 4 as is used in
;; Sun's source code, but this means indentation doesn't tell you where the 
;; body starts in if statements like:
;;    if (component != null &&
;;	  component.getRowHeight() != rowHeight) {
;;	  component.setRowHeight(getRowHeight()); 
;;    }
;; To customize java style so indent (c-basic-offset) is 2, not 4:
;; (add-hook 'java-mode-hook '(lambda () (setq c-basic-offset 2)))
;; ...........................................................................

;;; Coloring --- Strategies you may wish to keep in mind:

;;  o Reserve more noticeable color (e.g., reds) just for words 
;;    that you must scan for from greater distances, e.g., 
;;    method definition names, not words within methods.
;;  o Use low contrast colors for close-distance highlighting:
;;    Preserve horizontal readability of program text by coloring 
;;    keywords, types, and literals with colors that are similar 
;;    in intensity to the default text color, not high contrast 
;;    colors.  Garish, high-contrast coloring distracts the eye 
;;    into noticing the pattern formed by the colors, e.g., grouping
;;    magenta words on adjacent lines, making them more difficult to
;;    read horizontally.  You can also reduce this effect by reducing
;;    the coloring, e.g., by leaving types the default color.
;;
;; Example color schemes using above strategies for your .emacs file:
;; 1. For many-color screen, Black text on White/FloralWhite/etc. background,
;;    or White text on Black/dark background:
;;(custom-set-faces
;; '(font-lock-comment-face
;;   ((((class color) (background light)) (:foreground "ForestGreen"))
;;    (((class color) (background dark))  (:foreground "PaleGreen"))))
;; '(font-lock-string-face
;;   ((((class color) (background light)) (:foreground "SlateGray"))
;;    (((class color) (background dark))  (:foreground "SlateGray1"))))
;; '(font-lock-function-name-face ;; definition names (classes, methods, etc.)
;;   ((((class color) (background light)) (:foreground "Firebrick"))
;;    (((class color) (background dark))  (:foreground "LightSalmon1"))))
;; '(font-lock-keyword-face
;;   ((((class color) (background light)) (:foreground "Blue3"))
;;    (((class color) (background dark))  (:foreground "LightBlue1"))))
;; '(font-lock-builtin-face ;; not used
;;   ((((class color) (background light)) (:foreground "Blue3"))
;;    (((class color) (background dark))  (:foreground "LightBlue1"))))
;; '(font-lock-constant-face
;;   ((((class color) (background light)) (:foreground "SlateGray"))
;;    (((class color) (background dark))  (:foreground "SlateGray1"))))
;; '(font-lock-type-face
;;   ((((class color) (background light)) (:foreground "Purple3"))
;;    (((class color) (background dark))  (:foreground "Thistle1"))))
;; '(font-lock-variable-name-face
;;   ((((class color) (background light)) (:foreground "DarkGoldenrod4"))
;;    (((class color) (background dark))  (:foreground "Khaki2"))))
;; )
;; 2. For few-color screen (e.g., 16 color LCD), Black text on White background
;;    or White text on Black background:
;;(custom-set-faces
;; '(font-lock-comment-face
;;   ((((class color) (background light)) (:foreground "DarkGreen"))
;;    (((class color) (background dark))  (:foreground "Green"))))
;; '(font-lock-string-face
;;   ((((class color) (background light)) (:foreground "Gray50"))
;;    (((class color) (background dark))  (:foreground "Gray75"))))
;; '(font-lock-function-name-face ;; definition names (classes, methods, etc.)
;;   ((((class color) (background light)) (:foreground "DarkRed"))
;;    (((class color) (background dark))  (:foreground "Red"))))
;; '(font-lock-keyword-face
;;   ((((class color) (background light)) (:foreground "DarkBlue"))
;;    (((class color) (background dark))  (:foreground "Cyan"))))
;; '(font-lock-builtin-face ;; not used
;;   ((((class color) (background light)) (:foreground "DarkBlue"))
;;    (((class color) (background dark))  (:foreground "Cyan"))))
;; '(font-lock-constant-face
;;   ((((class color) (background light)) (:foreground "Gray50"))
;;    (((class color) (background dark))  (:foreground "Gray75"))))
;; '(font-lock-type-face
;;   ((((class color) (background light)) (:foreground "DarkMagenta"))
;;    (((class color) (background dark))  (:foreground "Magenta"))))
;; '(font-lock-variable-name-face
;;   ((((class color) (background light)) (:foreground "Gold4"))
;;    (((class color) (background dark))  (:foreground "Yellow"))))
;; )
;; ..........................................................................

;;; Design Rationales

;; Q. How is it that coloring works on some constructs broken into two lines
;;    when file is read in, but not after editing the second line?
;; A. While editing, font-lock looks only at the current line being edited,
;;    so if it doesn't provide all the context needed to make a coloring,
;;    it will not perform the coloring.  When an entire buffer or top level
;;    definition is fontified, (such as when a file is read in, when
;;    font-lock-fontify-buffer is run, or font-lock-fontify-block is run)
;;    font-lock can take the time to look at context across all line breaks.
;; Q. How is this better than making line coloring and buffer coloring behave
;;    the same?
;; A. Line breaks within syntax such as method declarations are inevitable
;;    in many systems with long, descriptive type and method names, e.g.,:
;;      public IOutlineComponentGenerator
;;        getExactOutlineGenerator(OutlineComponent aComponent) {
;;          ...
;;      }
;;    Coloring uses the type before and the "(" afterward to recognize 
;;    the method declaration name, but in systems with long names there
;;    may be no good line break that will keep these on one line.
;;
;;    Because code is read/scanned more often than it is written/edited, 
;;    it is preferrable to handle line breaks as follows: 
;;      a. make consistent coloring the default appearance (no missing
;;         coloring just because a line is broken in a file that is read in; 
;;         coloring works no matter where line is broken).
;;      b. coloring may disappear in an edit that involves a line break.
;;      c. coloring can be restored at any time by refontifying block.
;;         This is easy with font-lock-fontify-block (M-g M-g).
;;    This is more graceful degradation rather than completely failing to 
;;    color (which is source of bug reports).
;; 
;;    [Known exception: Adding multi-line coloring to c-style declarations 
;;     with multiple declarators such as
;;       int x = expression1(),
;;           y = expression2();
;;     has not yet been implemented [maybe use the next semicolon as end
;;     instead], but splitting this construct across lines is relatively
;;     rare and coloring can easily be fixed by splitting them into two 
;;     declarations so both variable declarators have a type.
;;       int x = expression1();
;;       int y = expression2();  ]  -- caroma
;;    [Note you can also break coloring by putting a comment in the middle]

;;; Code:

;; Load font-lock first, so these patches won't be overridden
(require 'font-lock) 

(defcustom java-font-lock-extra-types
  '("[A-Z\300-\326\330-\337]\\w*")
  "*List of extra types to fontify in Java mode.
Each list item should be a regexp not containing word-delimiters.
For example, a value of (\"[A-Z\300-\326\330-\337]\\\\w*\") 
means capitalized words are accepted as simple class names.

The value of this variable is used when Font Lock mode is turned on."
  :type 'font-lock-extra-types-widget
  :group 'font-lock-extra-types)

(defconst java-font-lock-keywords-1 nil
  "Subdued level declaration highlighting for Java mode: 
   class & method declaration names, commments, strings.
   See also `java-font-lock-extra-types'.")

(defconst java-font-lock-keywords-2 nil
  "Medium level reserved word highlighting for Java mode:
   keywords, primitive types, literal words (null/true/false);
   class & method names, commments, strings.
   See also `java-font-lock-extra-types'.")

(defconst java-font-lock-keywords-3 nil
  "Gaudy level type highlighting for Java mode,
   (best used with low-contrast colors):
   class types, imports, labels,
   variable (& field) declarator names,
   keywords, primitive types, literals,
   class & method names, commments, strings.
   See also `java-font-lock-extra-types'.")

(let* ((java-keywords
	(eval-when-compile
	  (regexp-opt
	   '("break" "case" "catch" "class" "continue" "default" "do" "else"
	     "extends" "finally" "for" "if" "implements" "instanceof"
	     "interface" "new" "return" "switch" "throw" "throws" "super"
	     "synchronized" "this" "try" "while" "goto"))))
       (java-type-modifiers
	(eval-when-compile
	  (regexp-opt
	   '("abstract" "final" "public" "private" "protected" "static"
	     "synchronized" "transient" "volatile" "native" "const"
	     "strictfp"))))
       (java-type-modifiers-depth (regexp-opt-depth java-type-modifiers))
       (java-primitive-types
	(eval-when-compile
	  (regexp-opt '("boolean" "char" "byte" "short" "int" "long"
			"float" "double" "void"))))
       ;; Space within Java constructs:
       ;; A. let 1sp be "[ \t]" and font-lock will consistently never fontify 
       ;; a Java construct across a line break.
       ;; B. let 1sp be "[ \t\n\r]" and font-lock-fontify-buffer and
       ;; font-lock-fontify-block will fontify java constructs broken across
       ;; a line break, but editting the lines will not, e.g., in method
       ;; definitions broken across lines due to long type names, such as:
       ;;   public IOutlineComponentGenerator
       ;;     getMostSpecificOutlineGenerator(OutlineComponent aComponent, ...
       ;; Font-lock-fontify-block (M-g M-g) refontifies after editing a
       ;; construct with a line break.  -- caroma, 1999.03
       (1sp "[ \t\n\r]")
       (sp* (concat 1sp "*"))
       (sp+ (concat 1sp "+"))
       ;; Regexps involving class names are evaluated later so they
       ;; can incorporate customized java-font-lock-extra-types.
       ;; 
       ;;   simple class names have no package prefix, and by convention 
       ;;   are capitalized ("[A-Z\300-\326\330-\337]\\w*")
       (java-simple-class-name-expr
	`(mapconcat 'identity java-font-lock-extra-types "\\|"))
       ;;   class names may have optional package prefix
       (java-class-name-expr
	`(concat "\\(\\w+[.]\\)*"
		 "\\(" ,java-simple-class-name-expr "\\)"))
       (java-all-types-expr
	;; note: parens around java-primitive-types needed to avoid mysterious
	;; regexp stack overflow on "bxx.Yxx xxx(" [initial 'b' is significant]
	`(concat "\\(" ,java-primitive-types "\\)\\|" ,java-class-name-expr))
       (java-all-types-depth-expr
	`(regexp-opt-depth ,java-all-types-expr))
       (optional-brackets-or-space
	(concat sp* "\\(\\[" sp* "\\]" sp* "\\)*"))
       (optional-brackets-or-space-depth
	(regexp-opt-depth optional-brackets-or-space))
       ;; Numerical & character literals.  Java's syntax for character
       ;; literals can be hard to remember in all its variations 
       ;; (literal chars, escaped chars, escape sequences, unicode, octal), 
       ;; so highlight only correct character syntax.  Syntax for literals
       ;; is described in the Java Language Specification:
       ;; http://java.sun.com/docs/books/jls/html/3.doc.html#48272
       (java-int-literal
	"\\<\\([0-9]+\\|0[xX][0-9A-Fa-f]+\\)[lL]?\\>")
       (java-float-literal
	"\\<[0-9]+\\([.][0-9]*\\)?\\([eE]?[-+]?[0-9]+\\)?[fFdD]?\\>")
       (java-char-escapes
	(concat "[\\][btnfr\"'\\]\\|" 
		;; unicode char specified using ascii: exactly 4 hex digits
		"[\\]u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]\\|"
		;; octal char: 1-3 octal digits
		"[\\][0-3]?[0-7]?[0-7]"))
       (java-char-literal
	(concat "'\\([^'\\\n\r]\\|" java-char-escapes "\\)'"))
       ;; Option to catch illegal escape sequences in strings; see use below
       ;;(java-string-literal;;Java string literals must terminate on same line
       ;; (concat "\"\\([^\"\\\n\r]\\|" java-char-escapes "\\)*\"?"))
       )
  (setq java-font-lock-keywords-1
	(list
	 ;; Fontify class and interface keywords and their declaration names.
	 (cons 'eval
	       `(list (concat "\\<\\(class\\|interface\\)\\>" ,sp+
			      "\\(" ,java-simple-class-name-expr "\\)?")
		      '(2 font-lock-function-name-face nil t)))
	 ;; Fontify method declaration names [...<type> <name> '('...]
	 (cons 'eval
	       `(list (concat "\\<\\(" ,java-all-types-expr "\\)\\>"
			      ,optional-brackets-or-space
			      "\\<\\(\\w+\\)\\>" ,sp* "(")
		      (list (+ 2
			       ,java-all-types-depth-expr
			       ,optional-brackets-or-space-depth)
			    'font-lock-function-name-face nil t)))
	 ;; Fontify constructor declaration name [...<modifier> <Name>'('...]
	 ;; A. This version does not highlight capitalized method calls,
	 ;;    nor unmodified constructor declarations.
	 ;; (cons 'eval
	 ;;  `(list
	 ;;    (concat "\\(\\<\\(" ,java-type-modifiers "\\)\\>" ,sp* "\\)"
	 ;;            "\\<\\(" ,java-simple-class-name-expr "\\)\\>" ,sp* "(")
	 ;;    '(,(+ 2 java-type-modifiers-depth)
	 ;;      font-lock-function-name-face nil t)))
	 ;; B. This version highlights unmodified constructor declarations,
	 ;;    but also capitalized method calls at beginning of line.
	 (cons 'eval
	       `(list (concat "^[ \t]*" ;; first thing on line
			      "\\(\\<\\(" ,java-type-modifiers "\\)\\>"
			      ,sp* "\\)*"
			      "\\<\\(" ,java-simple-class-name-expr "\\)\\>"
			      ,sp* "(")
		      '(,(+ 3 java-type-modifiers-depth)
			font-lock-function-name-face nil t)))
	 ;; Fontify strings.  Java strings must be terminated on the same line;
	 ;; makes sure starting " is not preceded by \ (or is at start of line)
	 ;; [optional; catches illegal escape sequences in strings, assuming
	 ;;  font-lock-string-face and font-lock-constant-face are different]
	 ;;`(,(concat "\\([^\\]\\|^\\)\\(" java-string-literal "\\)")
	 ;;  (2 font-lock-constant-face t))
	 ))

  (setq java-font-lock-keywords-2
	(append
	 java-font-lock-keywords-1
	 (list
	  ;; Fontify all keywords
	  (concat
	   "\\<\\(" java-keywords "\\|" java-type-modifiers "\\)\\>")
	  ;; Fontify all primitive type reserved words.
	  `(,(concat "\\<\\(" java-primitive-types "\\)\\>")
	    (1 font-lock-type-face))
	  ;; Fontify all literal reserved words.
	  '("\\<\\(null\\|false\\|true\\)\\>" . font-lock-constant-face))))

  (setq java-font-lock-keywords-3
	(append
	 java-font-lock-keywords-2
	 (list	  
	  ;; Fontify Class type names:
	  ;; class type names in casts.
	  (cons 'eval
		`(list (concat "(\\<\\(" ,java-all-types-expr "\\)\\>"
			       ,optional-brackets-or-space ")"
			       ,sp* "\\(\\w\\|[\"\(]\\)")
		       '(1 font-lock-type-face)))
	  ;; throws/implements/extends (interfaces) followed by list.
	  (cons 'eval
		`(list
		  (concat "\\<\\(throws\\|implements\\|extends\\)\\>" ,sp* 
			  "\\(\\<\\(" ,java-class-name-expr "\\)\\>" ,sp*
			  "\\(," ,sp* "\\<\\(" ,java-class-name-expr "\\)\\>"
			  ,sp* "\\)*\\)?")
		  '(1 font-lock-keyword-face)
		  '(2 font-lock-type-face nil t)
		  ;;(3 font-lock-type-face nil t)	    
		  ;;(,(+ 5 java-class-name-depth) font-lock-type-face nil t)
		  ))
	  ;; instanceof/new can be followed by a class name
	  (cons 'eval
		`(list (concat "\\<\\(instanceof\\|new\\)\\>" ,sp+
			       "\\<\\(" ,java-class-name-expr "\\)\\>?")
		       '(1 font-lock-keyword-face)
		       '(2 font-lock-type-face nil t)))
	  ;; Type names immediately followed by a parameter or declarator name
	  ;; [Cannot be combined with with parameter or declarator name
	  ;;  coloring, which is next, as it would then miscolor type names
	  ;;  after the first on the line as parameter names.  E.g., in
	  ;;  void foo(Class1 p1, Class2 p2) colors Class2 as var name.]
	  (cons 'eval
		`(list
		  (concat "\\<\\(" ,java-all-types-expr "\\)\\>"
			  ,optional-brackets-or-space "\\<")
		  ;; fontify type 
		  '(1 font-lock-type-face)))
	  ;; Type names immediately followed by one or more 
	  ;; variable (or field) declarators
	  (cons
	   'eval
	   `(list
	     (concat "\\<\\(" ,java-all-types-expr "\\)\\>"
		     ,optional-brackets-or-space "\\<")
	     ;; Fontify each declarator item in declaration.
	     '(font-lock-match-java-style-declaration-item-and-skip-to-next
	       ;; Start and finish with point after the type specifier.
	       nil (goto-char (match-end 0))
	       ;; Fontify as a variable name.
	       (1 font-lock-variable-name-face))))
	  ;; Fontify break/continue and targets
	  `(,(concat "\\<\\(break\\|continue\\)" sp+ "\\(-?\\w+\\)?")
	    (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
	  ;; Other literals (null/true/false and strings already highlighted)
	  `(,(mapconcat 'identity
			;; (float must be before int) 
			(list java-float-literal java-int-literal
			      java-char-literal)
			"\\|")
	    . font-lock-constant-face)
	  ;; Labels: 
	  `(":" ("^[ \t]*\\(\\w+\\):" ;; no space before ':', unlike (?:) exprs
		 (beginning-of-line) (end-of-line)
		 (1 font-lock-constant-face)))
	  ;; Fontify package and class names in import directives.
	  (cons 'eval 
		`(list
		  "\\<\\(import\\)\\>"
		  '(1 font-lock-keyword-face)
		  (list
		   (concat "\\=" ,sp+
			   "\\<\\(" ,java-class-name-expr "\\)\\>"
			   "\\(" ,sp* ";\\)")
		   nil nil '(1 font-lock-type-face))
		  (list 
		   (concat "\\=" ,sp+
			   "\\<\\(\\w+\\([.]\\w+\\)*\\)\\>"
			   "\\([.][*]" ,sp* ";\\)?")
		   nil nil '(1 font-lock-constant-face))))
	  `(,(concat "\\<\\(package\\)" sp+ "\\(\\w+\\([.]\\w+\\)*\\)?")
	    (1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
	  ;; Javadoc tags within comments.  Syntax of JavaDoc tags within 
	  ;; documentation comments is described in (fold URL into one line):
	  ;; http://java.sun.com/products/jdk/1.2/docs/tooldocs/win32/
	  ;; javadoc.html#documentationcomments
	  (cons 'eval
		`(list
		  "^[ \t]*\\([/][*][*][ \t]*\\)?\\([*][ \t]*\\)*\\(@\\)\\<"
		  '(3 font-lock-constant-face prepend)
		  ;; Anchor: @ at start of line, w/opt preceding space,*,"/**"
		  ;; Tag arguments are set in constant face just like tag; 
		  ;;   setting them in other faces makes it hard see where 
		  ;;   code starts. 
		  ;; Text descriptions are like rest of comment.
		  '(,(concat "\\=\\<"
			     (regexp-opt '("author" "deprecated" "return" 
					   "since" "see" "serial" "serialData"
					   "version") t)
			     "\\>")
		    nil nil (1 font-lock-constant-face prepend t))
		  (list (concat "\\=\\<\\(exception\\|throws\\)\\>"
				,sp* "\\(" ,java-class-name-expr "\\)?")
			nil nil
			'(1 font-lock-constant-face prepend)
			'(2 font-lock-constant-face prepend t)) ;; type
		  '(,(concat "\\=\\(param\\)" sp+ "\\(\\w+\\)?")
		    nil nil 
		    (1 font-lock-constant-face prepend)   
		    (2 font-lock-constant-face prepend t)) ;; variable-name
		  (list (concat "\\=\\(serialField\\)" ,sp+ "\\(\\w+\\)?"
				,sp+ "\\(" ,java-class-name-expr "\\)?")
			nil nil 
			'(1 font-lock-constant-face prepend)
			'(2 font-lock-constant-face prepend t)    ;; var-name
			'(3 font-lock-constant-face prepend t)))) ;; type
	  ;; link tags can be embedded anywhere
	  '("\\({@link\\>[^}\n\r]*}?\\)" ;; no newlines in link tag
	    (1 font-lock-constant-face prepend))
	  )))
  ;; set 'default'
  (setq java-font-lock-keywords java-font-lock-keywords-1)
  )

(defun font-lock-match-java-style-declaration-item-and-skip-to-next (limit)
  ;; run only if preceding anchor word is not in a comment or string
  ;; as marked by font-lock-fontify-syntactically-region
  (when (save-excursion
	  (save-match-data
	    (and (re-search-backward "\\<\\w+\\>" (point-min) t)
		 (let ((start (match-beginning 0))
		       (end (match-end 0)))
		   (and (text-property-not-all
			 start end 'face font-lock-comment-face)
			(text-property-not-all
			 start end 'face font-lock-string-face))))))
    (font-lock-match-c-style-declaration-item-and-skip-to-next limit)))

;; install patch to font-lock in 20.3
;;
;;	(java-mode-defaults
;;	 '((java-font-lock-keywords java-font-lock-keywords-1
;;	    java-font-lock-keywords-2 java-font-lock-keywords-3)
;; -->	   nil nil ((?' . "$") (?_ . "w") (?$ . "w")) nil
;;	   (font-lock-mark-block-function . mark-defun)))
;;
;; 1. font-lock.el in 20.3 gives ?.  "w" syntax in java mode; delete that.
;; Matching bogs down if \\w matches '.'s, especially in strings of ...'s
;; 2. make sure ?' has delimiter syntax in java modes so only valid
;; characters are highlighted; default seems to be string syntax.

(require 'cl) ;; for flet if jde not loaded
(flet ((patch-mode-defaults (name-of-mode)
         (let ((mode-defaults (assq name-of-mode font-lock-defaults-alist)))
	   (when mode-defaults
	     (setcar (cddddr mode-defaults)
		     (let ((syntax-defaults (car (cddddr mode-defaults))))
		       (list* '(?' . "$")
			      (delq (assq ?' syntax-defaults) 
				    (delq (assq ?. syntax-defaults)
					  syntax-defaults)))))))))
  (patch-mode-defaults 'java-mode)
  ;; do same for jde-mode if it is loaded
  (patch-mode-defaults 'jde-mode))

;; patch 20.3 font-lock's value of java-font-extra-types so it will work for 
;; classnames like URL and simple examples like
;;   class A {
;;     A() {}
;;   }
;;   class B extends A {
;;     B() {}
;;   }
(let ((cons-cell (member "[A-Z\300-\326\330-\337]\\sw+"
			java-font-lock-extra-types)))
  (if cons-cell (setcar cons-cell "[A-Z\300-\326\330-\337]\\w*")))

