diff lisp/cedet/semantic/db-ref.el @ 104417:6810f0d84270

cedet/semantic/ctxt.el, cedet/semantic/db-find.el, cedet/semantic/db-ref.el, cedet/semantic/find.el, cedet/semantic/format.el, cedet/semantic/sort.el: New files.
author Chong Yidong <cyd@stupidchicken.com>
date Fri, 28 Aug 2009 19:18:35 +0000
parents
children 902d22a2d922
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/cedet/semantic/db-ref.el	Fri Aug 28 19:18:35 2009 +0000
@@ -0,0 +1,161 @@
+;;; db-ref.el --- Handle cross-db file references
+
+;;; Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+
+;; Author: Eric M. Ludlam <eric@siege-engine.com>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Handle cross-database file references.
+;;
+;; Any given database may be referred to by some other database.  For
+;; example, if a .cpp file has a #include in a header, then that
+;; header file should have a reference to the .cpp file that included
+;; it.
+;;
+;; This is critical for purposes where a file (such as a .cpp file)
+;; needs to have its caches flushed because of changes in the
+;; header.  Changing a header may cause a referring file to be
+;; reparsed due to account for changes in defined macros, or perhaps
+;; a change to files the header includes.
+
+
+;;; Code:
+(defmethod semanticdb-add-reference ((dbt semanticdb-abstract-table)
+				     include-tag)
+  "Add a reference for the database table DBT based on INCLUDE-TAG.
+DBT is the database table that owns the INCLUDE-TAG.  The reference
+will be added to the database that INCLUDE-TAG refers to."
+  ;; NOTE: I should add a check to make sure include-tag is in DB.
+  ;;       but I'm too lazy.
+  (let* ((semanticdb-find-default-throttle
+	       (if (featurep 'semanticdb-find)
+		   (remq 'unloaded semanticdb-find-default-throttle)
+		 nil))
+	 (refdbt (semanticdb-find-table-for-include include-tag dbt))
+	 ;;(fullfile (semanticdb-full-filename dbt))
+	 )
+    (when refdbt
+      ;; Add our filename (full path)
+      ;; (object-add-to-list refdbt 'file-refs fullfile)
+
+      ;; Add our database.
+      (object-add-to-list refdbt 'db-refs dbt)
+      t)))
+
+(defmethod semanticdb-check-references ((dbt semanticdb-abstract-table))
+  "Check and cleanup references in the database DBT.
+Abstract tables would be difficult to reference."
+  ;; Not sure how an abstract table can have references.
+  nil)
+
+(defmethod semanticdb-includes-in-table ((dbt semanticdb-abstract-table))
+  "Return a list of direct includes in table DBT."
+  (semantic-find-tags-by-class 'include (semanticdb-get-tags dbt)))
+
+
+(defmethod semanticdb-check-references ((dbt semanticdb-table))
+  "Check and cleanup references in the database DBT.
+Any reference to a file that cannot be found, or whos file no longer
+refers to DBT will be removed."
+  (let ((refs (oref dbt db-refs))
+	(myexpr (concat "\\<" (oref dbt file)))
+	)
+    (while refs
+      (let* ((ok t)
+	     (db (car refs))
+	     (f (when (semanticdb-table-child-p db)
+		  (semanticdb-full-filename db)))
+	     )
+
+	;; The file was deleted
+	(when (and f (not (file-exists-p f)))
+	  (setq ok nil))
+
+	;; The reference no longer includes the textual reference?
+	(let* ((refs (semanticdb-includes-in-table db))
+	       (inc (semantic-find-tags-by-name-regexp
+		     myexpr refs)))
+	  (when (not inc)
+	    (setq ok nil)))
+
+	;; Remove not-ok databases from the list.
+	(when (not ok)
+	  (object-remove-from-list dbt 'db-refs db)
+	  ))
+      (setq refs (cdr refs)))))
+
+(defmethod semanticdb-refresh-references ((dbt semanticdb-abstract-table))
+  "Refresh references to DBT in other files."
+  ;; alternate tables can't be edited, so can't be changed.
+  nil
+  )
+
+(defmethod semanticdb-refresh-references ((dbt semanticdb-table))
+  "Refresh references to DBT in other files."
+  (let ((refs (semanticdb-includes-in-table dbt))
+	)
+    (while refs
+      (if (semanticdb-add-reference dbt (car refs))
+	  nil
+	;; If we succeeded, then do... nothing?
+	nil
+	)
+      (setq refs (cdr refs)))
+    ))
+
+(defmethod semanticdb-notify-references ((dbt semanticdb-table)
+					 method)
+  "Notify all references of the table DBT using method.
+METHOD takes two arguments.
+  (METHOD TABLE-TO-NOTIFY DBT)
+TABLE-TO-NOTIFY is a semanticdb-table which is being notified.
+DBT, the second argument is DBT."
+  (mapc (lambda (R) (funcall method R dbt))
+	  (oref dbt db-refs)))
+
+;;; DEBUG
+;;
+(defclass semanticdb-ref-adebug ()
+  ((i-depend-on :initarg :i-depend-on)
+   (local-table :initarg :local-table)
+   (i-include :initarg :i-include))
+  "Simple class to allow ADEBUG to show a nice list.")
+
+(defun semanticdb-ref-test (refresh)
+  "Dump out the list of references for the current buffer.
+If REFRESH is non-nil, cause the current table to have it's references
+refreshed before dumping the result."
+  (interactive "p")
+  ;; If we need to refresh... then do so.
+  (when refresh
+    (semanticdb-refresh-references semanticdb-current-table))
+  ;; Do the debug system
+  (let* ((tab semanticdb-current-table)
+	 (myrefs (oref tab db-refs))
+	 (myinc (semanticdb-includes-in-table tab))
+	 (adbc (semanticdb-ref-adebug "DEBUG"
+				      :i-depend-on myrefs
+				      :local-table tab
+				      :i-include myinc)))
+    (data-debug-new-buffer "*References ADEBUG*")
+    (data-debug-insert-object-slots adbc "!"))
+  )
+
+(provide 'semantic/db-ref)
+;;; semanticdb-ref.el ends here