diff lisp/packages/font-lock.el @ 10:49a24b4fd526 r19-15b6

Import from CVS: tag r19-15b6
author cvs
date Mon, 13 Aug 2007 08:47:52 +0200
parents ac2d302a0011
children 0293115a14e9
line wrap: on
line diff
--- a/lisp/packages/font-lock.el	Mon Aug 13 08:47:36 2007 +0200
+++ b/lisp/packages/font-lock.el	Mon Aug 13 08:47:52 2007 +0200
@@ -26,7 +26,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with XEmacs; see the file COPYING.  If not, write to the Free
-;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Synched up with: FSF 19.30 except for the code to initialize the faces.
 
@@ -75,7 +76,7 @@
 ;; the former is subdued, the latter is loud.
 ;;
 ;; You can make font-lock default to the gaudier variety of keyword
-;; highlighting by setting the variable `font-lock-use-maximal-decoration'
+;; highlighting by setting the variable `font-lock-maximum-decoration'
 ;; before loading font-lock, or by calling the functions
 ;; `font-lock-use-default-maximal-decoration' or
 ;; `font-lock-use-default-minimal-decoration'.
@@ -139,6 +140,8 @@
 
 ;;; Code:
 
+(require 'fontl-hooks)
+
 ;;;;;;;;;;;;;;;;;;;;;;      user variables       ;;;;;;;;;;;;;;;;;;;;;;
 
 (defvar font-lock-verbose t
@@ -1504,8 +1507,10 @@
 
 (put 'java-mode 'font-lock-defaults 
      '((java-font-lock-keywords
-	java-font-lock-keywords-1 java-font-lock-keywords-2)
-       nil nil ((?_ . "w")) beginning-of-defun))
+	java-font-lock-keywords-1 java-font-lock-keywords-2
+	java-font-lock-keywords-3)
+       nil nil ((?_ . "w")) beginning-of-defun
+       (font-lock-mark-block-function . mark-defun)))
 
 (put 'lisp-mode 'font-lock-defaults
      '((lisp-font-lock-keywords
@@ -2167,173 +2172,273 @@
 ;(defconst c++-font-lock-keywords c++-font-lock-keywords-1
 ;  "Additional expressions to highlight in C++ mode.")
 
+;; Java support from Anders Lindgren and Bob Weiner
+
 (defconst java-font-lock-keywords-1 nil
  "For consideration as a value of `java-font-lock-keywords'.
 This does fairly subdued highlighting.")
 
 (defconst java-font-lock-keywords-2 nil
  "For consideration as a value of `java-font-lock-keywords'.
-This does a lot more highlighting.")
+This adds highlighting of types and identifier names.")
+
+(defconst java-font-lock-keywords-3 nil
+ "For consideration as a value of `java-font-lock-keywords'.
+This adds highlighting of Java documentation tags, such as @see.")
+
+(defvar java-font-lock-type-regexp
+  (concat "\\<\\(boolean\\|byte\\|char\\|double\\|float\\|int"
+         "\\|long\\|short\\|void\\)\\>")
+  "Regexp which should match a primitive type.")
+
+(let ((capital-letter "A-Z\300-\326\330-\337")
+      (letter "a-zA-Z_$\300-\326\330-\366\370-\377")
+      (digit  "0-9"))
+(defvar java-font-lock-identifier-regexp
+  (concat "\\<\\([" letter "][" letter digit "]*\\)\\>")
+  "Regexp which should match all Java identifiers.")
+
+(defvar java-font-lock-class-name-regexp
+  (concat "\\<\\([" capital-letter "][" letter digit "]*\\)\\>")
+  "Regexp which should match a class or an interface name.
+The name is assumed to begin with a capital letter.")
+)
+
 
-(let ((storage (concat "static\\|abstract\\|const\\|final\\|"
-		       "synchronized\\|threadsafe\\|transient\\|native"))
-      (types (concat
-	      "boolean\\|int\\|char\\|byte\\|short\\|long\\|"
-	      "float\\|double\\|void"))
-      (reserved-words
-       '("private" "protected" "public" "break" "byvalue"
-	 "case" "catch" "class"
-	 "continue" "default" "do" "else if"
-	 "else" "extends" "false" "finally"
-	 "for" "if" "implements" "import"
-	 "instanceof" "interface"
-	 "new" "null" "package" "return"
-	 "super" "switch"
-	 "this" "throw" "throws"
-	 "true" "try" "synchronize" "while"))
+(let ((java-modifier-regexp
+       (concat "\\<\\(abstract\\|const\\|final\\|native\\|"
+	       "private\\|protected\\|public\\|"
+	       "static\\|synchronized\\|transient\\|volatile\\)\\>")))
 
-;      (java-token "\\w+")
-      (java-token "[a-zA-Z0-9_\.]+")
-      (java-modifying-token "[a-zA-Z0-9_\.]+\\([ \t]*\\[\\]\\)?")
-      )
+  ;; Basic font-lock support:
   (setq java-font-lock-keywords-1
-   (list
-    ;;------------------------------------------------------------------
-    ;; fontify C++-style comments as comments.
-    ;;------------------------------------------------------------------
+	(list
+	 ;; Keywords:
+	 (list        
+	  (concat
+	   "\\<\\("
+	   "break\\|byvalue\\|"
+	   "case\\|cast\\|catch\\|class\\|continue\\|"
+	   "do\\|else\\|extends\\|"
+	   "finally\\|for\\|future\\|"
+	   "generic\\|goto\\|"
+	   "if\\|implements\\|import\\|"
+	   "instanceof\\|interface\\|"
+	   "new\\|package\\|return\\|switch\\|"
+	   "throws?\\|try\\|while\\)\\>")
+	  1 'font-lock-keyword-face)
 
-    '("//.*" . font-lock-comment-face)
+	 ;; Modifiers:
+	 (list java-modifier-regexp 1 font-lock-type-face)
 
-    ;;------------------------------------------------------------------
-    ;; I think static deserves special attention
-    ;;------------------------------------------------------------------
-
-    '("static" . font-lock-keyword-face)
+	 ;; Special constants:
+	 '("\\<\\(this\\|super\\)\\>" (1 font-lock-reference-face))
+	 '("\\<\\(false\\|null\\|true\\)\\>" (1 font-lock-keyword-face))
 
-    ;;------------------------------------------------------------------
-    ;; Make the "public" keyword standout (should we do private instead?)
-    ;;------------------------------------------------------------------
-
-    ;; these depend on some personal SMF faces
+	 ;; Class names:
+	 (list (concat "\\<class\\>\\s *" java-font-lock-identifier-regexp)
+	       1 'font-lock-function-name-face)
 
-    ;; I wish I knew elisp, etc enough to know if it's
-    ;; faster to use 1 regex for n words, or n
-    ;; unglobbed entries in this list...
+	 ;; Package declarations:
+	 (list (concat "\\<\\(package\\|import\\)\\>\\s *"
+		       java-font-lock-identifier-regexp)
+	       '(2 font-lock-reference-face)
+	       (list (concat
+		      "\\=\\.\\(" java-font-lock-identifier-regexp "\\)")
+		     nil nil '(1 (if (= (char-after (match-end 0)) ?.)
+				     'font-lock-reference-face
+				   'font-lock-type-face))))
 
-    ;; '("private" . font-lock-pale-face)
-    ;; '("protected" . font-lock-pale-face)
-
-    ;;------------------------------------------------------------------
-    ;; special case so "new Foo();" doesn't map to method declaration
-    ;;------------------------------------------------------------------
+	 ;; Constructors:
+	 (list (concat
+		"^\\s *\\(" java-modifier-regexp "\\s +\\)*"
+		java-font-lock-class-name-regexp "\\s *\(")
+	       (list 3
+		     '(condition-case nil
+			  (save-excursion
+			    (goto-char (scan-sexps (- (match-end 0) 1) 1))
+			    (parse-partial-sexp (point) (point-max) nil t)
+			    (and (looking-at "\\($\\|\\<throws\\>\\|{\\)")
+				 'font-lock-function-name-face))
+			(error 'font-lock-function-name-face))))
 
-    (list (concat
-	   "^.*[ \t]+\\(new\\|return\\)[ \t]+"
-	   "\\(" java-token "\\)")
-	  2 'default)
-
-    ;;------------------------------------------------------------------
-    ;; special case so "else if();" doesn't map to method declaration
-    ;;------------------------------------------------------------------
+	 ;; Methods:
+	 (list (concat "\\(" java-font-lock-type-regexp "\\|"
+		       java-font-lock-class-name-regexp "\\)"
+		       "\\s *\\(\\[\\s *\\]\\s *\\)*"
+		       java-font-lock-identifier-regexp "\\s *\(")
+	       5
+	       'font-lock-function-name-face)
 
-    (list "^.*[ \t]+else[ \t]+\\(if\\)"
-	  1 'default)
+	 ;; Labels:
+	 (list ":"
+	       (list
+		(concat "^\\s *" java-font-lock-identifier-regexp "\\s *:")
+		'(beginning-of-line) '(end-of-line)
+		'(1 font-lock-reference-face)))
 
-    ;;------------------------------------------------------------------
-    ;; METHOD IDENTIFICATION
-    ;;
-    ;; fontify the (first word of) names of methods being defined.
-    ;;------------------------------------------------------------------
+	 ;; `break' and continue' destination labels:
+	 (list (concat "\\<\\(break\\|continue\\)\\>\\s *"
+		       java-font-lock-identifier-regexp)
+	       2 'font-lock-reference-face)
 
-    (list (concat
-	   "^[ \t]+"			;; indent of line
+	 ;; Case statements:
+	 ;; In Java, any constant expression is allowed.
+	 '("\\<case\\>\\s *\\(.*\\):" 1 font-lock-reference-face)))
+
+  ;; Types and declared variable names:
+  (setq java-font-lock-keywords-2
+	(append 
 
-	   ;;-------------------------------------------------------
-	   ;; Demanding a token 1st doesn't recognize constructors
-	   ;; w/out any access specifiers.  Unfortunately, that also
-	   ;; looks like many other things, including "if (foo) {",
-	   ;; so it's not an easy case to detect -- I'm just going
-	   ;; to live w/out it for now...
-	   ;;-------------------------------------------------------
+	 java-font-lock-keywords-1
+	 (list
+	  ;; Keywords followed by a type:
+	  (list (concat "\\<\\(extends\\|instanceof\\|new\\)\\>\\s *"
+			java-font-lock-identifier-regexp)
+		'(2 (if (= (char-after (match-end 0)) ?.)
+			'font-lock-reference-face 'font-lock-type-face))
+		(list (concat "\\=\\." java-font-lock-identifier-regexp)
+		      '(goto-char (match-end 0)) nil
+		      '(1 (if (= (char-after (match-end 0)) ?.)
+			      'font-lock-reference-face 'font-lock-type-face))))
 
-	   "\\(" java-modifying-token "[ \t]+\\)"
+	  ;; Keywords followed by a type list:
+	  (list (concat "\\<\\(implements\\|throws\\)\\>\\ s*"
+			java-font-lock-identifier-regexp)
+		'(2 (if (= (char-after (match-end 0)) ?.)
+			font-lock-reference-face font-lock-type-face))
+		(list (concat "\\=\\(\\.\\|\\s *\\(,\\)\\s *\\)"
+			      java-font-lock-identifier-regexp)
+		      '(goto-char (match-end 0)) nil
+		      '(3 (if (= (char-after (match-end 0)) ?.)
+			      font-lock-reference-face font-lock-type-face))))
 
-;	   "\\("
-;	   "\\(^[ \t]+\\(" java-token "[ \t]+\\)\\)"
-;	   "\\|"
-;	   "\\(    \\)"
-;	   "\\)"
-; failed attempt to hack in ^ followed by exactly 4 spaces allowance to
-; recognize constructions with no access specified
+	  ;; primitive types, can't be confused with anything else.
+	  (list java-font-lock-type-regexp
+		'(1 font-lock-type-face)
+		'(font-lock-match-java-declarations
+		  (goto-char (match-end 0))
+		  (goto-char (match-end 0))
+		  (0 font-lock-variable-name-face)))
 
-	   "\\(" java-modifying-token "[ \t]+\\)?"
-	   "\\(" java-modifying-token "[ \t]+\\)?"
-	   "\\(" java-modifying-token "[ \t]+\\)?"
-	   "\\(" java-modifying-token "[ \t]+\\)?"
-	   "\\(" java-modifying-token "[ \t]+\\)?"
-	   "\\(" java-token "\\)[ \t]*(")
-
-	 ;  "\\(" java-token "\\)[ \t]*(.*{")
-
-	  ;; SMF: while demanding { at EOL is stylistic,
-	  ;; it DOESN'T hilite the likes of:
-	  ;; return new Dimension()
-	  ;;	   "\\(" java-token "\\)[ \t]*(")
-	  ;; PROBLEM -- it leaves out abstract and native methods!
-
-	  13 'font-lock-function-name-face)
+	  ;; Declarations, class types and capitalized variables:
+	  ;;
+	  ;; Declarations are easy to recognize.  Capitalized words
+	  ;; followed by a closing parenthesis are treated as casts if they
+	  ;; also are followed by an expression.  Expressions beginning with
+	  ;; a unary numerical operator, e.g. +, can't be cast to an object
+	  ;; type.
+	  ;;
+	  ;; The path of a fully qualified type, e.g. java.lang.Foo, is
+	  ;; fontified in the reference face.
+	  ;;
+	  ;; An access to a static field, e.g. System.out.println, is
+	  ;; not fontified since it can't be distinguished from the
+	  ;; usage of a capitalized variable, e.g. Foo.out.println.
 
-    ;;------------------------------------------------------------------
-    ;; Fontify class names ...
-    ;; (info-node is another personal SMF face)
-    ;;------------------------------------------------------------------
-    
-    (list (concat
-	   "^[ \t]*\\([a-z]+[ \t]+\\)?\\([a-z]+[ \t]+\\)?class[ \t]+\\("
-	   java-token "\\)")
-	  3 'font-lock-reference-face)
+	  (list (concat java-font-lock-class-name-regexp
+			"\\s *\\(\\[\\s *\\]\\s *\\)*"
+			"\\(\\<\\|$\\|)\\s *\\([\(\"]\\|\\<\\)\\)")
+		'(1 (save-match-data
+		      (save-excursion
+			(goto-char
+			 (match-beginning 3))
+			(if (not (looking-at "\\<instanceof\\>"))
+			    'font-lock-type-face))))
+		(list (concat "\\=" java-font-lock-identifier-regexp "\\.")
+		      '(progn
+			 (goto-char (match-beginning 0))
+			 (while (or (= (preceding-char) ?.)
+				    (= (char-syntax (preceding-char)) ?w))
+			   (backward-char)))
+		      '(goto-char (match-end 0))
+		      '(1 font-lock-reference-face)
+		      '(0 nil))		; Workaround for bug in XEmacs.
+		'(font-lock-match-java-declarations
+		  (goto-char (match-end 1))
+		  (goto-char (match-end 0))
+		  (1 font-lock-variable-name-face))))))
 
-    ;;------------------------------------------------------------------
-    ;; Package names 
-    ;;------------------------------------------------------------------
-
-    (list (concat
-	   "package[ \t]+\\(" java-token "\\)")
-	  1 'font-lock-reference-face)
-
-    ;;
-    ;; Fontify case clauses.  This is fast because its anchored on the left.
+  ;; Modifier keywords and Java doc tags
+  (setq java-font-lock-keywords-3
+	(append
 
-    '("case[ \t]+\\(\\(\\sw\\|\\s_\\)+\\):". 1)
-    '("\\<\\(default\\):". 1)
-    ))
+	 '(
+	   ;; Feature scoping:
+	   ;; These must come first or the Modifiers from keywords-1 will
+	   ;; catch them.  We don't want to use override fontification here
+	   ;; because then these terms will be fontified within comments.
+	   ("\\<private\\>"   0 font-lock-string-face)
+	   ("\\<protected\\>" 0 font-lock-preprocessor-face)
+	   ("\\<public\\>"    0 font-lock-reference-face))
+
+	 java-font-lock-keywords-2
+
+	 (list
+
+	  ;; Java doc tags
+	  '("@\\(author\\|exception\\|param\\|return\\|see\\|version\\)\\s "
+	    0 font-lock-keyword-face t)
 
-  (setq java-font-lock-keywords-2
-   (append java-font-lock-keywords-1
-    (list
-     ;;
-     ;; fontify all storage classes and type specifiers
-     (cons (concat "\\<\\(" storage "\\)\\>") 'font-lock-type-face)
-     (cons (concat "\\<\\(" types "\\)\\>") 'font-lock-type-face)
-     
-     ;;
-     ;; fontify all builtin tokens
-	    (cons (concat
-		   "[ \t]\\("
-		   (mapconcat 'identity reserved-words "\\|")
-		   "\\)[ \t\n(){};,]")
-		  1)
-	    (cons (concat
-		   "^\\("
-		   (mapconcat 'identity reserved-words "\\|")
-		   "\\)[ \t\n(){};,]")
-		  1)
-	    )))
+	  ;; Doc tag - Parameter identifiers
+	  (list (concat "@param\\s +" java-font-lock-identifier-regexp)
+		1 'font-lock-variable-name-face t)
+
+	  ;; Doc tag - Exception types
+	  (list (concat "@exception\\ s*"
+			java-font-lock-identifier-regexp)
+		'(1 (if (= (char-after (match-end 0)) ?.)
+			font-lock-reference-face font-lock-type-face) t)
+		(list (concat "\\=\\." java-font-lock-identifier-regexp)
+		      '(goto-char (match-end 0)) nil
+		      '(1 (if (= (char-after (match-end 0)) ?.)
+			      'font-lock-reference-face 'font-lock-type-face) t)))
+
+	  ;; Doc tag - Cross-references, usually to methods 
+	  '("@see\\s +\\(\\S *[^][ \t\n\r\f(){},.;:]\\)"
+	    1 font-lock-function-name-face t)
+
+	  )))
   )
 
 (defvar java-font-lock-keywords java-font-lock-keywords-1
   "Additional expressions to highlight in Java mode.")
 
+;; Match and move over any declaration/definition item after
+;; point.  Does not match items which look like a type declaration
+;; (primitive types and class names, i.e. capitalized words.)
+;; Should the variable name be followed by a comma, we reposition
+;; the cursor to fontify more identifiers.
+(defun font-lock-match-java-declarations (limit)
+  "Match and skip over variable definitions."
+  (if (looking-at "\\s *\\(\\[\\s *\\]\\s *\\)*")
+      (goto-char (match-end 0)))
+  (and
+   (looking-at java-font-lock-identifier-regexp)
+   (save-match-data
+     (not (string-match java-font-lock-type-regexp
+			(buffer-substring (match-beginning 1)
+					  (match-end 1)))))
+   (save-match-data
+     (save-excursion
+       (goto-char (match-beginning 1))
+       (not (looking-at
+	     (concat java-font-lock-class-name-regexp
+		     "\\s *\\(\\[\\s *\\]\\s *\\)*\\<")))))
+   (save-match-data
+     (condition-case nil
+	 (save-restriction
+	   (narrow-to-region (point-min) limit)
+	   (goto-char (match-end 0))
+	   ;; Note: Both `scan-sexps' and the second goto-char can
+	   ;; generate an error which is caught by the
+	   ;; `condition-case' expression.
+	   (while (not (looking-at "\\s *\\(\\(,\\)\\|;\\|$\\)"))
+	     (goto-char (or (scan-sexps (point) 1) (point-max))))
+	   (goto-char (match-end 2)))   ; non-nil
+       (error t)))))
+
+
 (defvar tex-font-lock-keywords
 ;  ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>.
 ;  '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"