d63e1a7a49f41d41ee227d5fecf1a8840639a6ab
[bpt/emacs.git] / lisp / cedet / srecode / cpp.el
1 ;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder
2
3 ;; Copyright (C) 2007, 2009-2012 Free Software Foundation, Inc.
4
5 ;; Author: Eric M. Ludlam <eric@siege-engine.com>
6 ;; Jan Moringen <scymtym@users.sourceforge.net>
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23 ;;; Commentary:
24 ;;
25 ;; Supply some C++ specific dictionary fillers and helpers
26
27 ;;; Code:
28
29 (require 'srecode)
30 (require 'srecode/dictionary)
31 (require 'srecode/semantic)
32 (require 'semantic/tag)
33
34 ;;; Customization
35 ;;
36
37 (defgroup srecode-cpp nil
38 "C++-specific Semantic Recoder settings."
39 :group 'srecode)
40
41 (defcustom srecode-cpp-namespaces
42 '("std" "boost")
43 "List expansion candidates for the :using-namespaces argument.
44 A dictionary entry of the named PREFIX_NAMESPACE with the value
45 NAMESPACE:: is created for each namespace unless the current
46 buffer contains a using NAMESPACE; statement "
47 :group 'srecode-cpp
48 :type '(repeat string))
49
50 ;;; :c ARGUMENT HANDLING
51 ;;
52 ;; When a :c argument is required, fill the dictionary with
53 ;; information about the current C file.
54 ;;
55 ;; Error if not in a C mode.
56
57 ;;;###autoload
58 (defun srecode-semantic-handle-:c (dict)
59 "Add macros into the dictionary DICT based on the current c file.
60 Adds the following:
61 FILENAME_SYMBOL - filename converted into a C compat symbol.
62 HEADER - Shown section if in a header file."
63 ;; A symbol representing
64 (let ((fsym (file-name-nondirectory (buffer-file-name)))
65 (case-fold-search t))
66
67 ;; Are we in a header file?
68 (if (string-match "\\.\\(h\\|hh\\|hpp\\|h\\+\\+\\)$" fsym)
69 (srecode-dictionary-show-section dict "HEADER")
70 (srecode-dictionary-show-section dict "NOTHEADER"))
71
72 ;; Strip out bad characters
73 (while (string-match "\\.\\| " fsym)
74 (setq fsym (replace-match "_" t t fsym)))
75 (srecode-dictionary-set-value dict "FILENAME_SYMBOL" fsym)
76 )
77 )
78
79 ;;; :cpp ARGUMENT HANDLING
80 ;;
81 ;; When a :cpp argument is required, fill the dictionary with
82 ;; information about the current C++ file.
83 ;;
84 ;; Error if not in a C++ mode.
85 ;;;###autoload
86 (defun srecode-semantic-handle-:cpp (dict)
87 "Add macros into the dictionary DICT based on the current c file.
88 Calls `srecode-semantic-handle-:c.
89 Also adds the following:
90 - nothing -"
91 (srecode-semantic-handle-:c dict)
92 )
93
94 (defun srecode-semantic-handle-:using-namespaces (dict)
95 "Add macros into the dictionary DICT based on used namespaces.
96 Adds the following:
97 PREFIX_NAMESPACE - for each NAMESPACE in `srecode-cpp-namespaces'."
98 (let ((tags (semantic-find-tags-by-class
99 'using (semantic-fetch-tags))))
100 (dolist (name srecode-cpp-namespaces)
101 (let ((variable (format "PREFIX_%s" (upcase name)))
102 (prefix (format "%s::" name)))
103 (srecode-dictionary-set-value dict variable prefix)
104 (dolist (tag tags)
105 (when (and (eq (semantic-tag-get-attribute tag :kind)
106 'namespace)
107 (string= (semantic-tag-name tag) name))
108 (srecode-dictionary-set-value dict variable ""))))))
109 )
110
111 (define-mode-local-override srecode-semantic-apply-tag-to-dict
112 c-mode (tag-wrapper dict)
113 "Apply C and C++ specific features from TAG-WRAPPER into DICT.
114 Calls `srecode-semantic-apply-tag-to-dict-default' first. Adds
115 special behavior for tag of classes include, using and function.
116
117 This function cannot be split into C and C++ specific variants, as
118 the way the tags are created from the parser does not distinguish
119 either. The side effect is that you could get some C++ tag properties
120 specified in a C file."
121
122 ;; Use default implementation to fill in the basic properties.
123 (srecode-semantic-apply-tag-to-dict-default tag-wrapper dict)
124
125 ;; Pull out the tag for the individual pieces.
126 (let* ((tag (oref tag-wrapper :prime))
127 (class (semantic-tag-class tag)))
128
129 ;; Add additional information based on the class of the tag.
130 (cond
131 ;;
132 ;; INCLUDE
133 ;;
134 ((eq class 'include)
135 ;; For include tags, we have to discriminate between system-wide
136 ;; and local includes.
137 (if (semantic-tag-include-system-p tag)
138 (srecode-dictionary-show-section dict "SYSTEM")
139 (srecode-dictionary-show-section dict "LOCAL")))
140
141 ;;
142 ;; USING
143 ;;
144 ((eq class 'using)
145 ;; Insert the subject (a tag) of the include statement as VALUE
146 ;; entry into the dictionary.
147 (let ((value-tag (semantic-tag-get-attribute tag :value))
148 (value-dict (srecode-dictionary-add-section-dictionary
149 dict "VALUE")))
150 (srecode-semantic-apply-tag-to-dict
151 (srecode-semantic-tag (semantic-tag-name value-tag)
152 :prime value-tag)
153 value-dict))
154
155 ;; Discriminate using statements referring to namespaces and
156 ;; types.
157 (when (eq (semantic-tag-get-attribute tag :kind) 'namespace)
158 (srecode-dictionary-show-section dict "NAMESPACE")))
159
160 ;;
161 ;; FUNCTION
162 ;;
163 ((eq class 'function)
164 ;; @todo It would be nice to distinguish member functions from
165 ;; free functions and only apply the const and pure modifiers,
166 ;; when they make sense. My best bet would be
167 ;; (semantic-tag-function-parent tag), but it is not there, when
168 ;; the function is defined in the scope of a class.
169 (let ((member t)
170 (templates (semantic-tag-get-attribute tag :template))
171 (modifiers (semantic-tag-modifiers tag)))
172
173 ;; Mark constructors and destructors as such.
174 (when (semantic-tag-function-constructor-p tag)
175 (srecode-dictionary-show-section dict "CONSTRUCTOR"))
176 (when (semantic-tag-function-destructor-p tag)
177 (srecode-dictionary-show-section dict "DESTRUCTOR"))
178
179 ;; Add modifiers into the dictionary.
180 (dolist (modifier modifiers)
181 (let ((modifier-dict (srecode-dictionary-add-section-dictionary
182 dict "MODIFIERS")))
183 (srecode-dictionary-set-value modifier-dict "NAME" modifier)))
184
185 ;; Add templates into child dictionaries.
186 (srecode-c-apply-templates dict templates)
187
188 ;; When the function is a member function, it can have
189 ;; additional modifiers.
190 (when member
191
192 ;; For member functions, constness is called
193 ;; 'methodconst-flag'.
194 (when (semantic-tag-get-attribute tag :methodconst-flag)
195 (srecode-dictionary-show-section dict "CONST"))
196
197 ;; If the member function is pure virtual, add a dictionary
198 ;; entry.
199 (when (semantic-tag-get-attribute tag :pure-virtual-flag)
200 (srecode-dictionary-show-section dict "PURE")))))
201
202 ;;
203 ;; CLASS
204 ;;
205 ((eq class 'type)
206 ;; For classes, add template parameters.
207 (when (or (semantic-tag-of-type-p tag "class")
208 (semantic-tag-of-type-p tag "struct"))
209
210 ;; Add templates into child dictionaries.
211 (let ((templates (semantic-tag-get-attribute tag :template)))
212 (srecode-c-apply-templates dict templates))))
213 ))
214 )
215
216 \f
217 ;;; Helper functions
218 ;;
219
220 (defun srecode-c-apply-templates (dict templates)
221 "Add section dictionaries for TEMPLATES to DICT."
222 (when templates
223 (let ((templates-dict (srecode-dictionary-add-section-dictionary
224 dict "TEMPLATES")))
225 (dolist (template templates)
226 (let ((template-dict (srecode-dictionary-add-section-dictionary
227 templates-dict "ARGS")))
228 (srecode-semantic-apply-tag-to-dict
229 (srecode-semantic-tag (semantic-tag-name template)
230 :prime template)
231 template-dict)))))
232 )
233
234 (provide 'srecode/cpp)
235
236 ;; Local variables:
237 ;; generated-autoload-file: "loaddefs.el"
238 ;; generated-autoload-load-name: "srecode/cpp"
239 ;; End:
240
241 ;;; srecode/cpp.el ends here