Commit | Line | Data |
---|---|---|
a6de3d1a CY |
1 | ;;; semantic/analyze/complete.el --- Smart Completions |
2 | ||
5df4f04c | 3 | ;; Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. |
a6de3d1a CY |
4 | |
5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | |
6 | ||
7 | ;; This file is part of GNU Emacs. | |
8 | ||
9 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
10 | ;; it under the terms of the GNU General Public License as published by | |
11 | ;; the Free Software Foundation, either version 3 of the License, or | |
12 | ;; (at your option) any later version. | |
13 | ||
14 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | ;; GNU General Public License for more details. | |
18 | ||
19 | ;; You should have received a copy of the GNU General Public License | |
20 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;;; Commentary: | |
23 | ;; | |
9bf6c65c | 24 | ;; Calculate smart completions. |
a6de3d1a CY |
25 | ;; |
26 | ;; Uses the analyzer context routine to determine the best possible | |
27 | ;; list of completions. | |
28 | ;; | |
29 | ;;; History: | |
30 | ;; | |
31 | ;; Code was moved here from semantic-analyze.el | |
32 | ||
33 | (require 'semantic/analyze) | |
34 | ||
06b43459 CY |
35 | ;; For semantic-find-* macros: |
36 | (eval-when-compile (require 'semantic/find)) | |
37 | ||
a6de3d1a CY |
38 | ;;; Code: |
39 | ||
40 | ;;; Helper Fcns | |
41 | ;; | |
42 | ;; | |
55b522b2 | 43 | ;;;###autoload |
a6de3d1a CY |
44 | (define-overloadable-function semantic-analyze-type-constants (type) |
45 | "For the tag TYPE, return any constant symbols of TYPE. | |
46 | Used as options when completing.") | |
47 | ||
48 | (defun semantic-analyze-type-constants-default (type) | |
49 | "Do nothing with TYPE." | |
50 | nil) | |
51 | ||
a6de3d1a CY |
52 | (defun semantic-analyze-tags-of-class-list (tags classlist) |
53 | "Return the tags in TAGS that are of classes in CLASSLIST." | |
54 | (let ((origc tags)) | |
55 | ;; Accept only tags that are of the datatype specified by | |
56 | ;; the desired classes. | |
57 | (setq tags (apply 'nconc ;; All input lists are permutable. | |
58 | (mapcar (lambda (class) | |
59 | (semantic-find-tags-by-class class origc)) | |
60 | classlist))) | |
61 | tags)) | |
62 | ||
63 | ;;; MAIN completion calculator | |
64 | ;; | |
3d9d8486 | 65 | ;;;###autoload |
dd9af436 | 66 | (define-overloadable-function semantic-analyze-possible-completions (context &rest flags) |
a6de3d1a CY |
67 | "Return a list of semantic tags which are possible completions. |
68 | CONTEXT is either a position (such as point), or a precalculated | |
69 | context. Passing in a context is useful if the caller also needs | |
70 | to access parts of the analysis. | |
dd9af436 CY |
71 | The remaining FLAGS arguments are passed to the mode specific completion engine. |
72 | Bad flags should be ignored by modes that don't use them. | |
73 | See `semantic-analyze-possible-completions-default' for details on the default FLAGS. | |
74 | ||
a6de3d1a CY |
75 | Completions run through the following filters: |
76 | * Elements currently in scope | |
77 | * Constants currently in scope | |
78 | * Elements match the :prefix in the CONTEXT. | |
79 | * Type of the completion matches the type of the context. | |
80 | Context type matching can identify the following: | |
81 | * No specific type | |
82 | * Assignment into a variable of some type. | |
83 | * Argument to a function with type constraints. | |
84 | When called interactively, displays the list of possible completions | |
85 | in a buffer." | |
86 | (interactive "d") | |
87 | ;; In theory, we don't need the below since the context will | |
88 | ;; do it for us. | |
89 | ;;(semantic-refresh-tags-safe) | |
90 | (with-syntax-table semantic-lex-syntax-table | |
91 | (let* ((context (if (semantic-analyze-context-child-p context) | |
92 | context | |
93 | (semantic-analyze-current-context context))) | |
94 | (ans (if (not context) | |
9bf6c65c | 95 | (error "Nothing to complete") |
a6de3d1a CY |
96 | (:override)))) |
97 | ;; If interactive, display them. | |
2054a44c | 98 | (when (called-interactively-p 'any) |
a6de3d1a CY |
99 | (with-output-to-temp-buffer "*Possible Completions*" |
100 | (semantic-analyze-princ-sequence ans "" (current-buffer))) | |
101 | (shrink-window-if-larger-than-buffer | |
102 | (get-buffer-window "*Possible Completions*"))) | |
103 | ans))) | |
104 | ||
dd9af436 | 105 | (defun semantic-analyze-possible-completions-default (context &optional flags) |
a6de3d1a | 106 | "Default method for producing smart completions. |
dd9af436 CY |
107 | Argument CONTEXT is an object specifying the locally derived context. |
108 | The optional argument FLAGS changes which return options are returned. | |
109 | FLAGS can be any number of: | |
110 | 'no-tc - do not apply data-type constraint. | |
111 | 'no-unique - do not apply unique by name filtering." | |
a6de3d1a CY |
112 | (let* ((a context) |
113 | (desired-type (semantic-analyze-type-constraint a)) | |
114 | (desired-class (oref a prefixclass)) | |
115 | (prefix (oref a prefix)) | |
116 | (prefixtypes (oref a prefixtypes)) | |
117 | (completetext nil) | |
118 | (completetexttype nil) | |
119 | (scope (oref a scope)) | |
dd9af436 CY |
120 | (localvar (when scope (oref scope localvar))) |
121 | (origc nil) | |
122 | (c nil) | |
123 | (any nil) | |
124 | (do-typeconstraint (not (memq 'no-tc flags))) | |
125 | (do-unique (not (memq 'no-unique flags))) | |
126 | ) | |
a6de3d1a CY |
127 | |
128 | ;; Calculate what our prefix string is so that we can | |
129 | ;; find all our matching text. | |
130 | (setq completetext (car (reverse prefix))) | |
131 | (if (semantic-tag-p completetext) | |
132 | (setq completetext (semantic-tag-name completetext))) | |
133 | ||
134 | (if (and (not completetext) (not desired-type)) | |
135 | (error "Nothing to complete")) | |
136 | ||
137 | (if (not completetext) (setq completetext "")) | |
138 | ||
139 | ;; This better be a reasonable type, or we should fry it. | |
140 | ;; The prefixtypes should always be at least 1 less than | |
141 | ;; the prefix since the type is never looked up for the last | |
142 | ;; item when calculating a sequence. | |
143 | (setq completetexttype (car (reverse prefixtypes))) | |
144 | (when (or (not completetexttype) | |
145 | (not (and (semantic-tag-p completetexttype) | |
146 | (eq (semantic-tag-class completetexttype) 'type)))) | |
147 | ;; What should I do here? I think this is an error condition. | |
148 | (setq completetexttype nil) | |
149 | ;; If we had something that was a completetexttype but it wasn't | |
150 | ;; valid, then express our dismay! | |
151 | (when (> (length prefix) 1) | |
152 | (let* ((errprefix (car (cdr (reverse prefix))))) | |
153 | (error "Cannot find types for `%s'" | |
154 | (cond ((semantic-tag-p errprefix) | |
155 | (semantic-format-tag-prototype errprefix)) | |
156 | (t | |
157 | (format "%S" errprefix))))) | |
158 | )) | |
159 | ||
160 | ;; There are many places to get our completion stream for. | |
161 | ;; Here we go. | |
162 | (if completetexttype | |
163 | ||
164 | (setq c (semantic-find-tags-for-completion | |
165 | completetext | |
166 | (semantic-analyze-scoped-type-parts completetexttype scope) | |
167 | )) | |
168 | ||
169 | ;; No type based on the completetext. This is a free-range | |
170 | ;; var or function. We need to expand our search beyond this | |
171 | ;; scope into semanticdb, etc. | |
172 | (setq c (nconc | |
173 | ;; Argument list and local variables | |
174 | (semantic-find-tags-for-completion completetext localvar) | |
175 | ;; The current scope | |
dd9af436 | 176 | (semantic-find-tags-for-completion completetext (when scope (oref scope fullscope))) |
a6de3d1a CY |
177 | ;; The world |
178 | (semantic-analyze-find-tags-by-prefix completetext)) | |
179 | ) | |
180 | ) | |
181 | ||
dd9af436 | 182 | (let ((loopc c) |
a6de3d1a CY |
183 | (dtname (semantic-tag-name desired-type))) |
184 | ||
dd9af436 CY |
185 | ;; Save off our first batch of completions |
186 | (setq origc c) | |
187 | ||
a6de3d1a CY |
188 | ;; Reset c. |
189 | (setq c nil) | |
190 | ||
191 | ;; Loop over all the found matches, and catagorize them | |
192 | ;; as being possible features. | |
dd9af436 | 193 | (while (and loopc do-typeconstraint) |
a6de3d1a CY |
194 | |
195 | (cond | |
196 | ;; Strip operators | |
dd9af436 | 197 | ((semantic-tag-get-attribute (car loopc) :operator-flag) |
a6de3d1a CY |
198 | nil |
199 | ) | |
200 | ||
201 | ;; If we are completing from within some prefix, | |
202 | ;; then we want to exclude constructors and destructors | |
203 | ((and completetexttype | |
dd9af436 CY |
204 | (or (semantic-tag-get-attribute (car loopc) :constructor-flag) |
205 | (semantic-tag-get-attribute (car loopc) :destructor-flag))) | |
a6de3d1a CY |
206 | nil |
207 | ) | |
208 | ||
209 | ;; If there is a desired type, we need a pair of restrictions | |
210 | (desired-type | |
211 | ||
212 | (cond | |
213 | ;; Ok, we now have a completion list based on the text we found | |
214 | ;; we want to complete on. Now filter that stream against the | |
215 | ;; type we want to search for. | |
dd9af436 CY |
216 | ((string= dtname (semantic-analyze-type-to-name (semantic-tag-type (car loopc)))) |
217 | (setq c (cons (car loopc) c)) | |
a6de3d1a CY |
218 | ) |
219 | ||
220 | ;; Now anything that is a compound type which could contain | |
221 | ;; additional things which are of the desired type | |
dd9af436 CY |
222 | ((semantic-tag-type (car loopc)) |
223 | (let ((att (semantic-analyze-tag-type (car loopc) scope)) | |
a6de3d1a CY |
224 | ) |
225 | (if (and att (semantic-tag-type-members att)) | |
dd9af436 | 226 | (setq c (cons (car loopc) c)))) |
a6de3d1a CY |
227 | ) |
228 | ||
229 | ) ; cond | |
230 | ); desired type | |
231 | ||
232 | ;; No desired type, no other restrictions. Just add. | |
233 | (t | |
dd9af436 | 234 | (setq c (cons (car loopc) c))) |
a6de3d1a CY |
235 | |
236 | ); cond | |
237 | ||
dd9af436 | 238 | (setq loopc (cdr loopc))) |
a6de3d1a CY |
239 | |
240 | (when desired-type | |
241 | ;; Some types, like the enum in C, have special constant values that | |
242 | ;; we could complete with. Thus, if the target is an enum, we can | |
243 | ;; find possible symbol values to fill in that value. | |
244 | (let ((constants | |
245 | (semantic-analyze-type-constants desired-type))) | |
246 | (if constants | |
247 | (progn | |
248 | ;; Filter | |
249 | (setq constants | |
250 | (semantic-find-tags-for-completion | |
251 | completetext constants)) | |
252 | ;; Add to the list | |
253 | (setq c (nconc c constants))) | |
254 | ))) | |
255 | ) | |
256 | ||
257 | (when desired-class | |
258 | (setq c (semantic-analyze-tags-of-class-list c desired-class))) | |
259 | ||
dd9af436 CY |
260 | (if do-unique |
261 | (if c | |
262 | ;; Pull out trash. | |
263 | ;; NOTE TO SELF: Is this too slow? | |
264 | (setq c (semantic-unique-tag-table-by-name c)) | |
265 | (setq c (semantic-unique-tag-table-by-name origc))) | |
266 | (when (not c) | |
267 | (setq c origc))) | |
a6de3d1a CY |
268 | |
269 | ;; All done! | |
a6de3d1a CY |
270 | c)) |
271 | ||
a6de3d1a CY |
272 | (provide 'semantic/analyze/complete) |
273 | ||
3d9d8486 CY |
274 | ;; Local variables: |
275 | ;; generated-autoload-file: "../loaddefs.el" | |
06b43459 | 276 | ;; generated-autoload-load-name: "semantic/analyze/complete" |
3d9d8486 CY |
277 | ;; End: |
278 | ||
3999968a | 279 | ;; arch-tag: 97071c7e-2459-4e7a-8875-8cc5bbbc1f4d |
a6de3d1a | 280 | ;;; semantic/analyze/complete.el ends here |