emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 374f14f: CC Mode: Fontify "found types" which are recognized afte


From: Alan Mackenzie
Subject: master 374f14f: CC Mode: Fontify "found types" which are recognized after being first scanned
Date: Sun, 24 Oct 2021 16:01:09 -0400 (EDT)

branch: master
commit 374f14fb9936d2b8fb30a123457ff4b12160f5f3
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    CC Mode: Fontify "found types" which are recognized after being first 
scanned
    
    This aims to fix the scenario where on jit-lock's first scan of a type, it 
is
    not recognized as such, and only later does this happen.  The fontification 
of
    such found types is now done by background scanning in short time slices
    immediately after initialising the mode.
    
    * lisp/progmodes/cc-engine.el (c-add-type-1): New function.
    (c-add-type): Extract c-add-type-1 from it, and reformulate the mechanism 
for
    protecting c-found-types from excessive partial identifiers.
    
    * lisp/progmodes/cc-fonts.el (c-font-lock-complex-decl-prepare): Remove the
    code which cleared c-found-types on fontification at BOB.
    (c-find-types-background): New function, based on c-font-lock-declarations).
    (c-type-finder-timer-func): New function.
    (c-re-redisplay-timer): New variable.
    (c-force-redisplay, c-fontify-new-found-type): New functions.
    
    * lisp/progmodes/cc-mode.el (c-type-finder-timer, c-inhibit-type-finder): 
New
    variables.
    (c-leave-cc-mode-mode): Nullify c-post-command-hook, c-post-gc-hook, and
    c-type-finder-timer when the last CC Mode buffer of a session is killed.
    (c-type-finder-pos): New variable.
    (c-basic-common-init): Initialize/Install c-post-command, 
c-c-type-finder-pos,
    c-type-finder-timer, and c-post-gc-hook.
    (c-new-id-start, c-new-id-end, c-new-id-is-type): New variables.
    (c-update-new-id): New function.
    (c-post-command): New post command hook function, used for checking moving
    away from partially typed identifiers, and making them full identifiers.
    (c-post-gc-hook): New hook to prevent CC Mode activity immediately following
    GC, thus allowing keyboard/mouse input to be registered.
    (c-before-change): Add code to clear c-found-types on a buffer change at 
BOB.
    (c-after-change): Call c-update-new-id to keep track of partially typed
    identifiers.
    
    * doc/misc/cc-mode.texi (Found Types): New @section in the @Chapter Font
    Locking.
    
    * lisp/progmodes/cc-vars.el (c-type-finder-time-slot)
    (c-type-finder-repeat-time, c-type-finder-chunk-size): New customizable
    options.
---
 doc/misc/cc-mode.texi       |  56 +++++++++++
 lisp/progmodes/cc-engine.el |  36 +++++---
 lisp/progmodes/cc-fonts.el  | 220 ++++++++++++++++++++++++++++++++++++++++++--
 lisp/progmodes/cc-mode.el   |  95 ++++++++++++++++++-
 lisp/progmodes/cc-vars.el   |  33 +++++++
 5 files changed, 418 insertions(+), 22 deletions(-)

diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 98ded68..c255d98 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -283,6 +283,8 @@ Font Locking
 * Font Locking Preliminaries::
 * Faces::
 * Doc Comments::
+* Wrong Comment Style::
+* Found Types::
 * Misc Font Locking::
 * AWK Mode Font Locking::
 
