Merge changes from CEDET upstream.
[bpt/emacs.git] / lisp / cedet / semantic.el
index c899988..373864a 100644 (file)
@@ -1,6 +1,6 @@
 ;;; semantic.el --- Semantic buffer evaluator.
 
-;; Copyright (C) 1999-201 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2012 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: syntax tools
@@ -38,7 +38,7 @@
 (require 'semantic/tag)
 (require 'semantic/lex)
 
-(defvar semantic-version "2.0"
+(defvar semantic-version "2.1beta"
   "Current version of Semantic.")
 
 (declare-function inversion-test "inversion")
@@ -274,6 +274,7 @@ setup to use Semantic."
     (python-mode . wisent-python-default-setup)
     (scheme-mode . semantic-default-scheme-setup)
     (srecode-template-mode . srecode-template-setup-parser)
+    (texinfo-mode . semantic-default-texi-setup)
     (makefile-automake-mode . semantic-default-make-setup)
     (makefile-gmake-mode . semantic-default-make-setup)
     (makefile-makepp-mode . semantic-default-make-setup)
@@ -318,6 +319,11 @@ a parse of the buffer.")
   "Return non-nil if the current buffer was set up for parsing."
   semantic-new-buffer-fcn-was-run)
 
+(defsubst semantic-error-if-unparsed ()
+  "Raise an error if current buffer was not parsed by Semantic."
+  (unless semantic-new-buffer-fcn-was-run
+    (error "Buffer was not parsed by Semantic.")))
+
 (defsubst semantic--umatched-syntax-needs-refresh-p  ()
   "Return non-nil if the unmatched syntax cache needs a refresh.
 That is, if it is dirty or if the current parse tree isn't up to date."
@@ -344,7 +350,7 @@ to use Semantic, and `semantic-init-hook' is run."
     ;; don't go along for the ride.
     (add-hook 'clone-indirect-buffer-hook 'semantic-clear-toplevel-cache
              nil t)
-    ;; Specify that this function has done it's work.  At this point
+    ;; Specify that this function has done its work.  At this point
     ;; we can consider that semantic is active in this buffer.
     (setq semantic-new-buffer-fcn-was-run t)
     ;; Here are some buffer local variables we can initialize ourselves
@@ -378,10 +384,8 @@ Do not set this yourself.  Call `semantic-debug'.")
 
 (defun semantic-elapsed-time (start end)
   "Copied from elp.el.  Was `elp-elapsed-time'.
-Argument START and END bound the time being calculated."
-  (+ (* (- (car end) (car start)) 65536.0)
-     (- (car (cdr end)) (car (cdr start)))
-     (/ (- (car (cdr (cdr end))) (car (cdr (cdr start)))) 1000000.0)))
+Arguments START and END bound the time being calculated."
+  (float-time (time-subtract end start)))
 
 (defun bovinate (&optional clear)
   "Parse the current buffer.  Show output in a temp buffer.
@@ -433,13 +437,13 @@ will be silently ignored.
 
 Optional arguments:
 NONTERMINAL is the rule to start parsing at.
-DEPTH specifies the lexical depth to descend for parser that use
+DEPTH specifies the lexical depth to descend for parsers that use
 lexical analysis as their first step.
 RETURNONERROR specifies that parsing should stop on the first
 unmatched syntax encountered.  When nil, parsing skips the syntax,
 adding it to the unmatched syntax cache.
 
-Must return a list of semantic tags wich have been cooked
+Must return a list of semantic tags which have been cooked
 \(repositioned properly) but which DO NOT HAVE OVERLAYS associated
 with them.  When overloading this function, use `semantic--tag-expand'
 to cook raw tags.")
@@ -552,14 +556,14 @@ is requested."
   )
 
 (defvar semantic-working-type 'percent
-  "*The type of working message to use when parsing.
+  "The type of working message to use when parsing.
 'percent means we are doing a linear parse through the buffer.
 'dynamic means we are reparsing specific tags.")
 (semantic-varalias-obsolete 'semantic-bovination-working-type
                            'semantic-working-type "23.2")
 
 (defvar semantic-minimum-working-buffer-size (* 1024 5)
-  "*The minimum size of a buffer before working messages are displayed.
+  "The minimum size of a buffer before working messages are displayed.
 Buffers smaller than this will parse silently.
 Buffers larger than this will display the working progress bar.")
 
@@ -625,16 +629,18 @@ was marked unparseable, then do nothing, and return the cache."
 
 ;;;; Parse the whole system.
      ((semantic-parse-tree-needs-rebuild-p)
-      ;; Use Emacs' built-in progress-reporter
-      (let ((semantic--progress-reporter
-            (and (>= (point-max) semantic-minimum-working-buffer-size)
-                 (eq semantic-working-type 'percent)
-                 (make-progress-reporter
-                  (semantic-parser-working-message (buffer-name))
-                  0 100))))
-       (setq res (semantic-parse-region (point-min) (point-max)))
-       (if semantic--progress-reporter
-           (progress-reporter-done semantic--progress-reporter)))
+      ;; Use Emacs's built-in progress-reporter (only interactive).
+      (if noninteractive
+         (setq res (semantic-parse-region (point-min) (point-max)))
+       (let ((semantic--progress-reporter
+              (and (>= (point-max) semantic-minimum-working-buffer-size)
+                   (eq semantic-working-type 'percent)
+                   (make-progress-reporter
+                    (semantic-parser-working-message (buffer-name))
+                    0 100))))
+         (setq res (semantic-parse-region (point-min) (point-max)))
+         (if semantic--progress-reporter
+             (progress-reporter-done semantic--progress-reporter))))
 
       ;; Clear the caches when we see there were no errors.
       ;; But preserve the unmatched syntax cache and warnings!
@@ -682,7 +688,7 @@ Does nothing if the current buffer doesn't need reparsing."
                    (save-excursion (semantic-fetch-tags))
                    nil)
              ;; If we are here, it is because the lexical step failed,
-             ;; proably due to unterminated lists or something like that.
+             ;; probably due to unterminated lists or something like that.
 
              ;; We do nothing, and just wait for the next idle timer
              ;; to go off.  In the meantime, remember this, and make sure
@@ -764,7 +770,7 @@ This function returns semantic tags without overlays."
       ;; Designated to ignore.
       (setq stream (car nontermsym))
       (if stream
-         ;; Use Emacs' built-in progress reporter:
+         ;; Use Emacs's built-in progress reporter:
          (and (boundp 'semantic--progress-reporter)
               semantic--progress-reporter
               (eq semantic-working-type 'percent)
@@ -906,75 +912,91 @@ Throw away all the old tags, and recreate the tag database."
   ;; Edit Tags submenu:
   (define-key edit-menu [semantic-analyze-possible-completions]
     '(menu-item "List Completions" semantic-analyze-possible-completions
+               :enable (semantic-active-p)
                :help "Display a list of completions for the tag at point"))
   (define-key edit-menu [semantic-complete-analyze-inline]
     '(menu-item "Complete Tag Inline" semantic-complete-analyze-inline
+               :enable (semantic-active-p)
                :help "Display inline completion for the tag at point"))
   (define-key edit-menu [semantic-completion-separator]
     '("--"))
   (define-key edit-menu [senator-transpose-tags-down]
     '(menu-item "Transpose Tags Down" senator-transpose-tags-down
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Transpose the current tag and the next tag"))
   (define-key edit-menu [senator-transpose-tags-up]
     '(menu-item "Transpose Tags Up" senator-transpose-tags-up
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Transpose the current tag and the previous tag"))
   (define-key edit-menu [semantic-edit-separator]
     '("--"))
   (define-key edit-menu [senator-yank-tag]
     '(menu-item "Yank Tag" senator-yank-tag
-               :active (not (ring-empty-p senator-tag-ring))
+               :enable (not (ring-empty-p senator-tag-ring))
                :help "Yank the head of the tag ring into the buffer"))
   (define-key edit-menu [senator-copy-tag-to-register]
     '(menu-item "Copy Tag To Register" senator-copy-tag-to-register
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Yank the head of the tag ring into the buffer"))
   (define-key edit-menu [senator-copy-tag]
     '(menu-item "Copy Tag" senator-copy-tag
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Copy the current tag to the tag ring"))
   (define-key edit-menu [senator-kill-tag]
     '(menu-item "Kill Tag" senator-kill-tag
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Kill the current tag, and copy it to the tag ring"))
 
   ;; Navigate Tags submenu:
   (define-key navigate-menu [senator-narrow-to-defun]
     '(menu-item "Narrow to Tag" senator-narrow-to-defun
-               :active (semantic-current-tag)
+               :enable (and (semantic-active-p)
+                            (semantic-current-tag))
                :help "Narrow the buffer to the bounds of the current tag"))
   (define-key navigate-menu [semantic-narrow-to-defun-separator]
     '("--"))
   (define-key navigate-menu [semantic-symref-symbol]
     '(menu-item "Find Tag References..." semantic-symref-symbol
+               :enable (semantic-active-p)
                :help "Read a tag and list the references to it"))
   (define-key navigate-menu [semantic-complete-jump]
     '(menu-item "Find Tag Globally..." semantic-complete-jump
+               :enable (semantic-active-p)
                :help "Read a tag name and find it in the current project"))
   (define-key navigate-menu [semantic-complete-jump-local-members]
     '(menu-item "Find Local Members ..." semantic-complete-jump-local-members
+               :enable (semantic-active-p)
                :help "Read a tag name and find a local member with that name"))
   (define-key navigate-menu [semantic-complete-jump-local]
     '(menu-item "Find Tag in This Buffer..." semantic-complete-jump-local
+               :enable (semantic-active-p)
                :help "Read a tag name and find it in this buffer"))
   (define-key navigate-menu [semantic-navigation-separator]
     '("--"))
   (define-key navigate-menu [senator-go-to-up-reference]
     '(menu-item "Parent Tag" senator-go-to-up-reference
-               :help "Navigate up one reference by tag."))
+               :enable (semantic-active-p)
+               :help "Navigate up one reference by tag"))
   (define-key navigate-menu [senator-next-tag]
     '(menu-item "Next Tag" senator-next-tag
+               :enable (semantic-active-p)
                :help "Go to the next tag"))
   (define-key navigate-menu [senator-previous-tag]
     '(menu-item "Previous Tag" senator-previous-tag
+               :enable (semantic-active-p)
                :help "Go to the previous tag"))
 
   ;; Top level menu items:
   (define-key cedet-menu-map [semantic-force-refresh]
     '(menu-item "Reparse Buffer" semantic-force-refresh
-               :help "Force a full reparse of the current buffer."
-               :visible semantic-mode))
+               :help "Force a full reparse of the current buffer"
+               :visible semantic-mode
+               :enable (semantic-active-p)))
   (define-key cedet-menu-map [semantic-edit-menu]
     `(menu-item "Edit Tags" ,edit-menu
                :visible semantic-mode))
@@ -988,6 +1010,12 @@ Throw away all the old tags, and recreate the tag database."
                :help "Highlight the tag at point"
                :visible semantic-mode
                :button (:toggle . global-semantic-highlight-func-mode)))
