Eliminate sluggishness and hangs in fontification of "semicolon deserts".
cc-engine.el (c-state-nonlit-pos-interval): change value 10000 -> 3000. (c-state-safe-place): Reformulate so it doesn't stack up an infinite number of wrong entries in c-state-nonlit-pos-cache. (c-determine-limit-get-base, c-determine-limit): New functions to determine backward search limits disregarding literals. (c-find-decl-spots): Amend commenting. (c-cheap-inside-bracelist-p): New function which detects "={". cc-fonts.el (c-make-font-lock-BO-decl-search-function): Give a limit to a backward search. (c-font-lock-declarations): Fix an occurrence of point being undefined. Check additionally for point being in a bracelist or near a macro invocation without a semicolon so as to avoid a fruitless time consuming search for a declarator. Give a more precise search limit for declarators using the new c-determine-limit.
This commit is contained in:
parent
e8afb1265f
commit
9657183b6f
2 changed files with 168 additions and 23 deletions
|
@ -2074,7 +2074,7 @@ comment at the start of cc-engine.el for more info."
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; We maintain a simple cache of positions which aren't in a literal, so as to
|
||||
;; speed up testing for non-literality.
|
||||
(defconst c-state-nonlit-pos-interval 10000)
|
||||
(defconst c-state-nonlit-pos-interval 3000)
|
||||
;; The approximate interval between entries in `c-state-nonlit-pos-cache'.
|
||||
|
||||
(defvar c-state-nonlit-pos-cache nil)
|
||||
|
@ -2129,7 +2129,7 @@ comment at the start of cc-engine.el for more info."
|
|||
(widen)
|
||||
(save-excursion
|
||||
(let ((c c-state-nonlit-pos-cache)
|
||||
pos npos lit)
|
||||
pos npos lit macro-beg)
|
||||
;; Trim the cache to take account of buffer changes.
|
||||
(while (and c (> (car c) c-state-nonlit-pos-cache-limit))
|
||||
(setq c (cdr c)))
|
||||
|
@ -2139,16 +2139,32 @@ comment at the start of cc-engine.el for more info."
|
|||
(setq c (cdr c)))
|
||||
(setq pos (or (car c) (point-min)))
|
||||
|
||||
(while (<= (setq npos (+ pos c-state-nonlit-pos-interval))
|
||||
here)
|
||||
(setq lit (car (cddr (c-state-pp-to-literal pos npos))))
|
||||
(setq pos (or (cdr lit) npos)) ; end of literal containing npos.
|
||||
(while
|
||||
;; Add an element to `c-state-nonlit-pos-cache' each iteration.
|
||||
(and
|
||||
(<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
|
||||
(progn
|
||||
(setq lit (car (cddr (c-state-pp-to-literal pos npos))))
|
||||
(cond
|
||||
((null lit)
|
||||
(setq pos npos)
|
||||
t)
|
||||
((<= (cdr lit) here)
|
||||
(setq pos (cdr lit))
|
||||
t)
|
||||
(t
|
||||
(setq pos (car lit))
|
||||
nil))))
|
||||
|
||||
(goto-char pos)
|
||||
(when (and (c-beginning-of-macro) (/= (point) pos))
|
||||
(c-syntactic-end-of-macro)
|
||||
(or (eobp) (forward-char))
|
||||
(setq pos (point)))
|
||||
(setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
|
||||
(setq macro-beg (point))
|
||||
(c-syntactic-end-of-macro)
|
||||
(or (eobp) (forward-char))
|
||||
(setq pos (if (<= (point) here)
|
||||
(point)
|
||||
macro-beg)))
|
||||
(setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
|
||||
|
||||
(if (> pos c-state-nonlit-pos-cache-limit)
|
||||
(setq c-state-nonlit-pos-cache-limit pos))
|
||||
|
@ -4351,6 +4367,78 @@ comment at the start of cc-engine.el for more info."
|
|||
(t 'c))) ; Assuming the range is valid.
|
||||
range))
|
||||
|
||||
(defsubst c-determine-limit-get-base (start try-size)
|
||||
;; Get a "safe place" approximately TRY-SIZE characters before START.
|
||||
;; This doesn't preserve point.
|
||||
(let* ((pos (max (- start try-size) (point-min)))
|
||||
(base (c-state-safe-place pos))
|
||||
(s (parse-partial-sexp base pos)))
|
||||
(if (or (nth 4 s) (nth 3 s)) ; comment or string
|
||||
(nth 8 s)
|
||||
(point))))
|
||||
|
||||
(defun c-determine-limit (how-far-back &optional start try-size)
|
||||
;; Return a buffer position HOW-FAR-BACK non-literal characters from START
|
||||
;; (default point). This is done by going back further in the buffer then
|
||||
;; searching forward for literals. The position found won't be in a
|
||||
;; literal. We start searching for the sought position TRY-SIZE (default
|
||||
;; twice HOW-FAR-BACK) bytes back from START. This function must be fast.
|
||||
;; :-)
|
||||
(save-excursion
|
||||
(let* ((start (or start (point)))
|
||||
(try-size (or try-size (* 2 how-far-back)))
|
||||
(base (c-determine-limit-get-base start try-size))
|
||||
(pos base)
|
||||
|
||||
(s (parse-partial-sexp pos pos)) ; null state.
|
||||
stack elt size
|
||||
(count 0))
|
||||
(while (< pos start)
|
||||
;; Move forward one literal each time round this loop.
|
||||
;; Move forward to the start of a comment or string.
|
||||
(setq s (parse-partial-sexp
|
||||
pos
|
||||
start
|
||||
nil ; target-depth
|
||||
nil ; stop-before
|
||||
s ; state
|
||||
'syntax-table)) ; stop-comment
|
||||
|
||||
;; Gather details of the non-literal-bit - starting pos and size.
|
||||
(setq size (- (if (or (nth 4 s) (nth 3 s))
|
||||
(nth 8 s)
|
||||
(point))
|
||||
pos))
|
||||
(if (> size 0)
|
||||
(setq stack (cons (cons pos size) stack)))
|
||||
|
||||
;; Move forward to the end of the comment/string.
|
||||
(if (or (nth 4 s) (nth 3 s))
|
||||
(setq s (parse-partial-sexp
|
||||
(point)
|
||||
start
|
||||
nil ; target-depth
|
||||
nil ; stop-before
|
||||
s ; state
|
||||
'syntax-table))) ; stop-comment
|
||||
(setq pos (point)))
|
||||
|
||||
;; Now try and find enough non-literal characters recorded on the stack.
|
||||
;; Go back one recorded literal each time round this loop.
|
||||
(while (and (< count how-far-back)
|
||||
stack)
|
||||
(setq elt (car stack)
|
||||
stack (cdr stack))
|
||||
(setq count (+ count (cdr elt))))
|
||||
|
||||
;; Have we found enough yet?
|
||||
(cond
|
||||
((>= count how-far-back)
|
||||
(+ (car elt) (- count how-far-back)))
|
||||
((eq base (point-min))
|
||||
(point-min))
|
||||
(t
|
||||
(c-determine-limit (- how-far-back count) base try-size))))))
|
||||
|
||||
;; `c-find-decl-spots' and accompanying stuff.
|
||||
|
||||
|
@ -4487,13 +4575,14 @@ comment at the start of cc-engine.el for more info."
|
|||
;; Call CFD-FUN for each possible spot for a declaration, cast or
|
||||
;; label from the point to CFD-LIMIT.
|
||||
;;
|
||||
;; CFD-FUN is called with point at the start of the spot. It's
|
||||
;; passed two arguments: The first is the end position of the token
|
||||
;; preceding the spot, or 0 for the implicit match at bob. The
|
||||
;; second is a flag that is t when the match is inside a macro. If
|
||||
;; CFD-FUN adds `c-decl-end' properties somewhere below the current
|
||||
;; spot, it should return non-nil to ensure that the next search
|
||||
;; will find them.
|
||||
;; CFD-FUN is called with point at the start of the spot. It's passed two
|
||||
;; arguments: The first is the end position of the token preceding the spot,
|
||||
;; or 0 for the implicit match at bob. The second is a flag that is t when
|
||||
;; the match is inside a macro. Point should be moved forward by at least
|
||||
;; one token.
|
||||
;;
|
||||
;; If CFD-FUN adds `c-decl-end' properties somewhere below the current spot,
|
||||
;; it should return non-nil to ensure that the next search will find them.
|
||||
;;
|
||||
;; Such a spot is:
|
||||
;; o The first token after bob.
|
||||
|
@ -4867,7 +4956,8 @@ comment at the start of cc-engine.el for more info."
|
|||
(goto-char cfd-continue-pos)
|
||||
(if (= cfd-continue-pos cfd-limit)
|
||||
(setq cfd-match-pos cfd-limit)
|
||||
(c-find-decl-prefix-search)))))
|
||||
(c-find-decl-prefix-search))))) ; Moves point, sets cfd-continue-pos,
|
||||
; cfd-match-pos, etc.
|
||||
|
||||
|
||||
;; A cache for found types.
|
||||
|
@ -8047,6 +8137,23 @@ comment at the start of cc-engine.el for more info."
|
|||
next-open-brace (c-pull-open-brace paren-state)))
|
||||
open-brace))
|
||||
|
||||
(defun c-cheap-inside-bracelist-p (paren-state)
|
||||
;; Return the position of the L-brace if point is inside a brace list
|
||||
;; initialization of an array, etc. This is an approximate function,
|
||||
;; designed for speed over accuracy. It will not find every bracelist, but
|
||||
;; a non-nil result is reliable. We simply search for "= {" (naturally with
|
||||
;; syntactic whitespace allowed). PAREN-STATE is the normal thing that it
|
||||
;; is everywhere else.
|
||||
(let (b-pos)
|
||||
(save-excursion
|
||||
(while
|
||||
(and (setq b-pos (c-pull-open-brace paren-state))
|
||||
(progn (goto-char b-pos)
|
||||
(c-backward-sws)
|
||||
(c-backward-token-2)
|
||||
(not (looking-at "=")))))
|
||||
b-pos)))
|
||||
|
||||
(defun c-inside-bracelist-p (containing-sexp paren-state)
|
||||
;; return the buffer position of the beginning of the brace list
|
||||
;; statement if we're inside a brace list, otherwise return nil.
|
||||
|
|
|
@ -446,10 +446,12 @@
|
|||
;; `parse-sexp-lookup-properties' (when it exists).
|
||||
(parse-sexp-lookup-properties
|
||||
(cc-eval-when-compile
|
||||
(boundp 'parse-sexp-lookup-properties))))
|
||||
(boundp 'parse-sexp-lookup-properties)))
|
||||
(BOD-limit
|
||||
(c-determine-limit 1000)))
|
||||
(goto-char
|
||||
(let ((here (point)))
|
||||
(if (eq (car (c-beginning-of-decl-1)) 'same)
|
||||
(if (eq (car (c-beginning-of-decl-1 BOD-limit)) 'same)
|
||||
(point)
|
||||
here)))
|
||||
,(c-make-font-lock-search-form regexp highlights))
|
||||
|
@ -1240,6 +1242,7 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
;; it finds any. That's necessary so that we later will
|
||||
;; stop inside them to fontify types there.
|
||||
(c-parse-and-markup-<>-arglists t)
|
||||
lbrace ; position of some {.
|
||||
;; The font-lock package in Emacs is known to clobber
|
||||
;; `parse-sexp-lookup-properties' (when it exists).
|
||||
(parse-sexp-lookup-properties
|
||||
|
@ -1351,7 +1354,6 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(or (looking-at c-typedef-key)
|
||||
(goto-char start-pos)))
|
||||
|
||||
;; Now analyze the construct.
|
||||
;; 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.
|
||||
|
@ -1360,6 +1362,8 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
|
||||
(goto-char (match-end 1))
|
||||
(c-forward-syntactic-ws))
|
||||
|
||||
;; Now analyze the construct.
|
||||
(setq decl-or-cast (c-forward-decl-or-cast-1
|
||||
match-pos context last-cast-end))
|
||||
|
||||
|
@ -1428,6 +1432,39 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(c-fontify-recorded-types-and-refs)
|
||||
nil)
|
||||
|
||||
;; Restore point, since at this point in the code it has been
|
||||
;; left undefined by c-forward-decl-or-cast-1 above.
|
||||
((progn (goto-char start-pos) nil))
|
||||
|
||||
;; If point is inside a bracelist, there's no point checking it
|
||||
;; being at a declarator.
|
||||
((let ((paren-state (c-parse-state)))
|
||||
(setq lbrace (c-cheap-inside-bracelist-p paren-state)))
|
||||
;; Move past this bracelist to prevent an endless loop.
|
||||
(goto-char lbrace)
|
||||
(unless (c-safe (progn (forward-list) t))
|
||||
(goto-char start-pos)
|
||||
(c-forward-token-2))
|
||||
nil)
|
||||
|
||||
;; If point is just after a ")" which is followed by an
|
||||
;; identifier which isn't a label, or at the matching "(", we're
|
||||
;; at either a macro invocation, a cast, or a
|
||||
;; for/while/etc. statement. The cast case is handled above.
|
||||
;; None of these cases can contain a declarator.
|
||||
((or (and (eq (char-before match-pos) ?\))
|
||||
(c-on-identifier)
|
||||
(save-excursion (not (c-forward-label))))
|
||||
(and (eq (char-after) ?\()
|
||||
(save-excursion
|
||||
(and
|
||||
(progn (c-backward-token-2) (c-on-identifier))
|
||||
(save-excursion (not (c-forward-label)))
|
||||
(progn (c-backward-token-2)
|
||||
(eq (char-after) ?\())))))
|
||||
(c-forward-token-2) ; Must prevent looping.
|
||||
nil)
|
||||
|
||||
((and (not c-enums-contain-decls)
|
||||
;; An optimization quickly to eliminate scans of long enum
|
||||
;; declarations in the next cond arm.
|
||||
|
@ -1441,13 +1478,14 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(progn
|
||||
(c-backward-token-2)
|
||||
(looking-at c-brace-list-key)))))))
|
||||
t)
|
||||
(c-forward-token-2)
|
||||
nil)
|
||||
|
||||
(t
|
||||
;; Are we at a declarator? Try to go back to the declaration
|
||||
;; to check this. If we get there, check whether a "typedef"
|
||||
;; is there, then fontify the declarators accordingly.
|
||||
(let ((decl-search-lim (max (- (point) 50000) (point-min)))
|
||||
(let ((decl-search-lim (c-determine-limit 1000))
|
||||
paren-state bod-res encl-pos is-typedef
|
||||
c-recognize-knr-p) ; Strictly speaking, bogus, but it
|
||||
; speeds up lisp.h tremendously.
|
||||
|
|
Loading…
Add table
Reference in a new issue