|
From: Alan M. <ac...@mu...> - 2017-08-26 12:52:43
|
Hello, Ludwig,
I think I now understand what's happening with your example file, and I
enclose a patch which should fix the CC Mode problem. (Note: the patch
should be applied to the up to date version of CC Mode, not the version
as it was back in February).
The problem in CC Mode was that declarations with "struct" (etc.) were
being fontified twice, with two different pieces of CC Mode. The second
of these pieces was a much older, simpler piece of code, whose only
essential difference to the first piece was being able to fontify the "Y"
as a type in
<class X = Y>
. I have now amended the first piece to be able to do that. The second
piece I have removed. As a bonus, fontification is now 3.9% faster. :-)
The problem with the second fontification was that it put
"NotHighlighted" back into c-found-types after it had been removed by
"NotHighlighted2" (as explained in a previous email). Thus anything
triggering a redisplay (such as your 2. below) caused "NotHighlighted" to
become fontified.
On Sat, Apr 15, 2017 at 09:39:40 +0100, Lud wrote:
> Hello Allan,
> Thank you for your patch.
> > Please apply the patch below. I think it works on the test code in your
> > original bug report, but would you please try it out on your normal code,
> > and either let me know that it works, or tell me what still needs fixing.
> > This patch attempts to remove the "ambiguity" of font locking which
> > happened with deleting and reinserting the ">", and such like.
> On my code, the result is better, but I still have some not consistent
> behaviors. I tested with the below snippet of code, and the master
> branch the git repo of emacs:
> #include <vector>
> struct NotHighlighted{ int a; };
> namespace abc { struct NotHighlighted2{ int b; }; }
> // $ g++ test.cpp # should compile correctly
> int main () {
> std::vector<NotHighlighted> foo;
> std::vector<abc::NotHighlighted2> bar;
> }
> After my tests, here are my results:
> 1. Open the file with the snippet, types in both vector are not
> higlighted. I expected to be higlighted?
As explained last time, "NotHighlighted"'s entry in "c-found-types" was
erased when NotHighlighted2 was entered, since it is all the characters except the last of
that identifier. (The thinking is that it will have been typed in one
character at a time, and we don't want all the heads to have entries in
"c-found-types", so a new entry "foobar" checks for and deletes any
"fooba".)
> 2. Remove and put back '>' of 'std::vector<NotHighlighted> foo' makes
> the higlight on for the type.
This no longer happens, since the second fontification of
"NotHighlighted" no longer happens (see above).
> 3. Add a '2' at the end of the type 'std::vector<NotHighlighted> foo',
> highlight is still on. I expected to be off?
This should happen. "NotHighlighted2" has a correct entry in
"c-found-types" so any other occurrence of it is fontified as a type.
> 4. Replace the '2' by a '3' for 'std::vector<NotHighlighted> foo',
> highlight of the type is off. Looks good to me.
This should also happen, since there is no c-found-types entry for
"NotHighlighted3".
> 5. Remove and put back '>' of 'std::vector<abc::NotHighlighted> bar',
> the highlight of the type is still off. I expect to be on with namespaces?
Unfortunately not. CC Mode isn't (?yet) intelligent enough to create a
c-found-types entry for "abc::NotHighlighted" out of the namespace
declaration and the contents of the braces.
> Let me know your thoughts about these points.
Here is the patch. Would you please apply it to an up to date CC Mode
and try it out. Please let me know how well it works. Thanks!
diff -r dbf1a31b3959 cc-fonts.el
--- a/cc-fonts.el Tue Aug 22 16:38:44 2017 +0000
+++ b/cc-fonts.el Sat Aug 26 12:46:09 2017 +0000
@@ -1026,7 +1026,8 @@
(goto-char pos)))))
nil)
-(defun c-font-lock-declarators (limit list types not-top)
+(defun c-font-lock-declarators (limit list types not-top
+ &optional template-class)
;; Assuming the point is at the start of a declarator in a declaration,
;; fontify the identifier it declares. (If TYPES is set, it does this via
;; the macro `c-fontify-types-and-refs'.)
@@ -1040,6 +1041,11 @@
;; non-nil, we are not at the top-level ("top-level" includes being directly
;; inside a class or namespace, etc.).
;;
+ ;; TEMPLATE-CLASS is non-nil when the declaration is in template delimiters
+ ;; and was introduced by, e.g. "typename" or "class", such that if there is
+ ;; a default (introduced by "="), it will be fontified as a type.
+ ;; E.g. "<class X = Y>".
+ ;;
;; Nil is always returned. The function leaves point at the delimiter after
;; the last declarator it processes.
;;
@@ -1112,6 +1118,13 @@
(goto-char next-pos)
(setq pos nil) ; So as to terminate the enclosing `while' form.
+ (if (and template-class
+ (eq got-init ?=) ; C++ "<class X = Y>"?
+ (c-forward-token-2 1 nil limit) ; Over "="
+ (let ((c-promote-possible-types t))
+ (c-forward-type t))) ; Over "Y"
+ (setq list nil)) ; Shouldn't be needed. We can't have a list, here.
+
(when list
;; Jump past any initializer or function prototype to see if
;; there's a ',' to continue at.
@@ -1340,8 +1353,12 @@
(c-backward-syntactic-ws)
(and (c-simple-skip-symbol-backward)
(looking-at c-paren-stmt-key))))
- t)))
-
+ t))
+ (template-class (and (eq context '<>)
+ (save-excursion
+ (goto-char match-pos)
+ (c-forward-syntactic-ws)
+ (looking-at c-template-typename-key)))))
;; Fix the `c-decl-id-start' or `c-decl-type-start' property
;; before the first declarator if it's a list.
;; `c-font-lock-declarators' handles the rest.
@@ -1353,10 +1370,9 @@
(if (cadr decl-or-cast)
'c-decl-type-start
'c-decl-id-start)))))
-
(c-font-lock-declarators
(min limit (point-max)) decl-list
- (cadr decl-or-cast) (not toplev)))
+ (cadr decl-or-cast) (not toplev) template-class))
;; A declaration has been successfully identified, so do all the
;; fontification of types and refs that've been recorded.
@@ -1650,7 +1666,8 @@
;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; fontification".
- (let ((decl-search-lim (c-determine-limit 1000))
+ (let ((here (point))
+ (decl-search-lim (c-determine-limit 1000))
paren-state encl-pos token-end context decl-or-cast
start-pos top-level c-restricted-<>-arglists
c-recognize-knr-p) ; Strictly speaking, bogus, but it
@@ -1667,26 +1684,27 @@
(when (or (bobp)
(memq (char-before) '(?\; ?{ ?})))
(setq token-end (point))
- (c-forward-syntactic-ws)
- ;; We're now putatively at the declaration.
- (setq start-pos (point))
- (setq paren-state (c-parse-state))
- ;; At top level or inside a "{"?
- (if (or (not (setq encl-pos
- (c-most-enclosing-brace paren-state)))
- (eq (char-after encl-pos) ?\{))
- (progn
- (setq top-level (c-at-toplevel-p))
- (let ((got-context (c-get-fontification-context
- token-end nil top-level)))
- (setq context (car got-context)
- c-restricted-<>-arglists (cdr got-context)))
- (setq decl-or-cast
- (c-forward-decl-or-cast-1 token-end context nil))
- (when (consp decl-or-cast)
- (goto-char start-pos)
- (c-font-lock-single-decl limit decl-or-cast token-end
- context top-level)))))))
+ (c-forward-syntactic-ws here)
+ (when (< (point) here)
+ ;; We're now putatively at the declaration.
+ (setq start-pos (point))
+ (setq paren-state (c-parse-state))
+ ;; At top level or inside a "{"?
+ (if (or (not (setq encl-pos
+ (c-most-enclosing-brace paren-state)))
+ (eq (char-after encl-pos) ?\{))
+ (progn
+ (setq top-level (c-at-toplevel-p))
+ (let ((got-context (c-get-fontification-context
+ token-end nil top-level)))
+ (setq context (car got-context)
+ c-restricted-<>-arglists (cdr got-context)))
+ (setq decl-or-cast
+ (c-forward-decl-or-cast-1 token-end context nil))
+ (when (consp decl-or-cast)
+ (goto-char start-pos)
+ (c-font-lock-single-decl limit decl-or-cast token-end
+ context top-level))))))))
nil))
(defun c-font-lock-enclosing-decls (limit)
@@ -1998,85 +2016,6 @@
2 font-lock-type-face)
`(,(concat "\\<\\(" re "\\)\\>")
1 'font-lock-type-face)))
-
- ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct").
- ,@(when (c-lang-const c-type-prefix-kwds)
- `((,(byte-compile
- `(lambda (limit)
- (c-fontify-types-and-refs
- ((c-promote-possible-types t)
- ;; The font-lock package in Emacs is known to clobber
- ;; `parse-sexp-lookup-properties' (when it exists).
- (parse-sexp-lookup-properties
- (cc-eval-when-compile
- (boundp 'parse-sexp-lookup-properties))))
- (save-restriction
- ;; Narrow to avoid going past the limit in
- ;; `c-forward-type'.
- (narrow-to-region (point) limit)
- (while (re-search-forward
- ,(concat "\\<\\("
- (c-make-keywords-re nil
- (c-lang-const c-type-prefix-kwds))
- "\\)\\>")
- limit t)
- (unless (c-skip-comments-and-strings limit)
- (c-forward-syntactic-ws)
- ;; Handle prefix declaration specifiers.
- (while
- (or
- (when (or (looking-at c-prefix-spec-kwds-re)
- (and (c-major-mode-is 'java-mode)
- (looking-at "@[A-Za-z0-9]+")))
- (c-forward-keyword-clause 1)
- t)
- (when (and c-opt-cpp-prefix
- (looking-at
- c-noise-macro-with-parens-name-re))
- (c-forward-noise-clause)
- t)))
- ,(if (c-major-mode-is 'c++-mode)
- `(when (and (c-forward-type)
- (eq (char-after) ?=))
- ;; In C++ we additionally check for a "class
- ;; X = Y" construct which is used in
- ;; templates, to fontify Y as a type.
- (forward-char)
- (c-forward-syntactic-ws)
- (c-forward-type))
- `(c-forward-type))
- )))))))))
-
- ;; Fontify symbols after closing braces as declaration
- ;; identifiers under the assumption that they are part of
- ;; declarations like "class Foo { ... } foo;". It's too
- ;; expensive to check this accurately by skipping past the
- ;; brace block, so we use the heuristic that it's such a
- ;; declaration if the first identifier is on the same line as
- ;; the closing brace. `c-font-lock-declarations' will later
- ;; override it if it turns out to be an new declaration, but
- ;; it will be wrong if it's an expression (see the test
- ;; decls-8.cc).
-;; ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
-;; `((,(c-make-font-lock-search-function
-;; (concat "}"
-;; (c-lang-const c-single-line-syntactic-ws)
-;; "\\(" ; 1 + c-single-line-syntactic-ws-depth
-;; (c-lang-const c-type-decl-prefix-key)
-;; "\\|"
-;; (c-lang-const c-symbol-key)
-;; "\\)")
-;; `((c-font-lock-declarators limit t nil) ; That `nil' says use `font-lock-variable-name-face';
-;; ; `t' would mean `font-lock-function-name-face'.
-;; (progn
-;; (c-put-char-property (match-beginning 0) 'c-type
-;; 'c-decl-id-start)
-;; ; 'c-decl-type-start)
-;; (goto-char (match-beginning
-;; ,(1+ (c-lang-const
-;; c-single-line-syntactic-ws-depth)))))
-;; (goto-char (match-end 0)))))))
-
;; Fontify the type in C++ "new" expressions.
,@(when (c-major-mode-is 'c++-mode)
;; This pattern is a probably a "(MATCHER . ANCHORED-HIGHLIGHTER)"
diff -r dbf1a31b3959 cc-langs.el
--- a/cc-langs.el Tue Aug 22 16:38:44 2017 +0000
+++ b/cc-langs.el Sat Aug 26 12:46:09 2017 +0000
@@ -1857,6 +1857,17 @@
t (c-make-keywords-re t (c-lang-const c-typeof-kwds)))
(c-lang-defvar c-typeof-key (c-lang-const c-typeof-key))
+(c-lang-defconst c-template-typename-kwds
+ "Keywords which, within a template declaration, can introduce a
+declaration with a type as a default value. This is used only in
+C++ Mode, e.g. \"<typename X = Y>\"."
+ t nil
+ c++ '("class" "typename"))
+
+(c-lang-defconst c-template-typename-key
+ t (c-make-keywords-re t (c-lang-const c-template-typename-kwds)))
+(c-lang-defvar c-template-typename-key (c-lang-const c-template-typename-key))
+
(c-lang-defconst c-type-prefix-kwds
"Keywords where the following name - if any - is a type name, and
where the keyword together with the symbol works as a type in
> King regards
> Ludwig
--
Alan Mackenzie (Nuremberg, Germany).
|