diff options
| author | Alan Mackenzie | 2012-01-18 13:19:31 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2012-01-18 13:19:31 +0000 |
| commit | 9657183b6f79dceb468bf70ce0980788dc3f0da7 (patch) | |
| tree | 2707051d21c41e925d568246ee024ac94df7f0f2 | |
| parent | e8afb1265f8067d360f03c514603223cde92ffeb (diff) | |
| download | emacs-9657183b6f79dceb468bf70ce0980788dc3f0da7.tar.gz emacs-9657183b6f79dceb468bf70ce0980788dc3f0da7.zip | |
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.
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 143 | ||||
| -rw-r--r-- | lisp/progmodes/cc-fonts.el | 48 |
2 files changed, 168 insertions, 23 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 2e0294341da..25344fe96a7 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -2074,7 +2074,7 @@ comment at the start of cc-engine.el for more info." | |||
| 2074 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 2074 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2075 | ;; We maintain a simple cache of positions which aren't in a literal, so as to | 2075 | ;; We maintain a simple cache of positions which aren't in a literal, so as to |
| 2076 | ;; speed up testing for non-literality. | 2076 | ;; speed up testing for non-literality. |
| 2077 | (defconst c-state-nonlit-pos-interval 10000) | 2077 | (defconst c-state-nonlit-pos-interval 3000) |
| 2078 | ;; The approximate interval between entries in `c-state-nonlit-pos-cache'. | 2078 | ;; The approximate interval between entries in `c-state-nonlit-pos-cache'. |
| 2079 | 2079 | ||
| 2080 | (defvar c-state-nonlit-pos-cache nil) | 2080 | (defvar c-state-nonlit-pos-cache nil) |
| @@ -2129,7 +2129,7 @@ comment at the start of cc-engine.el for more info." | |||
| 2129 | (widen) | 2129 | (widen) |
| 2130 | (save-excursion | 2130 | (save-excursion |
| 2131 | (let ((c c-state-nonlit-pos-cache) | 2131 | (let ((c c-state-nonlit-pos-cache) |
| 2132 | pos npos lit) | 2132 | pos npos lit macro-beg) |
| 2133 | ;; Trim the cache to take account of buffer changes. | 2133 | ;; Trim the cache to take account of buffer changes. |
| 2134 | (while (and c (> (car c) c-state-nonlit-pos-cache-limit)) | 2134 | (while (and c (> (car c) c-state-nonlit-pos-cache-limit)) |
| 2135 | (setq c (cdr c))) | 2135 | (setq c (cdr c))) |
| @@ -2139,16 +2139,32 @@ comment at the start of cc-engine.el for more info." | |||
| 2139 | (setq c (cdr c))) | 2139 | (setq c (cdr c))) |
| 2140 | (setq pos (or (car c) (point-min))) | 2140 | (setq pos (or (car c) (point-min))) |
| 2141 | 2141 | ||
| 2142 | (while (<= (setq npos (+ pos c-state-nonlit-pos-interval)) | 2142 | (while |
| 2143 | here) | 2143 | ;; Add an element to `c-state-nonlit-pos-cache' each iteration. |
| 2144 | (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) | 2144 | (and |
| 2145 | (setq pos (or (cdr lit) npos)) ; end of literal containing npos. | 2145 | (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) |
| 2146 | (progn | ||
| 2147 | (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) | ||
| 2148 | (cond | ||
| 2149 | ((null lit) | ||
| 2150 | (setq pos npos) | ||
| 2151 | t) | ||
| 2152 | ((<= (cdr lit) here) | ||
| 2153 | (setq pos (cdr lit)) | ||
| 2154 | t) | ||
| 2155 | (t | ||
| 2156 | (setq pos (car lit)) | ||
| 2157 | nil)))) | ||
| 2158 | |||
| 2146 | (goto-char pos) | 2159 | (goto-char pos) |
| 2147 | (when (and (c-beginning-of-macro) (/= (point) pos)) | 2160 | (when (and (c-beginning-of-macro) (/= (point) pos)) |
| 2148 | (c-syntactic-end-of-macro) | 2161 | (setq macro-beg (point)) |
| 2149 | (or (eobp) (forward-char)) | 2162 | (c-syntactic-end-of-macro) |
| 2150 | (setq pos (point))) | 2163 | (or (eobp) (forward-char)) |
| 2151 | (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache))) | 2164 | (setq pos (if (<= (point) here) |
| 2165 | (point) | ||
| 2166 | macro-beg))) | ||
| 2167 | (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache))) | ||
| 2152 | 2168 | ||
| 2153 | (if (> pos c-state-nonlit-pos-cache-limit) | 2169 | (if (> pos c-state-nonlit-pos-cache-limit) |
| 2154 | (setq c-state-nonlit-pos-cache-limit pos)) | 2170 | (setq c-state-nonlit-pos-cache-limit pos)) |
| @@ -4351,6 +4367,78 @@ comment at the start of cc-engine.el for more info." | |||
| 4351 | (t 'c))) ; Assuming the range is valid. | 4367 | (t 'c))) ; Assuming the range is valid. |
| 4352 | range)) | 4368 | range)) |
| 4353 | 4369 | ||
| 4370 | (defsubst c-determine-limit-get-base (start try-size) | ||
| 4371 | ;; Get a "safe place" approximately TRY-SIZE characters before START. | ||
| 4372 | ;; This doesn't preserve point. | ||
| 4373 | (let* ((pos (max (- start try-size) (point-min))) | ||
| 4374 | (base (c-state-safe-place pos)) | ||
| 4375 | (s (parse-partial-sexp base pos))) | ||
| 4376 | (if (or (nth 4 s) (nth 3 s)) ; comment or string | ||
| 4377 | (nth 8 s) | ||
| 4378 | (point)))) | ||
| 4379 | |||
| 4380 | (defun c-determine-limit (how-far-back &optional start try-size) | ||
| 4381 | ;; Return a buffer position HOW-FAR-BACK non-literal characters from START | ||
| 4382 | ;; (default point). This is done by going back further in the buffer then | ||
| 4383 | ;; searching forward for literals. The position found won't be in a | ||
| 4384 | ;; literal. We start searching for the sought position TRY-SIZE (default | ||
| 4385 | ;; twice HOW-FAR-BACK) bytes back from START. This function must be fast. | ||
| 4386 | ;; :-) | ||
| 4387 | (save-excursion | ||
| 4388 | (let* ((start (or start (point))) | ||
| 4389 | (try-size (or try-size (* 2 how-far-back))) | ||
| 4390 | (base (c-determine-limit-get-base start try-size)) | ||
| 4391 | (pos base) | ||
| 4392 | |||
| 4393 | (s (parse-partial-sexp pos pos)) ; null state. | ||
| 4394 | stack elt size | ||
| 4395 | (count 0)) | ||
| 4396 | (while (< pos start) | ||
| 4397 | ;; Move forward one literal each time round this loop. | ||
| 4398 | ;; Move forward to the start of a comment or string. | ||
| 4399 | (setq s (parse-partial-sexp | ||
| 4400 | pos | ||
| 4401 | start | ||
| 4402 | nil ; target-depth | ||
| 4403 | nil ; stop-before | ||
| 4404 | s ; state | ||
| 4405 | 'syntax-table)) ; stop-comment | ||
| 4406 | |||
| 4407 | ;; Gather details of the non-literal-bit - starting pos and size. | ||
| 4408 | (setq size (- (if (or (nth 4 s) (nth 3 s)) | ||
| 4409 | (nth 8 s) | ||
| 4410 | (point)) | ||
| 4411 | pos)) | ||
| 4412 | (if (> size 0) | ||
| 4413 | (setq stack (cons (cons pos size) stack))) | ||
| 4414 | |||
| 4415 | ;; Move forward to the end of the comment/string. | ||
| 4416 | (if (or (nth 4 s) (nth 3 s)) | ||
| 4417 | (setq s (parse-partial-sexp | ||
| 4418 | (point) | ||
| 4419 | start | ||
| 4420 | nil ; target-depth | ||
| 4421 | nil ; stop-before | ||
| 4422 | s ; state | ||
| 4423 | 'syntax-table))) ; stop-comment | ||
| 4424 | (setq pos (point))) | ||
| 4425 | |||
| 4426 | ;; Now try and find enough non-literal characters recorded on the stack. | ||
| 4427 | ;; Go back one recorded literal each time round this loop. | ||
| 4428 | (while (and (< count how-far-back) | ||
| 4429 | stack) | ||
| 4430 | (setq elt (car stack) | ||
| 4431 | stack (cdr stack)) | ||
| 4432 | (setq count (+ count (cdr elt)))) | ||
| 4433 | |||
| 4434 | ;; Have we found enough yet? | ||
| 4435 | (cond | ||
| 4436 | ((>= count how-far-back) | ||
| 4437 | (+ (car elt) (- count how-far-back))) | ||
| 4438 | ((eq base (point-min)) | ||
| 4439 | (point-min)) | ||
| 4440 | (t | ||
| 4441 | (c-determine-limit (- how-far-back count) base try-size)))))) | ||
| 4354 | 4442 | ||
| 4355 | ;; `c-find-decl-spots' and accompanying stuff. | 4443 | ;; `c-find-decl-spots' and accompanying stuff. |
| 4356 | 4444 | ||
| @@ -4487,13 +4575,14 @@ comment at the start of cc-engine.el for more info." | |||
| 4487 | ;; Call CFD-FUN for each possible spot for a declaration, cast or | 4575 | ;; Call CFD-FUN for each possible spot for a declaration, cast or |
| 4488 | ;; label from the point to CFD-LIMIT. | 4576 | ;; label from the point to CFD-LIMIT. |
| 4489 | ;; | 4577 | ;; |
| 4490 | ;; CFD-FUN is called with point at the start of the spot. It's | 4578 | ;; CFD-FUN is called with point at the start of the spot. It's passed two |
| 4491 | ;; passed two arguments: The first is the end position of the token | 4579 | ;; arguments: The first is the end position of the token preceding the spot, |
| 4492 | ;; preceding the spot, or 0 for the implicit match at bob. The | 4580 | ;; or 0 for the implicit match at bob. The second is a flag that is t when |
| 4493 | ;; second is a flag that is t when the match is inside a macro. If | 4581 | ;; the match is inside a macro. Point should be moved forward by at least |
| 4494 | ;; CFD-FUN adds `c-decl-end' properties somewhere below the current | 4582 | ;; one token. |
| 4495 | ;; spot, it should return non-nil to ensure that the next search | 4583 | ;; |
| 4496 | ;; will find them. | 4584 | ;; If CFD-FUN adds `c-decl-end' properties somewhere below the current spot, |
| 4585 | ;; it should return non-nil to ensure that the next search will find them. | ||
| 4497 | ;; | 4586 | ;; |
| 4498 | ;; Such a spot is: | 4587 | ;; Such a spot is: |
| 4499 | ;; o The first token after bob. | 4588 | ;; o The first token after bob. |
| @@ -4867,7 +4956,8 @@ comment at the start of cc-engine.el for more info." | |||
| 4867 | (goto-char cfd-continue-pos) | 4956 | (goto-char cfd-continue-pos) |
| 4868 | (if (= cfd-continue-pos cfd-limit) | 4957 | (if (= cfd-continue-pos cfd-limit) |
| 4869 | (setq cfd-match-pos cfd-limit) | 4958 | (setq cfd-match-pos cfd-limit) |
| 4870 | (c-find-decl-prefix-search))))) | 4959 | (c-find-decl-prefix-search))))) ; Moves point, sets cfd-continue-pos, |
| 4960 | ; cfd-match-pos, etc. | ||
| 4871 | 4961 | ||
| 4872 | 4962 | ||
| 4873 | ;; A cache for found types. | 4963 | ;; A cache for found types. |
| @@ -8047,6 +8137,23 @@ comment at the start of cc-engine.el for more info." | |||
| 8047 | next-open-brace (c-pull-open-brace paren-state))) | 8137 | next-open-brace (c-pull-open-brace paren-state))) |
| 8048 | open-brace)) | 8138 | open-brace)) |
| 8049 | 8139 | ||
| 8140 | (defun c-cheap-inside-bracelist-p (paren-state) | ||
| 8141 | ;; Return the position of the L-brace if point is inside a brace list | ||
| 8142 | ;; initialization of an array, etc. This is an approximate function, | ||
| 8143 | ;; designed for speed over accuracy. It will not find every bracelist, but | ||
| 8144 | ;; a non-nil result is reliable. We simply search for "= {" (naturally with | ||
| 8145 | ;; syntactic whitespace allowed). PAREN-STATE is the normal thing that it | ||
| 8146 | ;; is everywhere else. | ||
| 8147 | (let (b-pos) | ||
| 8148 | (save-excursion | ||
| 8149 | (while | ||
| 8150 | (and (setq b-pos (c-pull-open-brace paren-state)) | ||
| 8151 | (progn (goto-char b-pos) | ||
| 8152 | (c-backward-sws) | ||
| 8153 | (c-backward-token-2) | ||
| 8154 | (not (looking-at "="))))) | ||
| 8155 | b-pos))) | ||
| 8156 | |||
| 8050 | (defun c-inside-bracelist-p (containing-sexp paren-state) | 8157 | (defun c-inside-bracelist-p (containing-sexp paren-state) |
| 8051 | ;; return the buffer position of the beginning of the brace list | 8158 | ;; return the buffer position of the beginning of the brace list |
| 8052 | ;; statement if we're inside a brace list, otherwise return nil. | 8159 | ;; statement if we're inside a brace list, otherwise return nil. |
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index e7d00815708..2d116e1ecdc 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el | |||
| @@ -446,10 +446,12 @@ | |||
| 446 | ;; `parse-sexp-lookup-properties' (when it exists). | 446 | ;; `parse-sexp-lookup-properties' (when it exists). |
| 447 | (parse-sexp-lookup-properties | 447 | (parse-sexp-lookup-properties |
| 448 | (cc-eval-when-compile | 448 | (cc-eval-when-compile |
| 449 | (boundp 'parse-sexp-lookup-properties)))) | 449 | (boundp 'parse-sexp-lookup-properties))) |
| 450 | (BOD-limit | ||
| 451 | (c-determine-limit 1000))) | ||
| 450 | (goto-char | 452 | (goto-char |
| 451 | (let ((here (point))) | 453 | (let ((here (point))) |
| 452 | (if (eq (car (c-beginning-of-decl-1)) 'same) | 454 | (if (eq (car (c-beginning-of-decl-1 BOD-limit)) 'same) |
| 453 | (point) | 455 | (point) |
| 454 | here))) | 456 | here))) |
| 455 | ,(c-make-font-lock-search-form regexp highlights)) | 457 | ,(c-make-font-lock-search-form regexp highlights)) |
| @@ -1240,6 +1242,7 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1240 | ;; it finds any. That's necessary so that we later will | 1242 | ;; it finds any. That's necessary so that we later will |
| 1241 | ;; stop inside them to fontify types there. | 1243 | ;; stop inside them to fontify types there. |
| 1242 | (c-parse-and-markup-<>-arglists t) | 1244 | (c-parse-and-markup-<>-arglists t) |
| 1245 | lbrace ; position of some {. | ||
| 1243 | ;; The font-lock package in Emacs is known to clobber | 1246 | ;; The font-lock package in Emacs is known to clobber |
| 1244 | ;; `parse-sexp-lookup-properties' (when it exists). | 1247 | ;; `parse-sexp-lookup-properties' (when it exists). |
| 1245 | (parse-sexp-lookup-properties | 1248 | (parse-sexp-lookup-properties |
| @@ -1351,7 +1354,6 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1351 | (or (looking-at c-typedef-key) | 1354 | (or (looking-at c-typedef-key) |
| 1352 | (goto-char start-pos))) | 1355 | (goto-char start-pos))) |
| 1353 | 1356 | ||
| 1354 | ;; Now analyze the construct. | ||
| 1355 | ;; In QT, "more" is an irritating keyword that expands to nothing. | 1357 | ;; In QT, "more" is an irritating keyword that expands to nothing. |
| 1356 | ;; We skip over it to prevent recognition of "more slots: <symbol>" | 1358 | ;; We skip over it to prevent recognition of "more slots: <symbol>" |
| 1357 | ;; as a bitfield declaration. | 1359 | ;; as a bitfield declaration. |
| @@ -1360,6 +1362,8 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1360 | (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)"))) | 1362 | (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)"))) |
| 1361 | (goto-char (match-end 1)) | 1363 | (goto-char (match-end 1)) |
| 1362 | (c-forward-syntactic-ws)) | 1364 | (c-forward-syntactic-ws)) |
| 1365 | |||
| 1366 | ;; Now analyze the construct. | ||
| 1363 | (setq decl-or-cast (c-forward-decl-or-cast-1 | 1367 | (setq decl-or-cast (c-forward-decl-or-cast-1 |
| 1364 | match-pos context last-cast-end)) | 1368 | match-pos context last-cast-end)) |
| 1365 | 1369 | ||
| @@ -1428,6 +1432,39 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1428 | (c-fontify-recorded-types-and-refs) | 1432 | (c-fontify-recorded-types-and-refs) |
| 1429 | nil) | 1433 | nil) |
| 1430 | 1434 | ||
| 1435 | ;; Restore point, since at this point in the code it has been | ||
| 1436 | ;; left undefined by c-forward-decl-or-cast-1 above. | ||
| 1437 | ((progn (goto-char start-pos) nil)) | ||
| 1438 | |||
| 1439 | ;; If point is inside a bracelist, there's no point checking it | ||
| 1440 | ;; being at a declarator. | ||
| 1441 | ((let ((paren-state (c-parse-state))) | ||
| 1442 | (setq lbrace (c-cheap-inside-bracelist-p paren-state))) | ||
| 1443 | ;; Move past this bracelist to prevent an endless loop. | ||
| 1444 | (goto-char lbrace) | ||
| 1445 | (unless (c-safe (progn (forward-list) t)) | ||
| 1446 | (goto-char start-pos) | ||
| 1447 | (c-forward-token-2)) | ||
| 1448 | nil) | ||
| 1449 | |||
| 1450 | ;; If point is just after a ")" which is followed by an | ||
| 1451 | ;; identifier which isn't a label, or at the matching "(", we're | ||
| 1452 | ;; at either a macro invocation, a cast, or a | ||
| 1453 | ;; for/while/etc. statement. The cast case is handled above. | ||
| 1454 | ;; None of these cases can contain a declarator. | ||
| 1455 | ((or (and (eq (char-before match-pos) ?\)) | ||
| 1456 | (c-on-identifier) | ||
| 1457 | (save-excursion (not (c-forward-label)))) | ||
| 1458 | (and (eq (char-after) ?\() | ||
| 1459 | (save-excursion | ||
| 1460 | (and | ||
| 1461 | (progn (c-backward-token-2) (c-on-identifier)) | ||
| 1462 | (save-excursion (not (c-forward-label))) | ||
| 1463 | (progn (c-backward-token-2) | ||
| 1464 | (eq (char-after) ?\()))))) | ||
| 1465 | (c-forward-token-2) ; Must prevent looping. | ||
| 1466 | nil) | ||
| 1467 | |||
| 1431 | ((and (not c-enums-contain-decls) | 1468 | ((and (not c-enums-contain-decls) |
| 1432 | ;; An optimization quickly to eliminate scans of long enum | 1469 | ;; An optimization quickly to eliminate scans of long enum |
| 1433 | ;; declarations in the next cond arm. | 1470 | ;; declarations in the next cond arm. |
| @@ -1441,13 +1478,14 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1441 | (progn | 1478 | (progn |
| 1442 | (c-backward-token-2) | 1479 | (c-backward-token-2) |
| 1443 | (looking-at c-brace-list-key))))))) | 1480 | (looking-at c-brace-list-key))))))) |
| 1444 | t) | 1481 | (c-forward-token-2) |
| 1482 | nil) | ||
| 1445 | 1483 | ||
| 1446 | (t | 1484 | (t |
| 1447 | ;; Are we at a declarator? Try to go back to the declaration | 1485 | ;; Are we at a declarator? Try to go back to the declaration |
| 1448 | ;; to check this. If we get there, check whether a "typedef" | 1486 | ;; to check this. If we get there, check whether a "typedef" |
| 1449 | ;; is there, then fontify the declarators accordingly. | 1487 | ;; is there, then fontify the declarators accordingly. |
| 1450 | (let ((decl-search-lim (max (- (point) 50000) (point-min))) | 1488 | (let ((decl-search-lim (c-determine-limit 1000)) |
| 1451 | paren-state bod-res encl-pos is-typedef | 1489 | paren-state bod-res encl-pos is-typedef |
| 1452 | c-recognize-knr-p) ; Strictly speaking, bogus, but it | 1490 | c-recognize-knr-p) ; Strictly speaking, bogus, but it |
| 1453 | ; speeds up lisp.h tremendously. | 1491 | ; speeds up lisp.h tremendously. |