+  (define-key cedet-menu-map [global-semantic-stickyfunc-mode]
+    '(menu-item "Stick Top Tag to Headerline" global-semantic-stickyfunc-mode
+               :help "Stick the tag scrolled off the top of the buffer into the header line"
+               :visible semantic-mode
+               :button (:toggle . (bound-and-true-p
+                                   global-semantic-stickyfunc-mode))))
   (define-key cedet-menu-map [global-semantic-decoration-mode]
     '(menu-item "Decorate Tags" global-semantic-decoration-mode
                :help "Decorate tags based on tag attributes"
@@ -1017,7 +1045,7 @@ Throw away all the old tags, and recreate the tag database."
                :visible semantic-mode
                :button (:toggle . global-semanticdb-minor-mode))))
 
-;; The `semantic-mode' command, in conjuction with the
+;; The `semantic-mode' command, in conjunction with the
 ;; `semantic-default-submodes' variable, toggles Semantic's various
 ;; auxiliary minor modes.
 
@@ -1033,7 +1061,12 @@ Prevent this load system from loading files in twice.")
     global-semantic-idle-scheduler-mode
     global-semanticdb-minor-mode
     global-semantic-idle-summary-mode
-    global-semantic-mru-bookmark-mode)
+    global-semantic-mru-bookmark-mode
+    global-cedet-m3-minor-mode
+    global-semantic-idle-local-symbol-highlight-mode
+    global-semantic-highlight-edits-mode
+    global-semantic-show-unmatched-syntax-mode
+    global-semantic-show-parser-state-mode)
   "List of auxiliary minor modes in the Semantic package.")
 
 ;;;###autoload
@@ -1050,15 +1083,27 @@ The possible elements of this list include the following:
  `global-semantic-highlight-func-mode' - Highlight the current tag.
  `global-semantic-stickyfunc-mode'     - Show current fun in header line.
  `global-semantic-mru-bookmark-mode'   - Provide `switch-to-buffer'-like
