summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/cc-mode.el')
-rw-r--r--lisp/progmodes/cc-mode.el171
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.