diff options
Diffstat (limited to 'lisp/progmodes/cc-mode.el')
-rw-r--r-- | lisp/progmodes/cc-mode.el | 171 |
1 files changed, 132 insertions, 39 deletions
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 057d292246f..f9435c9ceee 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,10 +596,15 @@ 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) - "Do the necessary initialization for the syntax handling routines -and the line breaking/filling code. Intended to be used by other -packages that embed CC Mode. + "Initialize the syntax handling routines and the line breaking/filling code. +Intended to be used by other packages that embed CC Mode. MODE is the CC Mode flavor to set up, e.g. `c-mode' or `java-mode'. DEFAULT-STYLE tells which indentation style to install. It has the @@ -746,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 @@ -1403,7 +1443,7 @@ Note that the style variables are always made local to the buffer." (memq (char-after) c-string-delims)) (c-clear-syn-tab (point))))) (c-clear-syn-tab (point))) - (t (c-benign-error "c-remove-string-fences: wrong position"))))) + (t (c-benign-error "c-remove-string-fences: Wrong position"))))) (defun c-before-change-check-unbalanced-strings (beg end) ;; If BEG or END is inside an unbalanced string, remove the syntax-table @@ -1649,7 +1689,7 @@ Note that the style variables are always made local to the buffer." (and (memq (char-before) c-string-delims) (not (nth 4 s))))) ; Check we're actually out of the ; comment. not stuck at EOB - (unless + (unless (and c-ml-string-opener-re (c-maybe-re-mark-ml-string)) (if (c-unescaped-nls-in-string-p (1- (point))) @@ -1951,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 @@ -1970,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) @@ -2152,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) @@ -2550,17 +2636,24 @@ This function is called from `c-common-init', once per mode initialization." At the time of call, point is just after the newly inserted CHAR. -When CHAR is \", t will be returned unless the \" is marked with -a string fence syntax-table text property. For other characters, -the default value of `electric-pair-inhibit-predicate' is called -and its value returned. +When CHAR is \" and not within a comment, t will be returned if +the quotes on the current line are already balanced (i.e. if the +last \" is not marked with a string fence syntax-table text +property). For other cases, the default value of +`electric-pair-inhibit-predicate' is called and its value +returned. This function is the appropriate value of `electric-pair-inhibit-predicate' for CC Mode modes, which mark invalid strings with such a syntax table text property on the opening \" and the next unescaped end of line." - (if (eq char ?\") - (not (equal (get-text-property (1- (point)) 'c-fl-syn-tab) '(15))) + (if (and (eq char ?\") + (not (memq (cadr (c-semi-pp-to-literal (1- (point)))) '(c c++)))) + (let ((last-quote (save-match-data + (save-excursion + (goto-char (c-point 'eoll)) + (search-backward "\""))))) + (not (equal (c-get-char-property last-quote 'c-fl-syn-tab) '(15)))) (funcall (default-value 'electric-pair-inhibit-predicate) char))) @@ -2568,17 +2661,17 @@ opening \" and the next unescaped end of line." (defvar c-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table c)) - "Syntax table used in c-mode buffers.") + "Syntax table used in `c-mode' buffers.") (defvar c-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in c-mode buffers.") + "Keymap used in `c-mode' buffers.") ;; Add bindings which are only useful for C. (define-key c-mode-map "\C-c\C-e" 'c-macro-expand) -(easy-menu-define c-c-menu c-mode-map "C Mode Commands" +(easy-menu-define c-c-menu c-mode-map "C Mode Commands." (cons "C" (c-lang-const c-mode-menu c))) ;; In XEmacs >= 21.5 modes should add their own entries to @@ -2617,7 +2710,7 @@ opening \" and the next unescaped end of line." "Major mode for editing C code. To submit a problem report, enter `\\[c-submit-bug-report]' from a -c-mode buffer. This automatically sets up a mail buffer with version +`c-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. @@ -2701,7 +2794,7 @@ the code is C or C++ and based on that chooses whether to enable (define-key c++-mode-map "<" 'c-electric-lt-gt) (define-key c++-mode-map ">" 'c-electric-lt-gt) -(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" +(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands." (cons "C++" (c-lang-const c-mode-menu c++))) ;;;###autoload @@ -2738,16 +2831,16 @@ Key bindings: (defvar objc-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table objc)) - "Syntax table used in objc-mode buffers.") + "Syntax table used in `objc-mode' buffers.") (defvar objc-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in objc-mode buffers.") + "Keymap used in `objc-mode' buffers.") ;; Add bindings which are only useful for Objective-C. (define-key objc-mode-map "\C-c\C-e" 'c-macro-expand) -(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" +(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands." (cons "ObjC" (c-lang-const c-mode-menu objc))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode)) @@ -2756,7 +2849,7 @@ Key bindings: (define-derived-mode objc-mode prog-mode "ObjC" "Major mode for editing Objective C code. To submit a problem report, enter `\\[c-submit-bug-report]' from an -objc-mode buffer. This automatically sets up a mail buffer with +`objc-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. @@ -2785,12 +2878,12 @@ Key bindings: (defvar java-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table java)) - "Syntax table used in java-mode buffers.") + "Syntax table used in `java-mode' buffers.") (defvar java-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in java-mode buffers.") + "Keymap used in `java-mode' buffers.") ;; Add bindings which are only useful for Java. ;; Regexp trying to describe the beginning of a Java top-level @@ -2800,7 +2893,7 @@ Key bindings: (defconst c-Java-defun-prompt-regexp "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()\^?=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\<throws\\>\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f\v]*\\)+\\)?\\s-*") -(easy-menu-define c-java-menu java-mode-map "Java Mode Commands" +(easy-menu-define c-java-menu java-mode-map "Java Mode Commands." (cons "Java" (c-lang-const c-mode-menu java))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode)) @@ -2809,7 +2902,7 @@ Key bindings: (define-derived-mode java-mode prog-mode "Java" "Major mode for editing Java code. To submit a problem report, enter `\\[c-submit-bug-report]' from a -java-mode buffer. This automatically sets up a mail buffer with +`java-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. @@ -2836,15 +2929,15 @@ Key bindings: (defvar idl-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table idl)) - "Syntax table used in idl-mode buffers.") + "Syntax table used in `idl-mode' buffers.") (defvar idl-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in idl-mode buffers.") + "Keymap used in `idl-mode' buffers.") ;; Add bindings which are only useful for IDL. -(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" +(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands." (cons "IDL" (c-lang-const c-mode-menu idl))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode)) @@ -2853,7 +2946,7 @@ Key bindings: (define-derived-mode idl-mode prog-mode "IDL" "Major mode for editing CORBA's IDL, PSDL and CIDL code. To submit a problem report, enter `\\[c-submit-bug-report]' from an -idl-mode buffer. This automatically sets up a mail buffer with +`idl-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. @@ -2879,16 +2972,16 @@ Key bindings: (defvar pike-mode-syntax-table (funcall (c-lang-const c-make-mode-syntax-table pike)) - "Syntax table used in pike-mode buffers.") + "Syntax table used in `pike-mode' buffers.") (defvar pike-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in pike-mode buffers.") + "Keymap used in `pike-mode' buffers.") ;; Additional bindings. (define-key pike-mode-map "\C-c\C-e" 'c-macro-expand) -(easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands" +(easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands." (cons "Pike" (c-lang-const c-mode-menu pike))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode)) @@ -2898,7 +2991,7 @@ Key bindings: (define-derived-mode pike-mode prog-mode "Pike" "Major mode for editing Pike code. To submit a problem report, enter `\\[c-submit-bug-report]' from a -pike-mode buffer. This automatically sets up a mail buffer with +`pike-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. @@ -2932,7 +3025,7 @@ Key bindings: (defvar awk-mode-map (let ((map (c-make-inherited-keymap))) map) - "Keymap used in awk-mode buffers.") + "Keymap used in `awk-mode' buffers.") ;; Add bindings which are only useful for awk. (define-key awk-mode-map "#" 'self-insert-command);Overrides electric parent binding. (define-key awk-mode-map "/" 'self-insert-command);Overrides electric parent binding. @@ -2945,7 +3038,7 @@ Key bindings: (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun) (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun) -(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" +(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands." (cons "AWK" (c-lang-const c-mode-menu awk))) ;; (require 'cc-awk) brings these in. @@ -2956,7 +3049,7 @@ Key bindings: (define-derived-mode awk-mode prog-mode "AWK" "Major mode for editing AWK code. To submit a problem report, enter `\\[c-submit-bug-report]' from an -awk-mode buffer. This automatically sets up a mail buffer with version +`awk-mode' buffer. This automatically sets up a mail buffer with version information already added. You just need to add a description of the problem, including a reproducible test case, and send the message. |