-                                         keybinding for tag names."
+                                         keybinding for tag names.
+ `global-cedet-m3-minor-mode'          - A mouse 3 context menu.
+ `global-semantic-idle-local-symbol-highlight-mode' - Highlight references
+                                         of the symbol under point.
+The following modes are more targeted at people who want to see
+ some internal information of the semantic parser in action:
+ `global-semantic-highlight-edits-mode' - Visualize incremental parser by
+                                         highlighting not-yet parsed changes.
+ `global-semantic-show-unmatched-syntax-mode' - Highlight unmatched lexical
+                                         syntax tokens.
+ `global-semantic-show-parser-state-mode' - Display the parser cache state."
   :group 'semantic
   :type `(set ,@(mapcar (lambda (c) (list 'const c))
                        semantic-submode-list)))
 
 ;;;###autoload
 (define-minor-mode semantic-mode
-  "Toggle Semantic mode.
-With ARG, turn Semantic mode on if ARG is positive, off otherwise.
+  "Toggle parser features (Semantic mode).
+With a prefix argument ARG, enable Semantic mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+Semantic mode if ARG is omitted or nil.
 
 In Semantic mode, Emacs parses the buffers you visit for their
 semantic content.  This information is used by a variety of
@@ -1095,16 +1140,27 @@ Semantic mode.
        (dolist (b (buffer-list))
          (with-current-buffer b
            (semantic-new-buffer-fcn))))
-    ;; Disable all Semantic features.
+    ;; Disable Semantic features.  Removing everything Semantic has
+    ;; introduced in the buffer is pretty much futile, but we have to
+    ;; clean the hooks and delete Semantic-related overlays, so that
+    ;; Semantic can be re-activated cleanly.
     (remove-hook 'mode-local-init-hook 'semantic-new-buffer-fcn)
     (remove-hook 'completion-at-point-functions
                 'semantic-completion-at-point-function)
+    (remove-hook 'after-change-functions
+                'semantic-change-function)
     (define-key cedet-menu-map [cedet-menu-separator] nil)
     (define-key cedet-menu-map [semantic-options-separator] nil)
     ;; FIXME: handle semanticdb-load-ebrowse-caches
     (dolist (mode semantic-submode-list)
       (if (and (boundp mode) (eval mode))
-         (funcall mode -1)))))
+         (funcall mode -1)))
+    ;; Unlink buffer and clear cache
+    (semantic--tag-unlink-cache-from-buffer)
+    (setq semantic--buffer-cache nil)
+    ;; Make sure we run the setup function if Semantic gets
+    ;; re-activated.
+    (setq semantic-new-buffer-fcn-was-run nil)))
 
 (defun semantic-completion-at-point-function ()
   'semantic-ia-complete-symbol)
@@ -1141,6 +1197,11 @@ minor mode can be turned on only if semantic feature is available and
 the current buffer was set up for parsing.  Return non-nil if the
 minor mode is enabled." t nil)
 
+(autoload 'global-semantic-idle-local-symbol-highlight-mode "semantic/idle"
+  "Highlight the tag and symbol references of the symbol under point.
+Call `semantic-analyze-current-context' to find the reference tag.
+Call `semantic-symref-hits-in-region' to identify local references." t nil)
+
 (autoload 'srecode-template-setup-parser "srecode/srecode-template"
   "Set up buffer for parsing SRecode template files." t nil)