dep.el 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. ;;; semantic/dep.el --- Methods for tracking dependencies (include files)
  2. ;; Copyright (C) 2006-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. ;; Include tags (dependencies for a given source file) usually have
  19. ;; some short name. The target file that it is dependent on is
  20. ;; generally found on some sort of path controlled by the compiler or
  21. ;; project.
  22. ;;
  23. ;; EDE or even ECB can control our project dependencies, and help us
  24. ;; find file within the setting of a given project. For system
  25. ;; dependencies, we need to depend on user supplied lists, which can
  26. ;; manifest themselves in the form of system databases (from
  27. ;; semanticdb.)
  28. ;;
  29. ;; Provide ways to track these different files here.
  30. (require 'semantic/tag)
  31. ;;; Code:
  32. (defvar semantic-dependency-include-path nil
  33. "Defines the include path used when searching for files.
  34. This should be a list of directories to search which is specific
  35. to the file being included.
  36. If `semantic-dependency-tag-file' is overridden for a given
  37. language, this path is most likely ignored.
  38. The above function, regardless of being overridden, caches the
  39. located dependency file location in the tag property
  40. `dependency-file'. If you override this function, you do not
  41. need to implement your own cache. Each time the buffer is fully
  42. reparsed, the cache will be reset.
  43. TODO: use ffap.el to locate such items?
  44. NOTE: Obsolete this, or use as special user")
  45. (make-variable-buffer-local `semantic-dependency-include-path)
  46. (defvar semantic-dependency-system-include-path nil
  47. "Defines the system include path.
  48. This should be set with either `defvar-mode-local', or with
  49. `semantic-add-system-include'.
  50. For mode authors, use
  51. `defcustom-mode-local-semantic-dependency-system-include-path'
  52. to create a mode-specific variable to control this.
  53. When searching for a file associated with a name found in an tag of
  54. class include, this path will be inspected for includes of type
  55. `system'. Some include tags are agnostic to this setting and will
  56. check both the project and system directories.")
  57. (make-variable-buffer-local `semantic-dependency-system-include-path)
  58. (defmacro defcustom-mode-local-semantic-dependency-system-include-path
  59. (mode name value &optional docstring)
  60. "Create a mode-local value of the system-dependency include path.
  61. MODE is the `major-mode' this name/value pairs is for.
  62. NAME is the name of the customizable value users will use.
  63. VALUE is the path (a list of strings) to add.
  64. DOCSTRING is a documentation string applied to the variable NAME
  65. users will customize.
  66. Creates a customizable variable users can customize that will
  67. keep semantic data structures up to date."
  68. `(progn
  69. ;; Create a variable users can customize.
  70. (defcustom ,name ,value
  71. ,docstring
  72. :group (quote ,(intern (car (split-string (symbol-name mode) "-"))))
  73. :group 'semantic
  74. :type '(repeat (directory :tag "Directory"))
  75. :set (lambda (sym val)
  76. (set-default sym val)
  77. (setq-mode-local ,mode
  78. semantic-dependency-system-include-path
  79. val)
  80. (when (fboundp
  81. 'semantic-decoration-unparsed-include-do-reset)
  82. (mode-local-map-mode-buffers
  83. 'semantic-decoration-unparsed-include-do-reset
  84. (quote ,mode))))
  85. )
  86. ;; Set the variable to the default value.
  87. (defvar-mode-local ,mode semantic-dependency-system-include-path
  88. ,name
  89. "System path to search for include files.")
  90. ;; Bind NAME onto our variable so tools can customize it
  91. ;; without knowing about it.
  92. (put 'semantic-dependency-system-include-path
  93. (quote ,mode) (quote ,name))
  94. ))
  95. ;;; PATH MANAGEMENT
  96. ;;
  97. ;; Some fcns to manage paths for a give mode.
  98. ;;;###autoload
  99. (defun semantic-add-system-include (dir &optional mode)
  100. "Add a system include DIR to path for MODE.
  101. Modifies a mode-local version of `semantic-dependency-system-include-path'.
  102. Changes made by this function are not persistent."
  103. (interactive "DNew Include Directory: ")
  104. (if (not mode) (setq mode major-mode))
  105. (let ((dirtmp (file-name-as-directory dir))
  106. (value
  107. (mode-local-value mode 'semantic-dependency-system-include-path))
  108. )
  109. (add-to-list 'value dirtmp t)
  110. (eval `(setq-mode-local ,mode
  111. semantic-dependency-system-include-path value))
  112. ))
  113. ;;;###autoload
  114. (defun semantic-remove-system-include (dir &optional mode)
  115. "Add a system include DIR to path for MODE.
  116. Modifies a mode-local version of`semantic-dependency-system-include-path'.
  117. Changes made by this function are not persistent."
  118. (interactive (list
  119. (completing-read
  120. "Include Directory to Remove: "
  121. semantic-dependency-system-include-path))
  122. )
  123. (if (not mode) (setq mode major-mode))
  124. (let ((dirtmp (file-name-as-directory dir))
  125. (value
  126. (mode-local-value mode 'semantic-dependency-system-include-path))
  127. )
  128. (setq value (delete dirtmp value))
  129. (eval `(setq-mode-local ,mode semantic-dependency-system-include-path
  130. value))
  131. ))
  132. ;;;###autoload
  133. (defun semantic-reset-system-include (&optional mode)
  134. "Reset the system include list to empty for MODE.
  135. Modifies a mode-local version of
  136. `semantic-dependency-system-include-path'."
  137. (interactive)
  138. (if (not mode) (setq mode major-mode))
  139. (eval `(setq-mode-local ,mode semantic-dependency-system-include-path
  140. nil))
  141. )
  142. ;;;###autoload
  143. (defun semantic-customize-system-include-path (&optional mode)
  144. "Customize the include path for this `major-mode'.
  145. To create a customizable include path for a major MODE, use the
  146. macro `defcustom-mode-local-semantic-dependency-system-include-path'."
  147. (interactive)
  148. (let ((ips (get 'semantic-dependency-system-include-path
  149. (or mode major-mode))))
  150. ;; Do we have one?
  151. (when (not ips)
  152. (error "There is no customizable includepath variable for %s"
  153. (or mode major-mode)))
  154. ;; Customize it.
  155. (customize-variable ips)))
  156. ;;; PATH SEARCH
  157. ;;
  158. ;; methods for finding files on a provided path.
  159. (defmacro semantic--dependency-find-file-on-path (file path)
  160. (if (fboundp 'locate-file)
  161. `(locate-file ,file ,path)
  162. `(let ((p ,path)
  163. (found nil))
  164. (while (and p (not found))
  165. (let ((f (expand-file-name ,file (car p))))
  166. (if (file-exists-p f)
  167. (setq found f)))
  168. (setq p (cdr p)))
  169. found)))
  170. (defvar ede-minor-mode)
  171. (defvar ede-object)
  172. (declare-function ede-system-include-path "ede")
  173. (defun semantic-dependency-find-file-on-path (file systemp &optional mode)
  174. "Return an expanded file name for FILE on available paths.
  175. If SYSTEMP is true, then only search system paths.
  176. If optional argument MODE is non-nil, then derive paths from the
  177. provided mode, not from the current major mode."
  178. (if (not mode) (setq mode major-mode))
  179. (let ((sysp (mode-local-value
  180. mode 'semantic-dependency-system-include-path))
  181. (edesys (when (and (featurep 'ede) ede-minor-mode
  182. ede-object)
  183. (ede-system-include-path
  184. (if (listp ede-object) (car ede-object) ede-object))))
  185. (locp (mode-local-value
  186. mode 'semantic-dependency-include-path))
  187. (found nil))
  188. (when (file-exists-p file)
  189. (setq found file))
  190. (when (and (not found) (not systemp))
  191. (setq found (semantic--dependency-find-file-on-path file locp)))
  192. (when (and (not found) edesys)
  193. (setq found (semantic--dependency-find-file-on-path file edesys)))
  194. (when (not found)
  195. (setq found (semantic--dependency-find-file-on-path file sysp)))
  196. (if found (expand-file-name found))))
  197. (provide 'semantic/dep)
  198. ;; Local variables:
  199. ;; generated-autoload-file: "loaddefs.el"
  200. ;; generated-autoload-load-name: "semantic/dep"
  201. ;; End:
  202. ;;; semantic/dep.el ends here