Commit 1379f2c5 authored by Alan Mackenzie's avatar Alan Mackenzie
Browse files

Fix fontification of labels, and other things with ":".

* progmodes/cc-engine.el (c-forward-label): The function now
returns 'goto-target, 'qt-2kwds-colon, 'qt-1kwd-colon, as well as
the former t.

* progmodes/cc-fonts.el (c-font-lock-declarations): Interpret the
new return code from c-forward-label, fontifying tokens properly.
Add some general comments throughout the file.
parent 1bf1feb5
......@@ -5371,7 +5371,7 @@ comment at the start of cc-engine.el for more info."
;; True if there's a prefix match outside the outermost
;; paren pair that surrounds the declarator.
got-prefix-before-parens
y ;; True if there's a suffix match outside the outermost
;; True if there's a suffix match outside the outermost
;; paren pair that surrounds the declarator. The value is
;; the position of the first suffix match.
got-suffix-after-parens
......@@ -5877,19 +5877,23 @@ y ;; True if there's a suffix match outside the outermost
(defun c-forward-label (&optional assume-markup preceding-token-end limit)
;; Assuming that point is at the beginning of a token, check if it starts a
;; label and if so move over it and return t, otherwise don't move and
;; return nil. "Label" here means "most things with a colon".
;; label and if so move over it and return non-nil (t in default situations,
;; specific symbols (see below) for interesting situations), otherwise don't
;; move and return nil. "Label" here means "most things with a colon".
;;
;; More precisely, a "label" is regarded as one of:
;; (i) a goto target like "foo:";
;; (ii) A case label - either the entire construct "case FOO:" or just the
;; bare "case", should the colon be missing;
;; (iii) a keyword which needs a colon, like "default:" or "private:";
;; (i) a goto target like "foo:" - returns the symbol `goto-target';
;; (ii) A case label - either the entire construct "case FOO:", or just the
;; bare "case", should the colon be missing. We return t;
;; (iii) a keyword which needs a colon, like "default:" or "private:"; We
;; return t;
;; (iv) One of QT's "extended" C++ variants of
;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:".
;; Returns the symbol `qt-2kwds-colon'.
;; (v) QT's construct "signals:". Returns the symbol `qt-1kwd-colon'.
;; (v) One of the keywords matched by `c-opt-extra-label-key' (without any
;; colon). Currently (2006-03), this applies only to Objective C's
;; keywords "@private", "@protected", and "@public".
;; keywords "@private", "@protected", and "@public". Returns t.
;;
;; One of the things which will NOT be recognised as a label is a bit-field
;; element of a struct, something like "int foo:5".
......@@ -5918,8 +5922,10 @@ y ;; True if there's a suffix match outside the outermost
;; This function might do hidden buffer changes.
(let ((start (point))
label-end
qt-symbol-idx
macro-start) ; if we're in one.
macro-start ; if we're in one.
label-type)
(cond
;; "case" or "default" (Doesn't apply to AWK).
((looking-at c-label-kwds-regexp)
......@@ -5932,25 +5938,26 @@ y ;; True if there's a suffix match outside the outermost
;; Find the label end.
(goto-char kwd-end)
(if (and (c-syntactic-re-search-forward
;; Stop on chars that aren't allowed in expressions,
;; and on operator chars that would be meaningless
;; there. FIXME: This doesn't cope with ?: operators.
"[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
limit t t nil 1)
(match-beginning 2))
(progn
(goto-char (match-beginning 2)) ; just after the :
(c-put-c-type-property (1- (point)) 'c-decl-end)
t)
;; It's an unfinished label. We consider the keyword enough
;; to recognize it as a label, so that it gets fontified.
;; Leave the point at the end of it, but don't put any
;; `c-decl-end' marker.
(goto-char kwd-end)
t)))
(setq label-type
(if (and (c-syntactic-re-search-forward
;; Stop on chars that aren't allowed in expressions,
;; and on operator chars that would be meaningless
;; there. FIXME: This doesn't cope with ?: operators.
"[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)"
limit t t nil 1)
(match-beginning 2))
(progn ; there's a proper :
(goto-char (match-beginning 2)) ; just after the :
(c-put-c-type-property (1- (point)) 'c-decl-end)
t)
;; It's an unfinished label. We consider the keyword enough
;; to recognize it as a label, so that it gets fontified.
;; Leave the point at the end of it, but don't put any
;; `c-decl-end' marker.
(goto-char kwd-end)
t))))
;; @private, @protected, @public, in Objective C, or similar.
((and c-opt-extra-label-key
......@@ -5962,7 +5969,7 @@ y ;; True if there's a suffix match outside the outermost
(when c-record-type-identifiers
(c-record-ref-id (cons (match-beginning 1) (point))))
(c-put-c-type-property (1- (point)) 'c-decl-end)
t)
(setq label-type t))
;; All other cases of labels.
((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t.
......@@ -6038,26 +6045,49 @@ y ;; True if there's a suffix match outside the outermost
(c-forward-syntactic-ws)
(c-forward-label nil pte start))))))))))
;; Point is still at the beginning of the possible label construct.
;;
;; Check that the next nonsymbol token is ":", or that we're in one
;; of QT's "slots" declarations. Allow '(' for the sake of macro
;; arguments. FIXME: Should build this regexp from the language
;; constants.
(when (c-syntactic-re-search-forward
"[ \t[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
(backward-char)
(setq qt-symbol-idx
(and (c-major-mode-is 'c++-mode)
(string-match
"\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
(buffer-substring start (point)))))
(c-forward-syntactic-ws limit)
(when (or (looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
(and qt-symbol-idx
(search-forward-regexp "\\=slots\\>" limit t)
(progn (c-forward-syntactic-ws limit)
(looking-at ":\\([^:]\\|\\'\\)")))) ; A single colon
(forward-char) ; to after the colon.
t)))
(cond
;; public: protected: private:
((and
(c-major-mode-is 'c++-mode)
(search-forward-regexp
"\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t)
(progn (backward-char)
(c-forward-syntactic-ws limit)
(looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon.
(forward-char)
(setq label-type t))
;; QT double keyword like "protected slots:" or goto target.
((progn (goto-char start) nil))
((when (c-syntactic-re-search-forward
"[ \t\n[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB
(backward-char)
(setq label-end (point))
(setq qt-symbol-idx
(and (c-major-mode-is 'c++-mode)
(string-match
"\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>"
(buffer-substring start (point)))))
(c-forward-syntactic-ws limit)
(cond
((looking-at ":\\([^:]\\|\\'\\)") ; A single colon.
(forward-char)
(setq label-type
(if (string= "signals" ; Special QT macro
(buffer-substring-no-properties start label-end))
'qt-1kwd-colon
'goto-target)))
((and qt-symbol-idx
(search-forward-regexp "\\=slots\\>" limit t)
(progn (c-forward-syntactic-ws limit)
(looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon
(forward-char)
(setq label-type 'qt-2kwds-colon)))))))
(save-restriction
(narrow-to-region start (point))
......@@ -6068,6 +6098,7 @@ y ;; True if there's a suffix match outside the outermost
(while (progn
(when (looking-at c-nonlabel-token-key)
(goto-char start)
(setq label-type nil)
(throw 'check-label nil))
(and (c-safe (c-forward-sexp)
(c-forward-syntactic-ws)
......@@ -6087,12 +6118,12 @@ y ;; True if there's a suffix match outside the outermost
(c-put-c-type-property (1- (point-max)) 'c-decl-end)
(goto-char (point-max))
t)))
)))
(t
;; Not a label.
(goto-char start)
nil))))
(goto-char start)))
label-type))
(defun c-forward-objc-directive ()
;; Assuming the point is at the beginning of a token, try to move
......
......@@ -704,8 +704,13 @@ casts and declarations are fontified. Used on level 2 and higher."
))
(defun c-font-lock-complex-decl-prepare (limit)
;; This function will be called from font-lock for a region bounded by POINT
;; and LIMIT, as though it were to identify a keyword for
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification".
;;
;; Called before any of the matchers in `c-complex-decl-matchers'.
;; Nil is always returned.
;;
;; This function does hidden buffer changes.
......@@ -742,10 +747,15 @@ casts and declarations are fontified. Used on level 2 and higher."
nil)
(defun c-font-lock-<>-arglists (limit)
;; This function will be called from font-lock for a region bounded by POINT
;; and LIMIT, as though it were to identify a keyword for
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification".
;;
;; Fontify types and references in names containing angle bracket
;; arglists from the point to LIMIT. Note that
;; `c-font-lock-declarations' already has handled many of them. Nil
;; is always returned.
;; `c-font-lock-declarations' already has handled many of them.
;;
;; This function might do hidden buffer changes.
......@@ -971,9 +981,14 @@ casts and declarations are fontified. Used on level 2 and higher."
font-lock-keyword-face))
(defun c-font-lock-declarations (limit)
;; This function will be called from font-lock for a region bounded by POINT
;; and LIMIT, as though it were to identify a keyword for
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification".
;;
;; Fontify all the declarations, casts and labels from the point to LIMIT.
;; Assumes that strings and comments have been fontified already. Nil is
;; always returned.
;; Assumes that strings and comments have been fontified already.
;;
;; This function might do hidden buffer changes.
......@@ -1009,6 +1024,7 @@ casts and declarations are fontified. Used on level 2 and higher."
;; `c-forward-decl-or-cast-1' and `c-forward-label' for
;; later fontification.
(c-record-type-identifiers t)
label-type
c-record-ref-identifiers
;; Make `c-forward-type' calls mark up template arglists if
;; it finds any. That's necessary so that we later will
......@@ -1174,39 +1190,31 @@ casts and declarations are fontified. Used on level 2 and higher."
(c-fontify-recorded-types-and-refs)
nil))
;; It was a false alarm.
;; It was a false alarm. Check if we're in a label (or other
;; construct with `:' except bitfield) instead.
(goto-char start-pos)
;; The below code attempts to fontify the case constants in
;; c-label-face-name, but it cannot catch every case [sic].
;; And do we want to fontify case constants anyway?
(c-forward-label t match-pos nil)
;;; (when (c-forward-label t match-pos nil)
;;; ;; Can't use `c-fontify-types-and-refs' here since we
;;; ;; should use the label face.
;;; (save-excursion
;;; (while c-record-ref-identifiers
;;; (let ((elem (car c-record-ref-identifiers))
;;; c-record-type-identifiers)
;;; (goto-char (cdr elem))
;;; ;; Find the end of any label.
;;; (while (and (re-search-forward "\\sw\\|:" nil t)
;;; (progn (backward-char 1) t)
;;; (or (re-search-forward
;;; "\\=0[Xx][0-9A-Fa-f]+\\|\\([0-9]+\\)" nil t)
;;; (c-forward-name)))
;;; (c-backward-syntactic-ws)
;;; (let ((end (point)))
;;; ;; Now find the start of the bit we regard as the label.
;;; (when (and (c-simple-skip-symbol-backward)
;;; (not (c-get-char-property (point) 'face)))
;;; (c-put-font-lock-face (point) end c-label-face-name))
;;; (goto-char end))))
;;; (setq c-record-ref-identifiers (cdr c-record-ref-identifiers))))
;;; ;; `c-forward-label' probably has added a `c-decl-end'
;;; ;; marker, so return t to `c-find-decl-spots' to signal
;;; ;; that.
;;; t)
)))
(when (setq label-type (c-forward-label t match-pos nil))
;; Can't use `c-fontify-types-and-refs' here since we
;; use the label face at times.
(cond ((eq label-type 'goto-target)
(c-put-font-lock-face (caar c-record-ref-identifiers)
(cdar c-record-ref-identifiers)
c-label-face-name))
((eq label-type 'qt-1kwd-colon)
(c-put-font-lock-face (caar c-record-ref-identifiers)
(cdar c-record-ref-identifiers)
'font-lock-keyword-face))
((eq label-type 'qt-2kwds-colon)
(mapc
(lambda (kwd)
(c-put-font-lock-face (car kwd) (cdr kwd)
'font-lock-keyword-face))
c-record-ref-identifiers)))
(setq c-record-ref-identifiers nil)
;; `c-forward-label' has probably added a `c-decl-end'
;; marker, so return t to `c-find-decl-spots' to signal
;; that.
t))))
nil)))
......@@ -1285,6 +1293,14 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
"Complex font lock matchers for types and declarations. Used on level
3 and higher."
;; Note: This code in this form dumps a number of funtions into the
;; resulting constant, `c-matchers-3'. At run time, font lock will call
;; each of them as a "FUNCTION" (see Elisp page "Search-based
;; Fontification"). The font lock region is delimited by POINT and the
;; single parameter, LIMIT. Each of these functions returns NIL (thus
;; inhibiting spurious font-lock-keyword-face highlighting and another
;; call).
t `(;; Initialize some things before the search functions below.
c-font-lock-complex-decl-prepare
......@@ -1397,6 +1413,8 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
;; Fontify the type in C++ "new" expressions.
,@(when (c-major-mode-is 'c++-mode)
;; This pattern is a probably a "(MATCHER . ANCHORED-HIGHLIGHTER)"
;; (see Elisp page "Search-based Fontification").
`(("\\<new\\>"
(c-font-lock-c++-new))))
))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment