|
From: Lud <lu...@lu...> - 2017-09-03 14:46:19
|
Hello Alan,
Thank you for getting back on this issue, and congratulation for the
fontification performance improvement!
> 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).
I will have a look at the patch. Is it fine if I apply the patch on the
HEAD of Emacs master branch?
Lud
On 08/26/2017 01:49 PM, Alan Mackenzie wrote:
> 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
>
|