tag-file.el 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. ;;; semantic/tag-file.el --- Routines that find files based on tags.
  2. ;; Copyright (C) 1999-2005, 2007-2012 Free Software Foundation, Inc.
  3. ;; Author: Eric M. Ludlam <zappo@gnu.org>
  4. ;; Keywords: syntax
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;
  18. ;; A tag, by itself, can have representations in several files.
  19. ;; These routines will find those files.
  20. (require 'semantic/tag)
  21. (defvar ede-minor-mode)
  22. (declare-function semanticdb-table-child-p "semantic/db" t t)
  23. (declare-function semanticdb-get-buffer "semantic/db")
  24. (declare-function semantic-dependency-find-file-on-path "semantic/dep")
  25. (declare-function ede-toplevel "ede/base")
  26. ;;; Code:
  27. ;;; Location a TAG came from.
  28. ;;
  29. ;;;###autoload
  30. (define-overloadable-function semantic-go-to-tag (tag &optional parent)
  31. "Go to the location of TAG.
  32. TAG may be a stripped element, in which case PARENT specifies a
  33. parent tag that has position information.
  34. PARENT can also be a `semanticdb-table' object."
  35. (:override
  36. (save-match-data
  37. (cond ((semantic-tag-in-buffer-p tag)
  38. ;; We have a linked tag, go to that buffer.
  39. (set-buffer (semantic-tag-buffer tag)))
  40. ((semantic-tag-file-name tag)
  41. ;; If it didn't have a buffer, but does have a file
  42. ;; name, then we need to get to that file so the tag
  43. ;; location is made accurate.
  44. (set-buffer (find-file-noselect (semantic-tag-file-name tag))))
  45. ((and parent (semantic-tag-p parent) (semantic-tag-in-buffer-p parent))
  46. ;; The tag had nothing useful, but we have a parent with
  47. ;; a buffer, then go there.
  48. (set-buffer (semantic-tag-buffer parent)))
  49. ((and parent (semantic-tag-p parent) (semantic-tag-file-name parent))
  50. ;; Tag had nothing, and the parent only has a file-name, then
  51. ;; find that file, and switch to that buffer.
  52. (set-buffer (find-file-noselect (semantic-tag-file-name parent))))
  53. ((and parent (featurep 'semantic/db)
  54. (semanticdb-table-child-p parent))
  55. (set-buffer (semanticdb-get-buffer parent)))
  56. (t
  57. ;; Well, just assume things are in the current buffer.
  58. nil
  59. )))
  60. ;; We should be in the correct buffer now, try and figure out
  61. ;; where the tag is.
  62. (cond ((semantic-tag-with-position-p tag)
  63. ;; If it's a number, go there
  64. (goto-char (semantic-tag-start tag)))
  65. ((semantic-tag-with-position-p parent)
  66. ;; Otherwise, it's a trimmed vector, such as a parameter,
  67. ;; or a structure part. If there is a parent, we can use it
  68. ;; as a bounds for searching.
  69. (goto-char (semantic-tag-start parent))
  70. ;; Here we make an assumption that the text returned by
  71. ;; the parser and concocted by us actually exists
  72. ;; in the buffer.
  73. (re-search-forward (semantic-tag-name tag)
  74. (semantic-tag-end parent)
  75. t))
  76. ((semantic-tag-get-attribute tag :line)
  77. ;; The tag has a line number in it. Go there.
  78. (goto-char (point-min))
  79. (forward-line (1- (semantic-tag-get-attribute tag :line))))
  80. ((and (semantic-tag-p parent) (semantic-tag-get-attribute parent :line))
  81. ;; The tag has a line number in it. Go there.
  82. (goto-char (point-min))
  83. (forward-line (1- (semantic-tag-get-attribute parent :line)))
  84. (re-search-forward (semantic-tag-name tag) nil t))
  85. (t
  86. ;; Take a guess that the tag has a unique name, and just
  87. ;; search for it from the beginning of the buffer.
  88. (goto-char (point-min))
  89. (re-search-forward (semantic-tag-name tag) nil t)))
  90. )
  91. )
  92. (make-obsolete-overload 'semantic-find-nonterminal
  93. 'semantic-go-to-tag "23.2")
  94. ;;; Dependencies
  95. ;;
  96. ;; A tag which is of type 'include specifies a dependency.
  97. ;; Dependencies usually represent a file of some sort.
  98. ;; Find the file described by a dependency.
  99. ;;;###autoload
  100. (define-overloadable-function semantic-dependency-tag-file (&optional tag)
  101. "Find the filename represented from TAG.
  102. Depends on `semantic-dependency-include-path' for searching. Always searches
  103. `.' first, then searches additional paths."
  104. (or tag (setq tag (car (semantic-find-tag-by-overlay nil))))
  105. (unless (semantic-tag-of-class-p tag 'include)
  106. (signal 'wrong-type-argument (list tag 'include)))
  107. (save-excursion
  108. (let ((result nil)
  109. (default-directory default-directory)
  110. (edefind nil)
  111. (tag-fname nil))
  112. (cond ((semantic-tag-in-buffer-p tag)
  113. ;; If the tag has an overlay and buffer associated with it,
  114. ;; switch to that buffer so that we get the right override methods.
  115. (set-buffer (semantic-tag-buffer tag)))
  116. ((semantic-tag-file-name tag)
  117. ;; If it didn't have a buffer, but does have a file
  118. ;; name, then we need to get to that file so the tag
  119. ;; location is made accurate.
  120. ;;(set-buffer (find-file-noselect (semantic-tag-file-name tag)))
  121. ;;
  122. ;; 2/3/08
  123. ;; The above causes unnecessary buffer loads all over the place. Ick!
  124. ;; All we really need is for 'default-directory' to be set correctly.
  125. (setq default-directory (file-name-directory (semantic-tag-file-name tag)))
  126. ))
  127. ;; Setup the filename represented by this include
  128. (setq tag-fname (semantic-tag-include-filename tag))
  129. ;; First, see if this file exists in the current EDE project
  130. (if (and (fboundp 'ede-expand-filename) ede-minor-mode
  131. (setq edefind
  132. (condition-case nil
  133. (let ((proj (ede-toplevel)))
  134. (when proj
  135. (ede-expand-filename proj tag-fname)))
  136. (error nil))))
  137. (setq result edefind))
  138. (if (not result)
  139. (setq result
  140. ;; I don't have a plan for refreshing tags with a dependency
  141. ;; stuck on them somehow. I'm thinking that putting a cache
  142. ;; onto the dependency finding with a hash table might be best.
  143. ;;(if (semantic--tag-get-property tag 'dependency-file)
  144. ;; (semantic--tag-get-property tag 'dependency-file)
  145. (:override
  146. (save-excursion
  147. (require 'semantic/dep)
  148. (semantic-dependency-find-file-on-path
  149. tag-fname (semantic-tag-include-system-p tag))))
  150. ;; )
  151. ))
  152. (if (stringp result)
  153. (progn
  154. (semantic--tag-put-property tag 'dependency-file result)
  155. result)
  156. ;; @todo: Do something to make this get flushed w/
  157. ;; when the path is changed.
  158. ;; @undo: Just eliminate
  159. ;; (semantic--tag-put-property tag 'dependency-file 'none)
  160. nil)
  161. )))
  162. (make-obsolete-overload 'semantic-find-dependency
  163. 'semantic-dependency-tag-file "23.2")
  164. ;;; PROTOTYPE FILE
  165. ;;
  166. ;; In C, a function in the .c file often has a representation in a
  167. ;; corresponding .h file. This routine attempts to find the
  168. ;; prototype file a given source file would be associated with.
  169. ;; This can be used by prototype manager programs.
  170. (define-overloadable-function semantic-prototype-file (buffer)
  171. "Return a file in which prototypes belonging to BUFFER should be placed.
  172. Default behavior (if not overridden) looks for a token specifying the
  173. prototype file, or the existence of an EDE variable indicating which
  174. file prototypes belong in."
  175. (:override
  176. ;; Perform some default behaviors
  177. (if (and (fboundp 'ede-header-file) ede-minor-mode)
  178. (with-current-buffer buffer
  179. (ede-header-file))
  180. ;; No EDE options for a quick answer. Search.
  181. (with-current-buffer buffer
  182. (if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t)
  183. (match-string 1))))))
  184. (semantic-alias-obsolete 'semantic-find-nonterminal
  185. 'semantic-go-to-tag "23.2")
  186. (semantic-alias-obsolete 'semantic-find-dependency
  187. 'semantic-dependency-tag-file "23.2")
  188. (provide 'semantic/tag-file)
  189. ;; Local variables:
  190. ;; generated-autoload-file: "loaddefs.el"
  191. ;; generated-autoload-load-name: "semantic/tag-file"
  192. ;; End:
  193. ;;; semantic/tag-file.el ends here