diff options
| author | Alan Mackenzie | 2011-12-24 19:32:31 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2011-12-24 19:32:31 +0000 |
| commit | be8b11bb321086c7edfdcf4ac079d694e6a8b97b (patch) | |
| tree | a2edb2d8feaa4b09d55988c2eeb8cb8df5e42480 | |
| parent | 3ba1a2ad82e1936f03b46b1db284945af806788b (diff) | |
| download | emacs-be8b11bb321086c7edfdcf4ac079d694e6a8b97b.tar.gz emacs-be8b11bb321086c7edfdcf4ac079d694e6a8b97b.zip | |
Introduce a mechanism to widen the region used in context font locking.
Use this to protect declarations from losing their contexts.
| -rw-r--r-- | lisp/ChangeLog | 23 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 26 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 204 |
3 files changed, 187 insertions, 66 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index f8f8e7eb695..8c368473871 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,26 @@ | |||
| 1 | 2011-12-24 Alan Mackenzie <acm@muc.de> | ||
| 2 | |||
| 3 | Introduce a mechanism to widen the region used in context font | ||
| 4 | locking. Use this to protect declarations from losing their | ||
| 5 | contexts. | ||
| 6 | |||
| 7 | * progmodes/cc-langs.el (c-before-font-lock-functions): replace | ||
| 8 | c-set-fl-decl-start with c-change-set-fl-decl-start (Renaming). | ||
| 9 | (c-before-context-fontification-functions): new defvar, a list of | ||
| 10 | functions to be run just before context (etc.) font locking. | ||
| 11 | |||
| 12 | * progmodes/cc-mode.el (c-extend-font-lock-region-for-macros): | ||
| 13 | new, functionality extracted from | ||
| 14 | c-neutralize-syntax-in-and-mark-CPP. | ||
| 15 | (c-in-after-change-fontification): new variable. | ||
| 16 | (c-after-change): Set c-in-after-change-fontification. | ||
| 17 | (c-set-fl-decl-start): Rejig its interface, so it can be called | ||
| 18 | from both after-change and context fontifying. | ||
| 19 | (c-change-set-fl-decl-start, c-context-set-fl-decl-start): new | ||
| 20 | functions. | ||
| 21 | (c-standard-font-lock-fontify-region-function): new variable. | ||
| 22 | (c-font-lock-fontify-region): new function. | ||
| 23 | |||
| 1 | 2011-12-24 Juri Linkov <juri@jurta.org> | 24 | 2011-12-24 Juri Linkov <juri@jurta.org> |
| 2 | 25 | ||
| 3 | * window.el (window--state-get-1): Set `FORCE' arg of `mark' to t. | 26 | * window.el (window--state-get-1): Set `FORCE' arg of `mark' to t. |
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 2b6dc7a9df7..2aca885ca35 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -488,8 +488,9 @@ parameters \(point-min) and \(point-max).") | |||
| 488 | (c-lang-defconst c-before-font-lock-functions | 488 | (c-lang-defconst c-before-font-lock-functions |
| 489 | ;; For documentation see the following c-lang-defvar of the same name. | 489 | ;; For documentation see the following c-lang-defvar of the same name. |
| 490 | ;; The value here may be a list of functions or a single function. | 490 | ;; The value here may be a list of functions or a single function. |
| 491 | t 'c-set-fl-decl-start | 491 | t 'c-change-set-fl-decl-start |
| 492 | (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP c-set-fl-decl-start) | 492 | (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP |
| 493 | c-change-set-fl-decl-start) | ||
| 493 | awk 'c-awk-extend-and-syntax-tablify-region) | 494 | awk 'c-awk-extend-and-syntax-tablify-region) |
| 494 | (c-lang-defvar c-before-font-lock-functions | 495 | (c-lang-defvar c-before-font-lock-functions |
| 495 | (let ((fs (c-lang-const c-before-font-lock-functions))) | 496 | (let ((fs (c-lang-const c-before-font-lock-functions))) |
| @@ -514,6 +515,27 @@ The functions are called even when font locking is disabled. | |||
| 514 | When the mode is initialized, these functions are called with | 515 | When the mode is initialized, these functions are called with |
| 515 | parameters \(point-min), \(point-max) and <buffer size>.") | 516 | parameters \(point-min), \(point-max) and <buffer size>.") |
| 516 | 517 | ||
| 518 | (c-lang-defconst c-before-context-fontification-functions | ||
| 519 | awk nil | ||
| 520 | t 'c-context-set-fl-decl-start) | ||
| 521 | ;; For documentation see the following c-lang-defvar of the same name. | ||
| 522 | ;; The value here may be a list of functions or a single function. | ||
| 523 | (c-lang-defvar c-before-context-fontification-functions | ||
| 524 | (let ((fs (c-lang-const c-before-context-fontification-functions))) | ||
| 525 | (if (listp fs) | ||
| 526 | fs | ||
| 527 | (list fs))) | ||
| 528 | "If non-nil, a list of functions called just before context (or | ||
| 529 | other non-change) fontification is done. Typically they will | ||
| 530 | extend the region. | ||
| 531 | |||
| 532 | These functions will be run in the order given. Each of them | ||
| 533 | takes 2 parameters, the BEG and END of the region to be | ||
| 534 | fontified. Point is undefined on both entry and exit. On entry, | ||
| 535 | the buffer will have been widened and match-data will have been | ||
| 536 | saved; the return value is a cons of the adjusted | ||
| 537 | region, (NEW-BEG . NEW-END).") | ||
| 538 | |||
| 517 | 539 | ||
| 518 | ;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK). | 540 | ;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK). |
| 519 | (c-lang-defconst c-at-vsemi-p-fn | 541 | (c-lang-defconst c-at-vsemi-p-fn |
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 01111d2b536..1bc0741b0aa 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -599,8 +599,8 @@ that requires a literal mode spec at compile time." | |||
| 599 | 599 | ||
| 600 | ;; Buffer local variables defining the region to be fontified by a font lock | 600 | ;; Buffer local variables defining the region to be fontified by a font lock |
| 601 | ;; after-change function. They are set in c-after-change to | 601 | ;; after-change function. They are set in c-after-change to |
| 602 | ;; after-change-function's BEG and END, and may be modified by a | 602 | ;; after-change-functions' BEG and END, and may be modified by functions in |
| 603 | ;; `c-before-font-lock-function'. | 603 | ;; `c-before-font-lock-functions'. |
| 604 | (defvar c-new-BEG 0) | 604 | (defvar c-new-BEG 0) |
| 605 | (make-variable-buffer-local 'c-new-BEG) | 605 | (make-variable-buffer-local 'c-new-BEG) |
| 606 | (defvar c-new-END 0) | 606 | (defvar c-new-END 0) |
| @@ -830,6 +830,35 @@ Note that the style variables are always made local to the buffer." | |||
| 830 | ; with a c-cpp-delimiter category property | 830 | ; with a c-cpp-delimiter category property |
| 831 | (setq c-old-EOM (point))) | 831 | (setq c-old-EOM (point))) |
| 832 | 832 | ||
| 833 | (defun c-extend-font-lock-region-for-macros (begg endd &optional old-len) | ||
| 834 | ;; Extend the region (BEGG ENDD) to cover all (possibly changed) | ||
| 835 | ;; preprocessor macros; return the cons (new-BEG . new-END). OLD-LEN should | ||
| 836 | ;; be either the old length parameter when called from an | ||
| 837 | ;; after-change-function, or nil otherwise. This defun uses the variables | ||
| 838 | ;; c-old-BOM, c-new-BOM. | ||
| 839 | ;; | ||
| 840 | ;; Point is undefined on both entry and exit to this function. The buffer | ||
| 841 | ;; will have been widened on entry. | ||
| 842 | (let (limits new-beg new-end) | ||
| 843 | (goto-char c-old-BOM) ; already set to old start of macro or begg. | ||
| 844 | (setq new-beg | ||
| 845 | (min begg | ||
| 846 | (if (setq limits (c-state-literal-at (point))) | ||
| 847 | (cdr limits) ; go forward out of any string or comment. | ||
| 848 | (point)))) | ||
| 849 | |||
| 850 | (goto-char endd) | ||
| 851 | (if (setq limits (c-state-literal-at (point))) | ||
| 852 | (goto-char (car limits))) ; go backward out of any string or comment. | ||
| 853 | (if (c-beginning-of-macro) | ||
| 854 | (c-end-of-macro)) | ||
| 855 | (setq new-end (max endd | ||
| 856 | (if old-len | ||
| 857 | (+ (- c-old-EOM old-len) (- endd begg)) | ||
| 858 | c-old-EOM) | ||
| 859 | (point))) | ||
| 860 | (cons new-beg new-end))) | ||
| 861 | |||
| 833 | (defun c-neutralize-CPP-line (beg end) | 862 | (defun c-neutralize-CPP-line (beg end) |
| 834 | ;; BEG and END bound a region, typically a preprocessor line. Put a | 863 | ;; BEG and END bound a region, typically a preprocessor line. Put a |
| 835 | ;; "punctuation" syntax-table property on syntactically obtrusive | 864 | ;; "punctuation" syntax-table property on syntactically obtrusive |
| @@ -886,26 +915,14 @@ Note that the style variables are always made local to the buffer." | |||
| 886 | ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! | 915 | ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! |
| 887 | ;; | 916 | ;; |
| 888 | ;; This function might make hidden buffer changes. | 917 | ;; This function might make hidden buffer changes. |
| 889 | (c-save-buffer-state (limits) | 918 | (c-save-buffer-state (new-bounds) |
| 890 | ;; First determine the region, (c-new-BEG c-new-END), which will get font | 919 | ;; First determine the region, (c-new-BEG c-new-END), which will get font |
| 891 | ;; locked. It might need "neutralizing". This region may not start | 920 | ;; locked. It might need "neutralizing". This region may not start |
| 892 | ;; inside a string, comment, or macro. | 921 | ;; inside a string, comment, or macro. |
| 893 | (goto-char c-old-BOM) ; already set to old start of macro or begg. | 922 | (setq new-bounds (c-extend-font-lock-region-for-macros |
| 894 | (setq c-new-BEG | 923 | c-new-BEG c-new-END old-len)) |
| 895 | (min c-new-BEG | 924 | (setq c-new-BEG (car new-bounds) |
| 896 | (if (setq limits (c-state-literal-at (point))) | 925 | c-new-END (cdr new-bounds)) |
| 897 | (cdr limits) ; go forward out of any string or comment. | ||
| 898 | (point)))) | ||
| 899 | |||
| 900 | (goto-char endd) | ||
| 901 | (if (setq limits (c-state-literal-at (point))) | ||
| 902 | (goto-char (car limits))) ; go backward out of any string or comment. | ||
| 903 | (if (c-beginning-of-macro) | ||
| 904 | (c-end-of-macro)) | ||
| 905 | (setq c-new-END (max c-new-END | ||
| 906 | (+ (- c-old-EOM old-len) (- endd begg)) | ||
| 907 | (point))) | ||
| 908 | |||
| 909 | ;; Clear all old relevant properties. | 926 | ;; Clear all old relevant properties. |
| 910 | (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) | 927 | (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) |
| 911 | (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter) | 928 | (c-clear-char-property-with-value c-new-BEG c-new-END 'category 'c-cpp-delimiter) |
| @@ -1015,6 +1032,11 @@ Note that the style variables are always made local to the buffer." | |||
| 1015 | c-get-state-before-change-functions)) | 1032 | c-get-state-before-change-functions)) |
| 1016 | )))) | 1033 | )))) |
| 1017 | 1034 | ||
| 1035 | (defvar c-in-after-change-fontification nil) | ||
| 1036 | (make-variable-buffer-local 'c-in-after-change-fontification) | ||
| 1037 | ;; A flag to prevent region expanding stuff being done twice for after-change | ||
| 1038 | ;; fontification. | ||
| 1039 | |||
| 1018 | (defun c-after-change (beg end old-len) | 1040 | (defun c-after-change (beg end old-len) |
| 1019 | ;; Function put on `after-change-functions' to adjust various caches | 1041 | ;; Function put on `after-change-functions' to adjust various caches |
| 1020 | ;; etc. Prefer speed to finesse here, since there will be an order | 1042 | ;; etc. Prefer speed to finesse here, since there will be an order |
| @@ -1066,63 +1088,113 @@ Note that the style variables are always made local to the buffer." | |||
| 1066 | ;; larger than (beg end). | 1088 | ;; larger than (beg end). |
| 1067 | (setq c-new-BEG beg | 1089 | (setq c-new-BEG beg |
| 1068 | c-new-END end) | 1090 | c-new-END end) |
| 1091 | (setq c-in-after-change-fontification t) | ||
| 1069 | (save-excursion | 1092 | (save-excursion |
| 1070 | (mapc (lambda (fn) | 1093 | (mapc (lambda (fn) |
| 1071 | (funcall fn beg end old-len)) | 1094 | (funcall fn beg end old-len)) |
| 1072 | c-before-font-lock-functions)))))) | 1095 | c-before-font-lock-functions)))))) |
| 1073 | 1096 | ||
| 1074 | (defun c-set-fl-decl-start (beg end old-len) | 1097 | (defun c-set-fl-decl-start (pos) |
| 1075 | ;; If the beginning of line containing c-new-BEG is in the middle of a | 1098 | ;; If the beginning of the line containing POS is in the middle of a "local" |
| 1076 | ;; "local" declaration (i.e. one which does not start outside of braces | 1099 | ;; declaration (i.e. one which does not start outside of braces enclosing |
| 1077 | ;; enclosing this pos, such as a struct), set c-new-BEG to (at most) the | 1100 | ;; POS, such as a struct), return the beginning of that declaration. |
| 1078 | ;; beginning of that declaration. Note that declarations, in this sense, | 1101 | ;; Otherwise return POS. Note that declarations, in this sense, can be |
| 1079 | ;; can be nested. c-new-BEG will be used later by c-font-lock-declarations. | 1102 | ;; nested. |
| 1080 | ;; | 1103 | ;; |
| 1081 | ;; This function is an element of c-before-font-lock-functions, being called | 1104 | ;; This function is called indirectly from font locking stuff - either from |
| 1082 | ;; (indirectly) from an after-change function. The after-change-functions' | 1105 | ;; c-after-change (to prepare for after-change font-lockng) or from font |
| 1083 | ;; parameters BEG, OLD and OLD-LEN are ignored here. | 1106 | ;; lock context (etc.) fontification. |
| 1084 | (when font-lock-mode | 1107 | (let ((lit-limits (c-literal-limits)) |
| 1085 | (goto-char (c-point 'bol c-new-BEG)) | 1108 | (new-pos pos) |
| 1086 | (let ((lit-limits (c-literal-limits)) | 1109 | bod-lim bo-decl) |
| 1087 | bod-lim bo-decl) | 1110 | (goto-char (c-point 'bol new-pos)) |
| 1088 | 1111 | (when lit-limits ; Comment or string. | |
| 1089 | (when lit-limits ; Comment or string. | 1112 | (goto-char (car lit-limits))) |
| 1090 | (goto-char (car lit-limits))) | 1113 | (setq bod-lim (max (- (point) 500) (point-min))) |
| 1091 | (setq bod-lim (max (- (point) 500) (point-min))) | 1114 | |
| 1092 | 1115 | (while | |
| 1093 | (while | 1116 | ;; Go to a less nested declaration each time round this loop. |
| 1094 | ;; Go to a less nested declaration each time round this loop. | 1117 | (and |
| 1095 | (and | 1118 | (eq (car (c-beginning-of-decl-1 bod-lim)) 'same) |
| 1096 | (eq (car (c-beginning-of-decl-1 bod-lim)) 'same) | 1119 | (progn (setq bo-decl (point)) |
| 1097 | (progn (setq bo-decl (point)) | 1120 | ;; Are we looking at a keyword such as "template" or |
| 1098 | ;; Are we looking at a keyword such as "template" or | 1121 | ;; "typedef" which can decorate a type, or the type itself? |
| 1099 | ;; "typedef" which can decorate a type, or the type itself? | 1122 | (when (or (looking-at c-prefix-spec-kwds-re) |
| 1100 | (when (or (looking-at c-prefix-spec-kwds-re) | 1123 | (c-forward-type t)) |
| 1101 | (c-forward-type t)) | 1124 | ;; We've found another candidate position. |
| 1102 | ;; We've found another candidate position. | 1125 | (setq new-pos (min new-pos bo-decl)) |
| 1103 | (setq c-new-BEG (min c-new-BEG bo-decl)) | 1126 | (goto-char bo-decl)) |
| 1104 | (goto-char bo-decl)) | 1127 | t) |
| 1105 | t) | 1128 | ;; Try and go out a level to search again. |
| 1106 | ;; Try and go out a level to search again. | 1129 | (progn |
| 1107 | (progn | 1130 | (c-backward-syntactic-ws bod-lim) |
| 1108 | (c-backward-syntactic-ws bod-lim) | 1131 | (or (memq (char-before) '(?\( ?\[)) |
| 1109 | (or (memq (char-before) '(?\( ?\[)) | 1132 | (and (eq (char-before) ?\<) |
| 1110 | (and (eq (char-before) ?\<) | 1133 | (eq (c-get-char-property |
| 1111 | (eq (c-get-char-property | 1134 | (1- (point)) 'syntax-table) |
| 1112 | (1- (point)) 'syntax-table) | 1135 | c-<-as-paren-syntax)))) |
| 1113 | c-<-as-paren-syntax)))) | 1136 | (not (bobp))) |
| 1114 | (not (bobp))) | 1137 | (backward-char)) |
| 1115 | (backward-char))))) ; back over (, [, <. | 1138 | new-pos)) ; back over (, [, <. |
| 1116 | 1139 | ||
| 1140 | (defun c-change-set-fl-decl-start (beg end old-len) | ||
| 1141 | ;; Set c-new-BEG to the beginning of a "local" declaration if it('s BOL) is | ||
| 1142 | ;; inside one. This is called from an after-change-function, but the | ||
| 1143 | ;; parameters BEG END and OLD-LEN are ignored. See `c-set-fl-decl-start' | ||
| 1144 | ;; for the detailed functionality. | ||
| 1145 | (if font-lock-mode | ||
| 1146 | (setq c-new-BEG (c-set-fl-decl-start c-new-BEG)))) | ||
| 1147 | |||
| 1148 | (defun c-context-set-fl-decl-start (beg end) | ||
| 1149 | ;; Return a cons (NEW-BEG . END), where NEW-BEG is the beginning of a | ||
| 1150 | ;; "local" declaration (BOL at) NEW is inside or BEG. See | ||
| 1151 | ;; `c-set-fl-decl-start' for the detailed functionality. | ||
| 1152 | (cons (c-set-fl-decl-start beg) end)) | ||
| 1153 | |||
| 1154 | (defvar c-standard-font-lock-fontify-region-function nil | ||
| 1155 | "Standard value of `font-lock-fontify-region-function'") | ||
| 1156 | |||
| 1157 | (defun c-font-lock-fontify-region (beg end &optional verbose) | ||
| 1158 | ;; Effectively advice around `font-lock-fontify-region' which extends the | ||
| 1159 | ;; region (BEG END), for example, to avoid context fontification chopping | ||
| 1160 | ;; off the start of the context. Do not do anything if it's already been | ||
| 1161 | ;; done (i.e. from and after-change fontification. An example (C++) where | ||
| 1162 | ;; this used to happen is this: | ||
| 1163 | ;; | ||
| 1164 | ;; template <typename T> | ||
| 1165 | ;; | ||
| 1166 | ;; | ||
| 1167 | ;; void myfunc(T* p) {} | ||
| 1168 | ;; | ||
| 1169 | ;; Type a space in the first blank line, and the fontification of the next | ||
| 1170 | ;; line was fouled up by context fontification. | ||
| 1171 | (let ((new-beg beg) (new-end end) new-region) | ||
| 1172 | (if c-in-after-change-fontification | ||
| 1173 | (setq c-in-after-change-fontification nil) | ||
| 1174 | (save-restriction | ||
| 1175 | (widen) | ||
| 1176 | (save-excursion | ||
| 1177 | (mapc (lambda (fn) | ||
| 1178 | (setq new-region (funcall fn new-beg new-end)) | ||
| 1179 | (setq new-beg (car new-region) new-end (cdr new-region))) | ||
| 1180 | c-before-context-fontification-functions)))) | ||
| 1181 | (funcall c-standard-font-lock-fontify-region-function | ||
| 1182 | new-beg new-end verbose))) | ||
| 1183 | |||
| 1117 | (defun c-after-font-lock-init () | 1184 | (defun c-after-font-lock-init () |
| 1118 | ;; Put on `font-lock-mode-hook'. | 1185 | ;; Put on `font-lock-mode-hook'. This function ensures our after-change |
| 1186 | ;; function will get excuted before the font-lock one. Amongst other | ||
| 1187 | ;; things. | ||
| 1119 | (remove-hook 'after-change-functions 'c-after-change t) | 1188 | (remove-hook 'after-change-functions 'c-after-change t) |
| 1120 | (add-hook 'after-change-functions 'c-after-change nil t)) | 1189 | (add-hook 'after-change-functions 'c-after-change nil t) |
| 1190 | (setq c-standard-font-lock-fontify-region-function | ||
| 1191 | (default-value 'font-lock-fontify-region-function))) | ||
| 1121 | 1192 | ||
| 1122 | (defun c-font-lock-init () | 1193 | (defun c-font-lock-init () |
| 1123 | "Set up the font-lock variables for using the font-lock support in CC Mode. | 1194 | "Set up the font-lock variables for using the font-lock support in CC Mode. |
| 1124 | This does not load the font-lock package. Use after | 1195 | This does not load the font-lock package. Use after |
| 1125 | `c-basic-common-init' and after cc-fonts has been loaded." | 1196 | `c-basic-common-init' and after cc-fonts has been loaded. |
| 1197 | This function is called from `c-common-init', once per mode initialization." | ||
| 1126 | 1198 | ||
| 1127 | (set (make-local-variable 'font-lock-defaults) | 1199 | (set (make-local-variable 'font-lock-defaults) |
| 1128 | `(,(if (c-major-mode-is 'awk-mode) | 1200 | `(,(if (c-major-mode-is 'awk-mode) |
| @@ -1136,6 +1208,10 @@ This does not load the font-lock package. Use after | |||
| 1136 | c-beginning-of-syntax | 1208 | c-beginning-of-syntax |
| 1137 | (font-lock-mark-block-function | 1209 | (font-lock-mark-block-function |
| 1138 | . c-mark-function))) | 1210 | . c-mark-function))) |
| 1211 | |||
| 1212 | (make-local-variable 'font-lock-fontify-region-function) | ||
| 1213 | (setq font-lock-fontify-region-function 'c-font-lock-fontify-region) | ||
| 1214 | |||
| 1139 | (if (featurep 'xemacs) | 1215 | (if (featurep 'xemacs) |
| 1140 | (make-local-hook 'font-lock-mode-hook)) | 1216 | (make-local-hook 'font-lock-mode-hook)) |
| 1141 | (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t)) | 1217 | (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t)) |