Commit | Line | Data |
---|---|---|
4d902e6f CY |
1 | ;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder |
2 | ||
5df4f04c | 3 | ;; Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc. |
4d902e6f CY |
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 | ||
b9749554 EL |
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 | ||
4d902e6f CY |
50 | ;;; :cpp ARGUMENT HANDLING |
51 | ;; | |
52 | ;; When a :cpp argument is required, fill the dictionary with | |
53 | ;; information about the current C++ file. | |
54 | ;; | |
55 | ;; Error if not in a C++ mode. | |
56 | ||
4d902e6f CY |
57 | ;;;###autoload |
58 | (defun srecode-semantic-handle-:cpp (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 | ||
b9749554 EL |
79 | (defun srecode-semantic-handle-:using-namespaces (dict) |
80 | "Add macros into the dictionary DICT based on used namespaces. | |
81 | Adds the following: | |
82 | PREFIX_NAMESPACE - for each NAMESPACE in `srecode-cpp-namespaces'." | |
83 | (let ((tags (semantic-find-tags-by-class | |
84 | 'using (semantic-fetch-tags)))) | |
85 | (dolist (name srecode-cpp-namespaces) | |
86 | (let ((variable (format "PREFIX_%s" (upcase name))) | |
87 | (prefix (format "%s::" name))) | |
88 | (srecode-dictionary-set-value dict variable prefix) | |
89 | (dolist (tag tags) | |
90 | (when (and (eq (semantic-tag-get-attribute tag :kind) | |
91 | 'namespace) | |
92 | (string= (semantic-tag-name tag) name)) | |
93 | (srecode-dictionary-set-value dict variable "")))))) | |
94 | ) | |
95 | ||
4d902e6f CY |
96 | (define-mode-local-override srecode-semantic-apply-tag-to-dict |
97 | c++-mode (tag-wrapper dict) | |
98 | "Apply C++ specific features from TAG-WRAPPER into DICT. | |
99 | Calls `srecode-semantic-apply-tag-to-dict-default' first. Adds | |
100 | special behavior for tag of classes include, using and function." | |
101 | ||
102 | ;; Use default implementation to fill in the basic properties. | |
103 | (srecode-semantic-apply-tag-to-dict-default tag-wrapper dict) | |
104 | ||
105 | ;; Pull out the tag for the individual pieces. | |
106 | (let* ((tag (oref tag-wrapper :prime)) | |
107 | (class (semantic-tag-class tag))) | |
108 | ||
109 | ;; Add additional information based on the class of the tag. | |
110 | (cond | |
111 | ;; | |
112 | ;; INCLUDE | |
113 | ;; | |
114 | ((eq class 'include) | |
115 | ;; For include tags, we have to discriminate between system-wide | |
116 | ;; and local includes. | |
117 | (if (semantic-tag-include-system-p tag) | |
118 | (srecode-dictionary-show-section dict "SYSTEM") | |
119 | (srecode-dictionary-show-section dict "LOCAL"))) | |
120 | ||
121 | ;; | |
122 | ;; USING | |
123 | ;; | |
124 | ((eq class 'using) | |
125 | ;; Insert the subject (a tag) of the include statement as VALUE | |
126 | ;; entry into the dictionary. | |
127 | (let ((value-tag (semantic-tag-get-attribute tag :value)) | |
128 | (value-dict (srecode-dictionary-add-section-dictionary | |
129 | dict "VALUE"))) | |
130 | (srecode-semantic-apply-tag-to-dict | |
131 | (srecode-semantic-tag (semantic-tag-name value-tag) | |
132 | :prime value-tag) | |
133 | value-dict)) | |
b9749554 | 134 | |
4d902e6f CY |
135 | ;; Discriminate using statements referring to namespaces and |
136 | ;; types. | |
137 | (when (eq (semantic-tag-get-attribute tag :kind) 'namespace) | |
138 | (srecode-dictionary-show-section dict "NAMESPACE"))) | |
139 | ||
140 | ;; | |
141 | ;; FUNCTION | |
142 | ;; | |
143 | ((eq class 'function) | |
144 | ;; @todo It would be nice to distinguish member functions from | |
145 | ;; free functions and only apply the const and pure modifiers, | |
146 | ;; when they make sense. My best bet would be | |
147 | ;; (semantic-tag-function-parent tag), but it is not there, when | |
148 | ;; the function is defined in the scope of a class. | |
b9749554 EL |
149 | (let ((member t) |
150 | (templates (semantic-tag-get-attribute tag :template)) | |
4d902e6f CY |
151 | (modifiers (semantic-tag-modifiers tag))) |
152 | ||
153 | ;; Add modifiers into the dictionary | |
154 | (dolist (modifier modifiers) | |
155 | (let ((modifier-dict (srecode-dictionary-add-section-dictionary | |
156 | dict "MODIFIERS"))) | |
157 | (srecode-dictionary-set-value modifier-dict "NAME" modifier))) | |
158 | ||
b9749554 EL |
159 | ;; Add templates into child dictionaries. |
160 | (srecode-cpp-apply-templates dict templates) | |
161 | ||
4d902e6f CY |
162 | ;; When the function is a member function, it can have |
163 | ;; additional modifiers. | |
164 | (when member | |
165 | ||
166 | ;; For member functions, constness is called | |
167 | ;; 'methodconst-flag'. | |
168 | (when (semantic-tag-get-attribute tag :methodconst-flag) | |
169 | (srecode-dictionary-show-section dict "CONST")) | |
170 | ||
171 | ;; If the member function is pure virtual, add a dictionary | |
172 | ;; entry. | |
173 | (when (semantic-tag-get-attribute tag :pure-virtual-flag) | |
174 | (srecode-dictionary-show-section dict "PURE")) | |
b9749554 EL |
175 | ))) |
176 | ||
177 | ;; | |
178 | ;; CLASS | |
179 | ;; | |
180 | ((eq class 'type) | |
181 | ;; For classes, add template parameters. | |
182 | (when (or (semantic-tag-of-type-p tag "class") | |
183 | (semantic-tag-of-type-p tag "struct")) | |
184 | ||
185 | ;; Add templates into child dictionaries. | |
186 | (let ((templates (semantic-tag-get-attribute tag :template))) | |
187 | (srecode-cpp-apply-templates dict templates)))) | |
4d902e6f CY |
188 | )) |
189 | ) | |
190 | ||
b9749554 EL |
191 | \f |
192 | ;;; Helper functions | |
193 | ;; | |
194 | ||
195 | (defun srecode-cpp-apply-templates (dict templates) | |
196 | "Add section dictionaries for TEMPLATES to DICT." | |
197 | (when templates | |
198 | (let ((templates-dict (srecode-dictionary-add-section-dictionary | |
199 | dict "TEMPLATES"))) | |
200 | (dolist (template templates) | |
201 | (let ((template-dict (srecode-dictionary-add-section-dictionary | |
202 | templates-dict "ARGS"))) | |
203 | (srecode-semantic-apply-tag-to-dict | |
204 | (srecode-semantic-tag (semantic-tag-name template) | |
205 | :prime template) | |
206 | template-dict))))) | |
207 | ) | |
208 | ||
4d902e6f CY |
209 | (provide 'srecode/cpp) |
210 | ||
211 | ;; Local variables: | |
212 | ;; generated-autoload-file: "loaddefs.el" | |
4d902e6f CY |
213 | ;; generated-autoload-load-name: "srecode/cpp" |
214 | ;; End: | |
215 | ||
3999968a | 216 | ;; arch-tag: 4659755c-88b4-405e-818f-bb1f776a8e82 |
4d902e6f | 217 | ;;; srecode/cpp.el ends here |