Update CEDET from upstream.
[bpt/emacs.git] / lisp / cedet / semantic / db-typecache.el
index a0827ee..94999a2 100644 (file)
@@ -1,6 +1,6 @@
-;;; db-typecache.el --- Manage Datatypes
+;;; semantic/db-typecache.el --- Manage Datatypes
 
-;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
 
 ;; Author: Eric M. Ludlam <eric@siege-engine.com>
 
 ;;
 ;; It is likely this feature will only be needed for C/C++.
 
+(require 'semantic)
 (require 'semantic/db)
 (require 'semantic/db-find)
-(require 'semantic/tag-ls)
 (require 'semantic/analyze/fcn)
-(require 'semantic/scope)
+
+;; For semantic-find-tags-by-* macros
+(eval-when-compile (require 'semantic/find))
 
 (declare-function data-debug-insert-thing "data-debug")
 (declare-function data-debug-new-buffer "data-debug")
+(declare-function semantic-sort-tags-by-name-then-type-increasing "semantic/sort")
+(declare-function semantic-scope-tag-clone-with-scope "semantic/scope")
 
 ;;; Code:
 
 \f
 ;;; TABLE TYPECACHE
+;;;###autoload
 (defclass semanticdb-typecache ()
   ((filestream :initform nil
               :documentation
@@ -92,7 +97,7 @@ Said object must support `semantic-reset' methods.")
   (when (semantic-find-tags-by-class 'type new-tags)
     ;; Reset our index
     (oset tc filestream nil)
-    t ;; Return true, our core file tags have changed in a relavant way.
+    t ;; Return true, our core file tags have changed in a relevant way.
     )
 
   ;; NO CODE HERE
@@ -106,7 +111,7 @@ Said object must support `semantic-reset' methods.")
         )
     (object-add-to-list cache 'dependants dep)))
 
-(defun semanticdb-typecache-length(thing)
+(defun semanticdb-typecache-length (thing)
   "How long is THING?
 Debugging function."
   (cond ((semanticdb-typecache-child-p thing)
@@ -149,6 +154,7 @@ If there is no table, create one, and fill it in."
 ;; Unlike file based caches, this one is a bit simpler, and just needs
 ;; to get reset when a table gets updated.
 
+;;;###autoload
 (defclass semanticdb-database-typecache (semanticdb-abstract-db-cache)
   ((stream :initform nil
           :documentation
@@ -211,6 +217,14 @@ Adds a filename and copies the tags."
    (semanticdb-full-filename table)
    tags))
 
+(defun semanticdb-typecache-faux-namespace (name members)
+  "Create a new namespace tag with NAME and a set of MEMBERS.
+The new tag will be a faux tag, used as a placeholder in a typecache."
+  (let ((tag (semantic-tag-new-type name "namespace" members nil)))
+    ;; Make sure we mark this as a fake tag.
+    (semantic-tag-set-faux tag)
+    tag))
+
 (defun semanticdb-typecache-merge-streams (cache1 cache2)
   "Merge into CACHE1 and CACHE2 together.  The Caches will be merged in place."
   (if (or (and (not cache1) (not cache2))
@@ -225,6 +239,7 @@ Adds a filename and copies the tags."
 
     ;; Assume we always have datatypes, as this typecache isn't really
     ;; useful without a typed language.
+    (require 'semantic/sort)
     (let ((S (semantic-sort-tags-by-name-then-type-increasing
              ;; I used to use append, but it copied cache1 but not cache2.
              ;; Since sort was permuting cache2, I already had to make sure
@@ -249,23 +264,22 @@ Adds a filename and copies the tags."
            (setq ans (cons next ans))
          ;; ELSE - We have a NAME match.
          (setq type (semantic-tag-type next))
-         (if (semantic-tag-of-type-p prev type) ; Are they the same datatype
+         (if (or (semantic-tag-of-type-p prev type) ; Are they the same datatype
+                 (semantic-tag-faux-p prev)
+                 (semantic-tag-faux-p next) ; or either a faux tag?
+                 )
              ;; Same Class, we can do a merge.
              (cond
               ((and (semantic-tag-of-class-p next 'type)
                     (string= type "namespace"))
                ;; Namespaces - merge the children together.
                (setcar ans
-                       (semantic-tag-new-type
+                       (semanticdb-typecache-faux-namespace
                         (semantic-tag-name prev) ; - they are the same
-                        "namespace"    ; - we know this as fact
                         (semanticdb-typecache-merge-streams
                          (semanticdb-typecache-safe-tag-members prev)
                          (semanticdb-typecache-safe-tag-members next))
-                        nil            ; - no attributes
                         ))
-               ;; Make sure we mark this as a fake tag.
-               (semantic-tag-set-faux (car ans))
                )
               ((semantic-tag-prototype-p next)
                ;; NEXT is a prototype... so keep previous.
@@ -292,6 +306,12 @@ Adds a filename and copies the tags."
 ;;; Refresh / Query API
 ;;
 ;; Queries that can be made for the typecache.
+(define-overloadable-function semanticdb-expand-nested-tag (tag)
+  "Expand TAG from fully qualified names.
+If TAG has fully qualified names, expand it to a series of nested
+namespaces instead."
+  tag)
+
 (defmethod semanticdb-typecache-file-tags ((table semanticdb-abstract-table))
   "No tags available from non-file based tables."
   nil)
@@ -306,10 +326,13 @@ all included files."
 
     ;; Make sure our file-tags list is up to date.
     (when (not (oref cache filestream))
-      (let ((tags  (semantic-find-tags-by-class 'type table)))
+      (let ((tags  (semantic-find-tags-by-class 'type table))
+           (exptags nil))
        (when tags
          (setq tags (semanticdb-typecache-safe-tag-list tags table))
-         (oset cache filestream (semanticdb-typecache-merge-streams tags nil)))))
+         (dolist (T tags)
+           (push (semanticdb-expand-nested-tag T) exptags))
+         (oset cache filestream (semanticdb-typecache-merge-streams exptags nil)))))
 
     ;; Return our cache.
     (oref cache filestream)
@@ -345,7 +368,7 @@ a master list."
                  (semanticdb-typecache-merge-streams
                   incstream
                   ;; Getting the cache from this table will also cause this
-                  ;; file to update it's cache from it's decendants.
+                  ;; file to update its cache from its descendants.
                   ;;
                   ;; In theory, caches are only built for most includes
                   ;; only once (in the loop before this one), so this ends
@@ -366,6 +389,7 @@ a master list."
 
 ;;; Search Routines
 ;;
+;;;###autoload
 (define-overloadable-function semanticdb-typecache-find (type &optional path find-file-match)
   "Search the typecache for TYPE in PATH.
 If type is a string, split the string, and search for the parts.
@@ -376,19 +400,23 @@ FIND-FILE-MATCH is non-nil to force all found tags to be loaded into a buffer.")
 (defun semanticdb-typecache-find-default (type &optional path find-file-match)
   "Default implementation of `semanticdb-typecache-find'.
 TYPE is the datatype to find.
-PATH is the search path.. which should be one table object.
+PATH is the search path, which should be one table object.
 If FIND-FILE-MATCH is non-nil, then force the file belonging to the
 found tag to be loaded."
-  (semanticdb-typecache-find-method (or path semanticdb-current-table)
-                                   type find-file-match))
+  (if (not (and (featurep 'semantic/db) semanticdb-current-database))
+      nil ;; No DB, no search
+    (save-excursion
+      (semanticdb-typecache-find-method (or path semanticdb-current-table)
+                                       type find-file-match))))
 
 (defun semanticdb-typecache-find-by-name-helper (name table)
   "Find the tag with NAME in TABLE, which is from a typecache.
 If more than one tag has NAME in TABLE, we will prefer the tag that
 is of class 'type."
   (let* ((names (semantic-find-tags-by-name name table))
-        (types (semantic-find-tags-by-class 'type names)))
-    (or (car-safe types) (car-safe names))))
+        (nmerge (semanticdb-typecache-merge-streams names nil))
+        (types (semantic-find-tags-by-class 'type nmerge)))
+    (or (car-safe types) (car-safe nmerge))))
 
 (defmethod semanticdb-typecache-find-method ((table semanticdb-abstract-table)
                                             type find-file-match)
@@ -445,7 +473,7 @@ found tag to be loaded."
        ;;       find a type/namespace because everything else is excluded.
 
        ;; If this is not the last entry from the list, then it
-       ;; must be a type or a namespace.  Lets double check.
+       ;; must be a type or a namespace.  Let's double check.
        (when (cdr type)
 
          ;; From above, there is only one tag in ans, and we prefer
@@ -455,6 +483,11 @@ found tag to be loaded."
            (setq ans nil)))
        )
 
+      ;; The typecache holds all the known types and elements.  Some databases
+      ;; may provide tags that are simplified by name, and are proxies.  These
+      ;; proxies must be resolved in order to extract type members.
+      (setq ans (semantic-tag-resolve-proxy ans))
+
       (push ans calculated-scope)
 
       ;; Track most recent file.
@@ -483,7 +516,7 @@ found tag to be loaded."
          ;; This won't liven up the tag since we have a copy, but
          ;; we ought to be able to get there and go to the right line.
          (find-file-noselect lastfile)
-       ;; We don't want to find-file match, so instead lets
+       ;; We don't want to find-file match, so instead let's
        ;; push the filename onto the return tag.
        (when lastans
          (setq lastans (semantic-tag-copy lastans nil lastfile))
@@ -496,8 +529,10 @@ found tag to be loaded."
       (if (and lastans calculated-scope)
 
          ;; Put our discovered scope into the tag if we have a tag
-         (semantic-scope-tag-clone-with-scope
-          lastans (reverse (cdr calculated-scope)))
+         (progn
+           (require 'semantic/scope)
+           (semantic-scope-tag-clone-with-scope
+            lastans (reverse (cdr calculated-scope))))
 
        ;; Else, just return
        lastans
@@ -531,8 +566,7 @@ If there isn't one, create it.
 
 (defun semanticdb-typecache-refresh-for-buffer (buffer)
   "Refresh the typecache for BUFFER."
-  (save-excursion
-    (set-buffer buffer)
+  (with-current-buffer buffer
     (let* ((tab semanticdb-current-table)
           ;(idx (semanticdb-get-table-index tab))
           (tc (semanticdb-get-typecache tab)))
@@ -548,7 +582,11 @@ If there isn't one, create it.
   (interactive)
   (let* ((path (semanticdb-find-translate-path nil nil)))
     (dolist (P path)
-      (oset P pointmax nil)
+      (condition-case nil
+         (oset P pointmax nil)
+       ;; Pointmax may not exist for all tables disovered in the
+       ;; path.
+       (error nil))
       (semantic-reset (semanticdb-get-typecache P)))))
 
 (defun semanticdb-typecache-dump ()
@@ -586,6 +624,11 @@ If there isn't one, create it.
 
     ))
 
-
 (provide 'semantic/db-typecache)
-;;; semanticdb-typecache.el ends here
+
+;; Local variables:
+;; generated-autoload-file: "loaddefs.el"
+;; generated-autoload-load-name: "semantic/db-typecache"
+;; End:
+
+;;; semantic/db-typecache.el ends here