@@ -2162,6 +2164,60 @@ which aren't of the default style will be fontified with
 @end defvar
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@node    Found Types
+@comment  node-name,  next,  previous,  up
+@section ``Found Type'' handling.
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+In most languages handled by CC Mode, @dfn{found types} are recognized
+as types by their context in the source code.  These contrast with
+types which are basic to a language or are declared as types (e.g. by
+@code{typedef} in C).
+
+In earlier versions of @ccmode{}, when @code{jit-lock-mode} was
+enabled in Emacs (which it is by default), found types would
+frequently fail to get fontified properly.  This happened when the
+fontification functions scanned a use of the found type before
+scanning the code which caused it to be recognized.
+
+From @ccmode{} version 5.36, a timer mechanism scans the entire buffer
+for found types in the seconds immediately after starting the major
+mode.  When a found type gets recognized, all its occurrences in the
+buffer get marked for (re)fontification.  This scanning happens in
+short time slices interleaved with other processing, such as keyboard
+handling, so that the responsiveness of Emacs should be barely
+affected.  This mechanism can be disabled (see below).  It is only
+active when @code{jit-lock-mode} is also active.
+
+@defvar c-type-finder-time-slot
+@vindex type-finder-time-slot (c-)
+The approximate time in seconds that CC Mode spends in scanning source
+code before relinquishing control to other Emacs activities.  The
+default value is 0.05.  To disable the scanning mechanism, set this
+variable to @code{nil}.
+@end defvar
+
+@defvar c-type-finder-repeat-time
+@vindex type-finder-repeat-time (c-)
+The approximate frequency (in seconds) with which the scanning
+mechanism is triggered.  This time must be greater than
+@code{c-type-finder-time-slot}.  Its default value is 0.1.  If a less
+powerful machine becomes sluggish due to the scanning, increase the
+value of @code{c-type-finder-repeat-time} to compensate.
+@end defvar
+
+@defvar c-type-finder-chunk-size
+@vindex type-finder-chunk-size (c-)
+The approximate size (in characters) of the buffer chunk processed as
+a unit before the scanning mechanism checks whether
+@code{c-type-finder-time-slot} seconds have passed.  The default value
+is 1000.  A too small value here will cause inefficiencies due to the
+initialization which happens for each chunk, whereas a too large value
+will cause the processing to consume an excessive proportion of the
+@code{c-type-finder-repeat-time}.
+@end defvar
+
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @node    Misc Font Locking
 @comment  node-name,  next,  previous,  up
 @section Miscellaneous Font Locking
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index c42c957..ace6b1b 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -165,6 +165,9 @@
 (defvar c-doc-line-join-end-ch)
 (defvar c-syntactic-context)
 (defvar c-syntactic-element)
+(defvar c-new-id-start)
+(defvar c-new-id-end)
+(defvar c-new-id-is-type)
 (cc-bytecomp-defvar c-min-syn-tab-mkr)
 (cc-bytecomp-defvar c-max-syn-tab-mkr)
 (cc-bytecomp-defun c-clear-syn-tab)
@@ -6813,21 +6816,32 @@ comment at the start of cc-engine.el for more info."
   (setq c-found-types
        (make-hash-table :test #'equal :weakness nil)))
 
-(defun c-add-type (from to)
-  ;; Add the given region as a type in `c-found-types'.  If the region
-  ;; doesn't match an existing type but there is a type which is equal
-  ;; to the given one except that the last character is missing, then
-  ;; the shorter type is removed.  That's done to avoid adding all
-  ;; prefixes of a type as it's being entered and font locked.  This
-  ;; doesn't cover cases like when characters are removed from a type
-  ;; or added in the middle.  We'd need the position of point when the
-  ;; font locking is invoked to solve this well.
+(defun c-add-type-1 (from to)
+  ;; Add the given region as a type in `c-found-types'.  Prepare occurrences
+  ;; of this new type for fontification throughout the buffer.
   ;;
   ;; This function might do hidden buffer changes.
   (let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
     (unless (gethash type c-found-types)
-      (remhash (substring type 0 -1) c-found-types)
-      (puthash type t c-found-types))))
+      (puthash type t c-found-types)
+      (when (and (eq (string-match c-symbol-key type) 0)
+                (eq (match-end 0) (length type)))
+       (c-fontify-new-found-type type)))))
+
+(defun c-add-type (from to)
+  ;; Add the given region as a type in `c-found-types'.  Also perform the
+  ;; actions of `c-add-type-1'.  If the region is or overlaps an identifier
+  ;; which might be being typed in, don't record it.  This is tested by
+  ;; checking `c-new-id-start' and `c-new-id-end'.  That's done to avoid
+  ;; adding all prefixes of a type as it's being entered and font locked.
+  ;; This is a bit rough and ready, but now covers adding characters into the
+  ;; middle of an identifer.
+  ;;
+  ;; This function might do hidden buffer changes.
+  (if (and c-new-id-start c-new-id-end
+          (<= from c-new-id-end) (>= to c-new-id-start))
+      (setq c-new-id-is-type t)
+    (c-add-type-1 from to)))
 
 (defun c-unfind-type (name)
   ;; Remove the "NAME" from c-found-types, if present.
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index bc0ae6c..9355409 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -93,10 +93,14 @@
 (cc-bytecomp-defvar c-preprocessor-face-name)
 (cc-bytecomp-defvar c-reference-face-name)
 (cc-bytecomp-defvar c-block-comment-flag)
+(cc-bytecomp-defvar c-type-finder-pos)
+(cc-bytecomp-defvar c-inhibit-type-finder)
+(cc-bytecomp-defvar c-type-finder-timer)
 (cc-bytecomp-defun c-fontify-recorded-types-and-refs)
 (cc-bytecomp-defun c-font-lock-declarators)
 (cc-bytecomp-defun c-font-lock-objc-method)
 (cc-bytecomp-defun c-font-lock-invalid-string)
+(cc-bytecomp-defun c-before-context-fl-expand-region)
 
 
 ;; Note that font-lock in XEmacs doesn't expand face names as
@@ -919,13 +923,6 @@ casts and declarations are fontified.  Used on level 2 and 
higher."
   ;; This function does hidden buffer changes.
 
   ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit)
