Mercurial > emacs
diff lisp/cedet/semantic/tag-file.el @ 105260:bbd7017a25d9
CEDET (development tools) package merged.
* cedet/*.el:
* cedet/ede/*.el:
* cedet/semantic/*.el:
* cedet/srecode/*.el: New files.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Mon, 28 Sep 2009 15:15:00 +0000 |
parents | 8db96f200ac8 |
children | 6969c5b2e0b2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/cedet/semantic/tag-file.el Mon Sep 28 15:15:00 2009 +0000 @@ -0,0 +1,220 @@ +;;; semantic/tag-file.el --- Routines that find files based on tags. + +;;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, +;;; 2008, 2009 Free Software Foundation, Inc. + +;; Author: Eric M. Ludlam <zappo@gnu.org> +;; Keywords: syntax + +;; 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: +;; +;; A tag, by itself, can have representations in several files. +;; These routines will find those files. + +(require 'semantic/tag) + +(defvar ede-minor-mode) +(declare-function semanticdb-table-child-p "semantic/db") +(declare-function semanticdb-get-buffer "semantic/db") +(declare-function semantic-dependency-find-file-on-path "semantic/dep") +(declare-function ede-toplevel "ede/files") + +;;; Code: + +;;; Location a TAG came from. +;; +;;;###autoload +(define-overloadable-function semantic-go-to-tag (tag &optional parent) + "Go to the location of TAG. +TAG may be a stripped element, in which case PARENT specifies a +parent tag that has position information. +PARENT can also be a `semanticdb-table' object." + (:override + (save-match-data + (cond ((semantic-tag-in-buffer-p tag) + ;; We have a linked tag, go to that buffer. + (set-buffer (semantic-tag-buffer tag))) + ((semantic-tag-file-name tag) + ;; If it didn't have a buffer, but does have a file + ;; name, then we need to get to that file so the tag + ;; location is made accurate. + (set-buffer (find-file-noselect (semantic-tag-file-name tag)))) + ((and parent (semantic-tag-p parent) (semantic-tag-in-buffer-p parent)) + ;; The tag had nothing useful, but we have a parent with + ;; a buffer, then go there. + (set-buffer (semantic-tag-buffer parent))) + ((and parent (semantic-tag-p parent) (semantic-tag-file-name parent)) + ;; Tag had nothing, and the parent only has a file-name, then + ;; find that file, and switch to that buffer. + (set-buffer (find-file-noselect (semantic-tag-file-name parent)))) + ((and parent (featurep 'semantic/db) + (semanticdb-table-child-p parent)) + (set-buffer (semanticdb-get-buffer parent))) + (t + ;; Well, just assume things are in the current buffer. + nil + ))) + ;; We should be in the correct buffer now, try and figure out + ;; where the tag is. + (cond ((semantic-tag-with-position-p tag) + ;; If it's a number, go there + (goto-char (semantic-tag-start tag))) + ((semantic-tag-with-position-p parent) + ;; Otherwise, it's a trimmed vector, such as a parameter, + ;; or a structure part. If there is a parent, we can use it + ;; as a bounds for searching. + (goto-char (semantic-tag-start parent)) + ;; Here we make an assumption that the text returned by + ;; the parser and concocted by us actually exists + ;; in the buffer. + (re-search-forward (semantic-tag-name tag) + (semantic-tag-end parent) + t)) + ((semantic-tag-get-attribute tag :line) + ;; The tag has a line number in it. Go there. + (goto-char (point-min)) + (forward-line (1- (semantic-tag-get-attribute tag :line)))) + ((and (semantic-tag-p parent) (semantic-tag-get-attribute parent :line)) + ;; The tag has a line number in it. Go there. + (goto-char (point-min)) + (forward-line (1- (semantic-tag-get-attribute parent :line))) + (re-search-forward (semantic-tag-name tag) nil t)) + (t + ;; Take a guess that the tag has a unique name, and just + ;; search for it from the beginning of the buffer. + (goto-char (point-min)) + (re-search-forward (semantic-tag-name tag) nil t))) + ) + ) + +(make-obsolete-overload 'semantic-find-nonterminal + 'semantic-go-to-tag) + +;;; Dependencies +;; +;; A tag which is of type 'include specifies a dependency. +;; Dependencies usually represent a file of some sort. +;; Find the file described by a dependency. + +;;;###autoload +(define-overloadable-function semantic-dependency-tag-file (&optional tag) + "Find the filename represented from TAG. +Depends on `semantic-dependency-include-path' for searching. Always searches +`.' first, then searches additional paths." + (or tag (setq tag (car (semantic-find-tag-by-overlay nil)))) + (unless (semantic-tag-of-class-p tag 'include) + (signal 'wrong-type-argument (list tag 'include))) + (save-excursion + (let ((result nil) + (default-directory default-directory) + (edefind nil) + (tag-fname nil)) + (cond ((semantic-tag-in-buffer-p tag) + ;; If the tag has an overlay and buffer associated with it, + ;; switch to that buffer so that we get the right override metohds. + (set-buffer (semantic-tag-buffer tag))) + ((semantic-tag-file-name tag) + ;; If it didn't have a buffer, but does have a file + ;; name, then we need to get to that file so the tag + ;; location is made accurate. + ;;(set-buffer (find-file-noselect (semantic-tag-file-name tag))) + ;; + ;; 2/3/08 + ;; The above causes unnecessary buffer loads all over the place. Ick! + ;; All we really need is for 'default-directory' to be set correctly. + (setq default-directory (file-name-directory (semantic-tag-file-name tag))) + )) + ;; Setup the filename represented by this include + (setq tag-fname (semantic-tag-include-filename tag)) + + ;; First, see if this file exists in the current EDE project + (if (and (fboundp 'ede-expand-filename) ede-minor-mode + (setq edefind + (condition-case nil + (let ((proj (ede-toplevel))) + (when proj + (ede-expand-filename proj tag-fname))) + (error nil)))) + (setq result edefind)) + (if (not result) + (setq result + ;; I don't have a plan for refreshing tags with a dependency + ;; stuck on them somehow. I'm thinking that putting a cache + ;; onto the dependancy finding with a hash table might be best. + ;;(if (semantic--tag-get-property tag 'dependency-file) + ;; (semantic--tag-get-property tag 'dependency-file) + (:override + (save-excursion + (require 'semantic/dep) + (semantic-dependency-find-file-on-path + tag-fname (semantic-tag-include-system-p tag)))) + ;; ) + )) + (if (stringp result) + (progn + (semantic--tag-put-property tag 'dependency-file result) + result) + ;; @todo: Do something to make this get flushed w/ + ;; when the path is changed. + ;; @undo: Just eliminate + ;; (semantic--tag-put-property tag 'dependency-file 'none) + nil) + ))) + +(make-obsolete-overload 'semantic-find-dependency + 'semantic-dependency-tag-file) + +;;; PROTOTYPE FILE +;; +;; In C, a function in the .c file often has a representation in a +;; corresponding .h file. This routine attempts to find the +;; prototype file a given source file would be associated with. +;; This can be used by prototype manager programs. +(define-overloadable-function semantic-prototype-file (buffer) + "Return a file in which prototypes belonging to BUFFER should be placed. +Default behavior (if not overridden) looks for a token specifying the +prototype file, or the existence of an EDE variable indicating which +file prototypes belong in." + (:override + ;; Perform some default behaviors + (if (and (fboundp 'ede-header-file) ede-minor-mode) + (save-excursion + (set-buffer buffer) + (ede-header-file)) + ;; No EDE options for a quick answer. Search. + (save-excursion + (set-buffer buffer) + (if (re-search-forward "::Header:: \\([a-zA-Z0-9.]+\\)" nil t) + (match-string 1)))))) + +(semantic-alias-obsolete 'semantic-find-nonterminal + 'semantic-go-to-tag) + +(semantic-alias-obsolete 'semantic-find-dependency + 'semantic-dependency-tag-file) + + +(provide 'semantic/tag-file) + +;; Local variables: +;; generated-autoload-file: "loaddefs.el" +;; generated-autoload-feature: semantic/loaddefs +;; generated-autoload-load-name: "semantic/tag-file" +;; End: + +;;; semantic/tag-file.el ends here