;; A major mode for Java.  -*- lexical-binding: nil; -*-
;;
;; Usage for your Emacs initialization file:
;;
;;    (require 'java-deprecated-mode)
;;    (setq font-lock-maximum-decoration '((java-deprecated-mode . 1)(t . t)))
;;
;; Maximum decoration must be '1' in order to constrain the parent `java-mode` to minimal decorations.
;; Only its multi-line comments are needed here, because I do not yet know how to code them myself.
;;
;; PUBLIC at `http://reluk.ca/sys/computer/workstation/etc/emacs/` because my Emacs initialization
;; file refers to it there.  http://reluk.ca/.emacs.d/lisp/initialization.el


(defun java-deprecated-add-font-lock-js-common()
  "Adds font-locking common to modes java-deprecated and js-deprecated."
  (font-lock-add-keywords nil
   '(
     ;; Javadoc
     ;; -------
     ("^[ \t]*\\(?:/\\*\\)?\\*[ \t]+\\([^\n]+\\)$" (1 'font-lock-doc-face t))
     ("^[ \t]*\\(?:/\\*\\)?\\*[ \t]+\\(@\\)\\([a-z]+\\)\\>"
      (1 'font-lock-comment-face t) (2 'java-deprecated-pragma t))
     ("^[ \t]*\\(?:/\\*\\)?\\*[ \t]+@param[ \t]+\\(\\w+\\)\\>" (1 'java-deprecated-pragma-param t))

     ;; Punctuation
     ;; -----------
     ("[;,:]" . 'font-lock-comment-face)
     ("['\"]" 0 'font-lock-comment-face t)
     ("[{}]" . 'java-deprecated-subdued)

     )
   )
  )



(defun java-deprecated-add-font-lock-js-common-salvage() ; no longer actually common, only java-deprecated calls this
  "Adds font-locking common to modes java-deprecated and js-deprecated (salvage)."
  (font-lock-add-keywords nil
   '(
     ;; Comment edge
     ;; ------------
   ; ("^ *\\(///.*\\)$" 1 'header-line t)
   ; ("^ *\\(//\\)" 1 'header-line t)

     ;; Commented-out line
     ;; ------------------
   ; ("^\\(//.*\\)$" 1 'header-line t)

     )
   )
  )



(define-derived-mode java-deprecated-mode java-mode ; deriving from the Java mode bundled with Emacs
  "Java MCA"
  "Major mode for editing Java source code"
  (java-deprecated-add-font-lock-js-common)
  (java-deprecated-add-font-lock-js-common-salvage)
    ;;; Added first, common ones get lower precedence.  This ensures (e.g.) that generic
    ;;; parameters separated by commas are fontified.
  (font-lock-add-keywords nil ; on such usage of font-lock-add-keywords, see js-deprecated-mode
   '(
     ;; Keyword
     ;; -------
     ("\\<\\(catch\\|do\\|else\\|finally\\|for\\|if\\|return\\|switch\\|throw\\|try\\|while\\)\\>"
      . 'font-lock-keyword-face)
     ("\\<\\(break\\|case\\|continue\\|goto\\)\\>[ \t]*\\(-?\\w+\\)?" ; copied from an old version of Emacs
      (1 'font-lock-keyword-face) (2 'font-lock-constant-face nil t))
       ;;; this must follow the above

     ;; Label
     ;; -----
 ;;; ("^[ \t]*\\(\\w+\\)[ \t]*:[ \t]*$"
 ;;;; but allow the label to be followed by a statement on the same line:
     ("^[ \t]*\\(\\w+\\)[ \t]*:"
    ; (beginning-of-line) (end-of-line) (1 'font-lock-constant-face))
    ;; Purpose of moving point to beginning and end is now unclear.
    ;; It caused unstable (on again, off again) matching in property names of JavaScript literals;
    ;; at least in these ones: /home/mike/work/waymaker/spec/build/android/Target.js.  So drop it:
      (1 'font-lock-constant-face))

     ;;
     ;;
     ;; ^ ^ ^ each of the above is given top placement just to be sure,
     ;;       because e.g. it was moved here from java-deprecated-add-font-lock-js-common*
     ;;
     ;;

     ;; GWT JSNI methods
     ;; ----------------
   ; ("/\\*-[{]\\(.*\\)\\}-\\*/;" 1 'font-lock-constant-face t) ; t override existing fontification
   ;   ; [{] is needed instead of \\{, or it messes up (Emacs 23.1.1)
   ;; no point, because this won't do multi-line font-lock, which is difficult

     ;; Type parameter
     ;; --------------
     (                                                                        "\\w\\(<\\)\\(\\(?:[][[:word:]?., <]\\|>+,\\)*>*\\)\\(>\\)"  (1 'font-lock-comment-face)(2 'font-lock-builtin-face)(3 'font-lock-comment-face))
     ("\\(?:^\\|final\\|static\\|private\\|protected\\|public\\) +\\(?:@\\w+ +\\)?\\(<\\)\\(\\(?:[][[:word:]?., <]\\|>+,\\)+>*\\)\\(>\\) " (1 'font-lock-comment-face)(2 'font-lock-builtin-face)(3 'font-lock-comment-face))
     ;;                                                                ''A''                      ][                 >+,    >*
     ;; A   annotation
     ;; ][  inclusion of ']' and '[' in choice list
     ;; >+, nested closing brackets (intermediate)
     ;; >*  nested closing brackets (trailing)  In both cases a following space is disallowed;
     ;;       or, given "Foo<T,U> implements Bar<T>", it might wrongly capture all "<T,U> implements Bar<T>".

     ;; Subdued keyword
     ;; ---------------
     ;; get these out of the way, or extends|implements can be taken as variable names
     ("\\<\\(extends\\|implements\\|native\\|throws\\|void\\)\\>"
      . 'java-deprecated-subdued)
     ;; (continued further below, reason for separation unknown)

     ;; Method, variable or constant declaration
     ;; ----------------------------------------
     ("[^@]\\<[A-Z][A-Za-z0-9_.]*\\(?:<[^>]+>+\\)?\\(?:\\[\\]\\)* +\\([a-z_]\\w*\\)\\>(" 1 'font-lock-function-name-face)
     ;; 'A'   ''''''''T''''''''''     '''TP'''         ''[]''         '''''N''''
     ("[^@]\\<[A-Z][A-Za-z0-9_.]*\\(?:<[^>]+>+\\)?\\(?:\\[\\]\\)* +\\([a-z_]\\w*\\|[A-Z_][A-Z0-9_]*\\)\\>[^(]" 1 'font-lock-variable-name-face)
     ;; 'A'   ''''''''T''''''''''     '''TP'''         ''[]''         '''''N'''''''''''''''''''''''
     ;; A  annotations ignored, not taken as type name
     ;; T  type
     ;; TP optional type parameter
     ;; [] optional array brackets
     ;; N  method, variable or constant name

     ("\\<\\(?:boolean\\|byte\\|char\\|double\\|float\\|int\\|long\\|short\\|void\\)\\(?:\\[\\]\\)* +\\([a-z_]\\w*\\)\\>(" 1 'font-lock-function-name-face)
     ;;        '''''''''''''''''''''''''''''''''''T''''''''''''''''''''''''''''''        ''[]''         '''''N''''
     ("\\<\\(?:boolean\\|byte\\|char\\|double\\|float\\|int\\|long\\|short\\|void\\)\\(?:\\[\\]\\)* +\\([a-z_]\\w*\\|[A-Z_][A-Z0-9_]*\\)\\>[^(]" 1 'font-lock-variable-name-face)
     ;;        '''''''''''''''''''''''''''''''''''T''''''''''''''''''''''''''''''        ''[]''         '''''N'''''''''''''''''''''''
     ;; T  type
     ;; [] optional array brackets
     ;; N  method or variable name

     ;; Annotation  (copied from old version of Emacs)
     ;; ----------
     ("\\(@\\)\\(\\w+\\(?:\\.\\w+\\)*\\)\\(?: *\\((\\) *\\([^)]*\\)\\()\\)\\)?"
      (1 'font-lock-comment-face) (2 'java-deprecated-subdued) (3 'java-deprecated-subdued t t)
      (4 'font-lock-comment-face t t) (5 'java-deprecated-subdued t t))

     ;; Type declaration
     ;; ----------------
     ("\\(?:[^.]\\|^\\)\\<\\(?:class\\|enum\\|interface\\)\\>[ \t]*\\(\\w+\\)?"
      1 'font-lock-type-face nil t) ; avoiding ".class" and tokens after it

     ;; Keyword  (continued)
     ;; -------
     ("\\<\\(abstract\\|final\\|private\\|protected\\|public\\|static\\|transient\\|volatile\\)\\>"
      . 'java-deprecated-subdued)
     ("\\b\\(synchronized\\) *[^(]" 1 'java-deprecated-subdued) ; see also synchronized (as statement) below
     ("^package " . 'java-deprecated-subdued)
     ("^ *\\(import .*\\);" 1 'java-deprecated-subdued t)

     ;; Boilerplate
     ;; -----------
     ("\\bassert\\b.+?;" 0 'font-lock-comment-face t)
     ("[lL]ogger.+\\(?:log\\|severe\\|warning\\|info\\|config\\|fine\\|finer\\|finest\\)(.+?;" 0
      'font-lock-comment-face t)
   ; ("\\bif[(] rep > 0 [)] report[(].+?[)];" 0 'font-lock-comment-face t) ; for votorola.s.gwt.mediawiki.DifferenceShadowsV

     ;; Punctuation
     ;; -----------
     (" ->" . 'java-deprecated-subdued) ; lambda symbol

     ;; Synchronized statement  (statement only, not as qualifier)
     ;; ----------------------
     ("\\b\\(synchronized\\) *(" 1 'font-lock-keyword-face)

     ;; System exit call
     ;; ----------------
     ("\\b\\(System\\)\\.\\(exit\\) *(" (1 'font-lock-keyword-face)(2 'font-lock-keyword-face)))))



(defface java-deprecated-pragma
  `((default . (:inherit font-lock-builtin-face)))
  "The face for pragmas in code documentation."
  :group 'faces)



(defface java-deprecated-pragma-param
  `((default . (:inherit java-deprecated-pragma)))
  "The face for pragma parameters."
  :group 'faces)



(defface java-deprecated-subdued
  `((default . (:inherit init/subdued)))
  "The face for noisy symbolic clutter that needs subduing."
  :group 'faces)



(provide 'java-deprecated-mode)



;; This file has been dedicated by its author(s) to the public domain.  To the extent possible
;; by law, the author(s) have waived all of their copyright and related or neighbouring rights to
;; this file under the terms of CC0 1.0.  http://creativecommons.org/publicdomain/zero/1.0/
;; The author(s) are:
;;
;;     Michael Allan, mike@reluk.ca, http://reluk.ca/
;;
;; Other authors who make further, substantial contributions to this file, and who wish to dedicate
;; their contributions to the public domain, should append their names to the list above.