-
-  ;; Clear the list of found types if we start from the start of the
-  ;; buffer, to make it easier to get rid of misspelled types and
-  ;; variables that have gotten recognized as types in malformed code.
-  (when (bobp)
-    (c-clear-found-types))
-
   (c-skip-comments-and-strings limit)
   (when (< (point) limit)
 
@@ -1605,6 +1602,175 @@ casts and declarations are fontified.  Used on level 2 
and higher."
 
        nil))))
 
+(defun c-find-types-background (start limit)
+  ;; Find any "found types" between START and LIMIT.  Allow any such types to
+  ;; be entered into `c-found-types' by the action of `c-forward-name' or
+  ;; `c-forward-type' called from this function.  This process also causes
+  ;; occurrences of the type to be prepared for fontification throughout the
+  ;; buffer.
+  ;;
+  ;; Return POINT at the end of the function.  This should be at or after
+  ;; LIMIT, and not later than the next decl-spot after LIMIT.
+  ;;
+  ;; This function is called from the timer `c-type-finder-timer'.  It may do
+  ;; hidden buffer changes.
+  (save-excursion
+    (save-restriction
+      (widen)
+      (goto-char start)
+      ;; If we're in a (possibly large) literal, skip over it.
+      (let ((lit-bounds (nth 2 (c-full-pp-to-literal (point)))))
+       (if lit-bounds
+           (goto-char (cdr lit-bounds))))
+      (when (< (point) limit)
+       (let (;; o - 'decl if we're in an arglist containing declarations
+             ;;   (but if `c-recognize-paren-inits' is set it might also be
+             ;;   an initializer arglist);
+             ;; o - '<> if the arglist is of angle bracket type;
+             ;; o - 'arglist if it's some other arglist;
+             ;; o - nil, if not in an arglist at all.  This includes the
+             ;;   parenthesized condition which follows "if", "while", etc.
+             context
+             ;; A list of starting positions of possible type declarations, or 
of
+             ;; the typedef preceding one, if any.
+             last-cast-end
+             ;; The result from `c-forward-decl-or-cast-1'.
+             decl-or-cast
+             ;; The maximum of the end positions of all the checked type
+             ;; decl expressions in the successfully identified
+             ;; declarations.  The position might be either before or
+             ;; after the syntactic whitespace following the last token
+             ;; in the type decl expression.
+             (max-type-decl-end 0)
+             ;; Same as `max-type-decl-*', but used when we're before
+             ;; `token-pos'.
+             (max-type-decl-end-before-token 0)
+             )
+         (goto-char start)
+         (c-find-decl-spots
+          limit
+          c-decl-start-re
+          nil                          ; (eval c-maybe-decl-faces)
+
+          (lambda (match-pos inside-macro &optional toplev)
+            ;; Note to maintainers: don't use `limit' inside this lambda form;
+            ;; c-find-decl-spots sometimes narrows to less than `limit'.
+            (if (and c-macro-with-semi-re
+                     (looking-at c-macro-with-semi-re))
+                ;; Don't do anything more if we're looking at something that
+                ;; can't start a declaration.
+                t
+
+              ;; Set `context' and `c-restricted-<>-arglists'.  Look for
+              ;; "<" for the sake of C++-style template arglists.
+              ;; "Ignore "(" when it's part of a control flow construct
+              ;; (e.g. "for (").
+              (let ((got-context
+                     (c-get-fontification-context
+                      match-pos
+                      (< match-pos (if inside-macro
+                                       max-type-decl-end-before-token
+                                     max-type-decl-end))
+                      toplev)))
+                (setq context (car got-context)
+                      c-restricted-<>-arglists (cdr got-context)))
+
+              ;; In QT, "more" is an irritating keyword that expands to 
nothing.
+              ;; We skip over it to prevent recognition of "more slots: 
<symbol>"
+              ;; as a bitfield declaration.
+              (when (and (c-major-mode-is 'c++-mode)
+                         (looking-at
+                          (concat "\\(more\\)\\([^" c-symbol-chars 
"]\\|$\\)")))
+                (goto-char (match-end 1))
+                (c-forward-syntactic-ws))
+
+              ;; Now analyze the construct.  This analysis will cause
+              ;; `c-forward-name' and `c-forward-type' to call `c-add-type',
+              ;; triggering the desired recognition and fontification of
+              ;; these found types.
+              (when (not (eq context 'not-decl))
+                (setq decl-or-cast
+                      (c-forward-decl-or-cast-1
+                       match-pos context last-cast-end))
+
+                (cond
+                 ((eq decl-or-cast 'cast)
+                  ;; Save the position after the previous cast so we can feed
+                  ;; it to `c-forward-decl-or-cast-1' in the next round.  That
+                  ;; helps it discover cast chains like "(a) (b) c".
+                  (setq last-cast-end (point))
+                  nil)
+                 (decl-or-cast
+                  ;; We've found a declaration.
+
+                  ;; Set `max-type-decl-end' or 
`max-type-decl-end-before-token'
+                  ;; under the assumption that we're after the first type decl
+                  ;; expression in the declaration now.  That's not really 
true;
+                  ;; we could also be after a parenthesized initializer
+                  ;; expression in C++, but this is only used as a last resort
+                  ;; to slant ambiguous expression/declarations, and overall
+                  ;; it's worth the risk to occasionally fontify an expression
+                  ;; as a declaration in an initializer expression compared to
+                  ;; getting ambiguous things in normal function prototypes
+                  ;; fontified as expressions.
+                  (if inside-macro
+                      (when (> (point) max-type-decl-end-before-token)
+                        (setq max-type-decl-end-before-token (point)))
+                    (when (> (point) max-type-decl-end)
+                      (setq max-type-decl-end (point)))))
+                 (t t))))))))
+      (point))))
+
+(defun c-type-finder-timer-func ()
+  ;; A CC Mode idle timer function for finding "found types".  It triggers
+  ;; every `c-type-finder-repeat-time' seconds and processes buffer chunks of
+  ;; size around `c-type-finder-chunk-size' characters, and runs for (a little
+  ;; over) `c-type-finder-time-slot' seconds.  The types it finds are inserted
+  ;; into `c-found-types', and their occurrences throughout the buffer are
+  ;; prepared for fontification.
+  (when (and c-type-finder-time-slot
+            (boundp 'font-lock-support-mode)
+            (eq font-lock-support-mode 'jit-lock-mode))
+    (if c-inhibit-type-finder ; No processing immediately after a GC operation.
+       (setq c-inhibit-type-finder nil)
+      (let* ((stop-time (+ (float-time) c-type-finder-time-slot))
+            (buf-list (buffer-list)))
+       ;; One CC Mode buffer needing processing each time around this loop.
+       (while (and buf-list
+                   (< (float-time) stop-time))
+         ;; Cdr through BUF-LIST to find the next buffer needing processing.
+         (while (and buf-list
+                     (not (with-current-buffer (car buf-list) 
c-type-finder-pos)))
+           (setq buf-list (cdr buf-list)))
+         (when buf-list
+           (with-current-buffer (car buf-list)
+             ;; (message "%s" (current-buffer)) ; Useful diagnostic.
+             (save-restriction
+               (widen)
+               ;; Process one `c-type-finder-chunk-size' chunk each time
+               ;; around this loop.
+               (while (and c-type-finder-pos
+                           (< (float-time) stop-time))
+                 ;; Process one chunk per iteration.
+                 (save-match-data
+                   (c-save-buffer-state
+                       (case-fold-search
+                        (beg (marker-position c-type-finder-pos))
+                        (end (min (+ beg c-type-finder-chunk-size) 
(point-max)))
+                        (region (c-before-context-fl-expand-region beg end)))
+                     (setq beg (car region)
+                           end (cdr region))
+                     (setq beg (max (c-find-types-background beg end) end))
+                     (move-marker c-type-finder-pos
+                                  (if (save-excursion (goto-char beg) (eobp))
+                                      nil
+                                    beg))
+                     (when (not (marker-position c-type-finder-pos))
+                       (setq c-type-finder-pos nil))))))))))))
+  ;; Set the timer to run again.
+  (setq c-type-finder-timer
+       (run-at-time c-type-finder-repeat-time nil #'c-type-finder-timer-func)))
+
 (defun c-font-lock-enum-body (limit)
   ;; Fontify the identifiers of each enum we find by searching forward.
   ;;
@@ -2255,6 +2421,46 @@ higher."
     ;; defvar will install its default value later on.
     (makunbound def-var)))
 
+;; `c-re-redisplay-timer' is a timer which, when triggered, causes a
+;; redisplay.
+(defvar c-re-redisplay-timer nil)
+
+(defun c-force-redisplay (start end)
+  ;; Force redisplay immediately.  This assumes `font-lock-support-mode' is
+  ;; 'jit-lock-mode.  Set the variable `c-re-redisplay-timer' to nil.
+  (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
+  (setq c-re-redisplay-timer nil))
+
+(defun c-fontify-new-found-type (type)
+  ;; Cause the fontification of TYPE, a string, wherever it occurs in the
+  ;; buffer.  If TYPE is currently displayed in a window, cause redisplay to
+  ;; happen "instantaneously".  These actions are done only when jit-lock-mode
+  ;; is active.
+  (when (and (boundp 'font-lock-support-mode)
+            (eq font-lock-support-mode 'jit-lock-mode))
+    (c-save-buffer-state
+       ((window-boundaries
+         (mapcar (lambda (win)
+                   (cons (window-start win)
+                         (window-end win)))
+                 (get-buffer-window-list (current-buffer) 'no-mini t)))
+        (target-re (concat "\\_<" type "\\_>")))
+      (save-excursion
+       (save-restriction
+         (widen)
+         (goto-char (point-min))
+         (while (re-search-forward target-re nil t)
+           (put-text-property (match-beginning 0) (match-end 0)
+                              'fontified nil)
+           (dolist (win-boundary window-boundaries)
+             (when (and (< (match-beginning 0) (cdr win-boundary))
+                        (> (match-end 0) (car win-boundary))
+                        (c-get-char-property (match-beginning 0) 'fontified)
+                        (not c-re-redisplay-timer))
+               (setq c-re-redisplay-timer
+                     (run-with-timer 0 nil #'c-force-redisplay
+                                     (match-beginning 0) (match-end 
0)))))))))))
+
 
 ;;; C.
 
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index c9b7a95..ee5872d 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -129,6 +129,16 @@
 ;   '
 (require 'cc-fonts) ;)
 
+(defvar c-type-finder-timer nil)
+;; The variable which holds the repeating idle timer which triggers off the
+;; background type finding search.
+
+(defvar c-inhibit-type-finder nil)
+;; When non-nil (set by `c-post-gc-hook') don't perform the type finding
+;; activities the next time `c-type-finder-timer' triggers.  This ensures
+;; keyboard/mouse input will be dealt with when garbage collection is taking a
+;; large portion of CPU time.
+
 ;; The following three really belong to cc-fonts.el, but they are required
 ;; even when cc-fonts.el hasn't been loaded (this happens in XEmacs when
 ;; font-lock-mode is nil).
@@ -179,6 +189,18 @@
   (when c-buffer-is-cc-mode
     (save-restriction
       (widen)
+      (let ((lst (buffer-list)))
+       (catch 'found
+         (dolist (b lst)
+           (if (and (not (eq b (current-buffer)))
+                    (with-current-buffer b
+                      c-buffer-is-cc-mode))
+               (throw 'found nil)))
+         (remove-hook 'post-command-hook 'c-post-command)
+         (remove-hook 'post-gc-hook 'c-post-gc-hook)
+         (and c-type-finder-timer
+              (progn (cancel-timer c-type-finder-timer)
+                     (setq c-type-finder-timer nil)))))
       (c-save-buffer-state ()
        (c-clear-char-properties (point-min) (point-max) 'category)
        (c-clear-char-properties (point-min) (point-max) 'syntax-table)
@@ -574,6 +596,12 @@ preferably use the `c-mode-menu' language constant 
directly."
 ;; currently no such text property.
 (make-variable-buffer-local 'c-max-syn-tab-mkr)
 
+;; `c-type-finder-pos' is a marker marking the current place in a CC Mode
+;; buffer which is due to be searched next for "found types", or nil if the
+;; searching is complete.
+(defvar c-type-finder-pos nil)
+(make-variable-buffer-local 'c-type-finder-pos)
+
 (defun c-basic-common-init (mode default-style)
   "Initialize the syntax handling routines and the line breaking/filling code.
 Intended to be used by other packages that embed CC Mode.
@@ -745,6 +773,19 @@ that requires a literal mode spec at compile time."
   ;; would do since font-lock uses a(n implicit) depth of 0) so we don't need
   ;; c-after-font-lock-init.
   (add-hook 'after-change-functions 'c-after-change nil t)
+  (add-hook 'post-command-hook 'c-post-command)
+  (setq c-type-finder-pos
+       (save-restriction
+         (widen)
+         (move-marker (make-marker) (point-min))))
+
+  ;; Install the functionality for seeking "found types" at mode startup:
+  (or c-type-finder-timer
+      (setq c-type-finder-timer
+           (run-at-time
+            c-type-finder-repeat-time nil #'c-type-finder-timer-func)))
+  (add-hook 'post-gc-hook #'c-post-gc-hook)
+
   (when (boundp 'font-lock-extend-after-change-region-function)
     (set (make-local-variable 'font-lock-extend-after-change-region-function)
          'c-extend-after-change-region))) ; Currently (2009-05) used by all
@@ -1950,6 +1991,46 @@ Note that this is a strict tail, so won't match, e.g. 
\"0x....\".")
        ;; confused by already processed single quotes.
        (narrow-to-region (point) (point-max))))))
 
+;; The next two variables record the bounds of an identifier currently being
+;; typed in.  These are used to prevent such a partial identifier being
+;; recorded as a found type by c-add-type.
+(defvar c-new-id-start nil)
+(make-variable-buffer-local 'c-new-id-start)
+(defvar c-new-id-end nil)
+(make-variable-buffer-local 'c-new-id-end)
+;; The next variable, when non-nil, records that the previous two variables
+;; define a type.
+(defvar c-new-id-is-type nil)
+(make-variable-buffer-local 'c-new-id-is-type)
+
+(defun c-update-new-id (end)
+  ;; Note the bounds of any identifier that END is in or just after, in
+  ;; `c-new-id-start' and `c-new-id-end'.  Otherwise set these variables to
+  ;; nil.
+  (save-excursion
+    (goto-char end)
+    (let ((id-beg (c-on-identifier)))
+      (setq c-new-id-start id-beg
+           c-new-id-end (and id-beg
+                             (progn (c-end-of-current-token) (point)))))))
+
+
+(defun c-post-command ()
+  ;; If point was inside of a new identifier and no longer is, record that
+  ;; fact.
+  (when (and c-buffer-is-cc-mode
+            c-new-id-start c-new-id-end
+            (or (> (point) c-new-id-end)
+                (< (point) c-new-id-start)))
+    (when c-new-id-is-type
+      (c-add-type-1 c-new-id-start c-new-id-end))
+    (setq c-new-id-start nil
+         c-new-id-end nil
+         c-new-id-is-type nil)))
+
+(defun c-post-gc-hook (&optional _stats) ; For XEmacs.
+  (setq c-inhibit-type-finder t))
+
 (defun c-before-change (beg end)
   ;; Function to be put on `before-change-functions'.  Primarily, this calls
   ;; the language dependent `c-get-state-before-change-functions'.  It is
@@ -1969,11 +2050,16 @@ Note that this is a strict tail, so won't match, e.g. 
\"0x....\".")
   (unless (c-called-from-text-property-change-p)
     (save-restriction
       (widen)
+      ;; Clear the list of found types if we make a change at the start of the
+      ;; buffer, to make it easier to get rid of misspelled types and
+      ;; variables that have gotten recognized as types in malformed code.
+      (when (eq beg (point-min))
+       (c-clear-found-types))
       (if c-just-done-before-change
-         ;; We have two consecutive calls to `before-change-functions' without
-         ;; an intervening `after-change-functions'.  An example of this is bug
-         ;; #38691.  To protect CC Mode, assume that the entire buffer has
-         ;; changed.
+         ;; We have two consecutive calls to `before-change-functions'
+         ;; without an intervening `after-change-functions'.  An example of
+         ;; this is bug #38691.  To protect CC Mode, assume that the entire
+         ;; buffer has changed.
          (setq beg (point-min)
                end (point-max)
                c-just-done-before-change 'whole-buffer)
@@ -2151,6 +2237,7 @@ Note that this is a strict tail, so won't match, e.g. 
\"0x....\".")
                                                      c->-as-paren-syntax)
                    (c-clear-char-property-with-value beg end 'syntax-table 
nil)))
 
+               (c-update-new-id end)
                (c-trim-found-types beg end old-len) ; maybe we don't
                                                     ; need all of these.
                (c-invalidate-sws-region-after beg end old-len)
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 83fd3da..40a43c3 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1524,6 +1524,39 @@ working due to this change."
   :type 'boolean
   :group 'c)
 
+(defcustom c-type-finder-time-slot 0.05
+  "The length in seconds of a background type search time slot.
+
+In CC Mode modes, \"found types\" wouldn't always get cleanly
+fontified without the background searching for them which happens
+in the seconds after starting Emacs or initializing the major
+mode.
+
+This background searching can be disabled by setting this option
+to nil."
+  :type '(choice (const :tag "disabled" nil)
+                number)
+  :group 'c)
+
+(defcustom c-type-finder-repeat-time 0.1
+  "The interval, in seconds, at which background type searches occur.
+
+This interval must be greater than `c-type-finder-time-slot'."
+  :type 'number
+  :group 'c)
+
+(defcustom c-type-finder-chunk-size 1000
+  "The size, in characters, of a chunk for background type search.
+
+Chunks of this size are searched atomically for \"found types\"
+just after starting Emacs or initializing the major mode.
+
+This chunk size is a balance between efficiency (with larger
+values) and responsiveness of the keyboard (with smaller values).
+See also `c-type-finder-time-slot'."
+  :type 'integer
+  :group 'c)
+
 (define-widget 'c-extra-types-widget 'radio
   "Internal CC Mode widget for the `*-font-lock-extra-types' variables."
   :args '((const :tag "none" nil)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]