Commit | Line | Data |
---|---|---|
a6de3d1a CY |
1 | ;;; semantic/analyze/complete.el --- Smart Completions |
2 | ||
114f9c96 | 3 | ;; Copyright (C) 2007, 2008, 2009, 2010 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 |
a6de3d1a CY |
66 | (define-overloadable-function semantic-analyze-possible-completions (context) |
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. | |
71 | Completions run through the following filters: | |
72 | * Elements currently in scope | |
73 | * Constants currently in scope | |
74 | * Elements match the :prefix in the CONTEXT. | |
75 | * Type of the completion matches the type of the context. | |
76 | Context type matching can identify the following: | |
77 | * No specific type | |
78 | * Assignment into a variable of some type. | |
79 | * Argument to a function with type constraints. | |
80 | When called interactively, displays the list of possible completions | |
81 | in a buffer." | |
82 | (interactive "d") | |
83 | ;; In theory, we don't need the below since the context will | |
84 | ;; do it for us. | |
85 | ;;(semantic-refresh-tags-safe) | |
86 | (with-syntax-table semantic-lex-syntax-table | |
87 | (let* ((context (if (semantic-analyze-context-child-p context) | |
88 | context | |
89 | (semantic-analyze-current-context context))) | |
90 | (ans (if (not context) | |
9bf6c65c | 91 | (error "Nothing to complete") |
a6de3d1a CY |
92 | (:override)))) |
93 | ;; If interactive, display them. | |
2054a44c | 94 | (when (called-interactively-p 'any) |
a6de3d1a CY |
95 | (with-output-to-temp-buffer "*Possible Completions*" |
96 | (semantic-analyze-princ-sequence ans "" (current-buffer))) | |
97 | (shrink-window-if-larger-than-buffer | |
98 | (get-buffer-window "*Possible Completions*"))) | |
99 | ans))) | |
100 | ||
101 | (defun semantic-analyze-possible-completions-default (context) | |
102 | "Default method for producing smart completions. | |
103 | Argument CONTEXT is an object specifying the locally derived context." | |
104 | (let* ((a context) | |
105 | (desired-type (semantic-analyze-type-constraint a)) | |
106 | (desired-class (oref a prefixclass)) | |
107 | (prefix (oref a prefix)) | |
108 | (prefixtypes (oref a prefixtypes)) | |
109 | (completetext nil) | |
110 | (completetexttype nil) | |
111 | (scope (oref a scope)) | |
112 | (localvar (oref scope localvar)) | |
113 | (c nil)) | |
114 | ||
115 | ;; Calculate what our prefix string is so that we can | |
116 | ;; find all our matching text. | |
117 | (setq completetext (car (reverse prefix))) | |
118 | (if (semantic-tag-p completetext) | |
119 | (setq completetext (semantic-tag-name completetext))) | |
120 | ||
121 | (if (and (not completetext) (not desired-type)) | |
122 | (error "Nothing to complete")) | |
123 | ||
124 | (if (not completetext) (setq completetext "")) | |
125 | ||
126 | ;; This better be a reasonable type, or we should fry it. | |
127 | ;; The prefixtypes should always be at least 1 less than | |
128 | ;; the prefix since the type is never looked up for the last | |
129 | ;; item when calculating a sequence. | |
130 | (setq completetexttype (car (reverse prefixtypes))) | |
131 | (when (or (not completetexttype) | |
132 | (not (and (semantic-tag-p completetexttype) | |
133 | (eq (semantic-tag-class completetexttype) 'type)))) | |
134 | ;; What should I do here? I think this is an error condition. | |
135 | (setq completetexttype nil) | |
136 | ;; If we had something that was a completetexttype but it wasn't | |
137 | ;; valid, then express our dismay! | |
138 | (when (> (length prefix) 1) | |
139 | (let* ((errprefix (car (cdr (reverse prefix))))) | |
140 | (error "Cannot find types for `%s'" | |
141 | (cond ((semantic-tag-p errprefix) | |
142 | (semantic-format-tag-prototype errprefix)) | |
143 | (t | |
144 | (format "%S" errprefix))))) | |
145 | )) | |
146 | ||
147 | ;; There are many places to get our completion stream for. | |
148 | ;; Here we go. | |
149 | (if completetexttype | |
150 | ||
151 | (setq c (semantic-find-tags-for-completion | |
152 | completetext | |
153 | (semantic-analyze-scoped-type-parts completetexttype scope) | |
154 | )) | |
155 | ||
156 | ;; No type based on the completetext. This is a free-range | |
157 | ;; var or function. We need to expand our search beyond this | |
158 | ;; scope into semanticdb, etc. | |
159 | (setq c (nconc | |
160 | ;; Argument list and local variables | |
161 | (semantic-find-tags-for-completion completetext localvar) | |
162 | ;; The current scope | |
163 | (semantic-find-tags-for-completion completetext (oref scope fullscope)) | |
164 | ;; The world | |
165 | (semantic-analyze-find-tags-by-prefix completetext)) | |
166 | ) | |
167 | ) | |
168 | ||
169 | (let ((origc c) | |
170 | (dtname (semantic-tag-name desired-type))) | |
171 | ||
172 | ;; Reset c. | |
173 | (setq c nil) | |
174 | ||
175 | ;; Loop over all the found matches, and catagorize them | |
176 | ;; as being possible features. | |
177 | (while origc | |
178 | ||
179 | (cond | |
180 | ;; Strip operators | |
181 | ((semantic-tag-get-attribute (car origc) :operator-flag) | |
182 | nil | |
183 | ) | |
184 | ||
185 | ;; If we are completing from within some prefix, | |
186 | ;; then we want to exclude constructors and destructors | |
187 | ((and completetexttype | |
188 | (or (semantic-tag-get-attribute (car origc) :constructor-flag) | |
189 | (semantic-tag-get-attribute (car origc) :destructor-flag))) | |
190 | nil | |
191 | ) | |
192 | ||
193 | ;; If there is a desired type, we need a pair of restrictions | |
194 | (desired-type | |
195 | ||
196 | (cond | |
197 | ;; Ok, we now have a completion list based on the text we found | |
198 | ;; we want to complete on. Now filter that stream against the | |
199 | ;; type we want to search for. | |
200 | ((string= dtname (semantic-analyze-type-to-name (semantic-tag-type (car origc)))) | |
201 | (setq c (cons (car origc) c)) | |
202 | ) | |
203 | ||
204 | ;; Now anything that is a compound type which could contain | |
205 | ;; additional things which are of the desired type | |
206 | ((semantic-tag-type (car origc)) | |
207 | (let ((att (semantic-analyze-tag-type (car origc) scope)) | |
208 | ) | |
209 | (if (and att (semantic-tag-type-members att)) | |
210 | (setq c (cons (car origc) c)))) | |
211 | ) | |
212 | ||
213 | ) ; cond | |
214 | ); desired type | |
215 | ||
216 | ;; No desired type, no other restrictions. Just add. | |
217 | (t | |
218 | (setq c (cons (car origc) c))) | |
219 | ||
220 | ); cond | |
221 | ||
222 | (setq origc (cdr origc))) | |
223 | ||
224 | (when desired-type | |
225 | ;; Some types, like the enum in C, have special constant values that | |
226 | ;; we could complete with. Thus, if the target is an enum, we can | |
227 | ;; find possible symbol values to fill in that value. | |
228 | (let ((constants | |
229 | (semantic-analyze-type-constants desired-type))) | |
230 | (if constants | |
231 | (progn | |
232 | ;; Filter | |
233 | (setq constants | |
234 | (semantic-find-tags-for-completion | |
235 | completetext constants)) | |
236 | ;; Add to the list | |
237 | (setq c (nconc c constants))) | |
238 | ))) | |
239 | ) | |
240 | ||
241 | (when desired-class | |
242 | (setq c (semantic-analyze-tags-of-class-list c desired-class))) | |
243 | ||
244 | ;; Pull out trash. | |
245 | ;; NOTE TO SELF: Is this too slow? | |
246 | ;; OTHER NOTE: Do we not want to strip duplicates by name and | |
247 | ;; only by position? When are duplicate by name but not by tag | |
248 | ;; useful? | |
249 | (setq c (semantic-unique-tag-table-by-name c)) | |
250 | ||
251 | ;; All done! | |
252 | ||
253 | c)) | |
254 | ||
a6de3d1a CY |
255 | (provide 'semantic/analyze/complete) |
256 | ||
3d9d8486 CY |
257 | ;; Local variables: |
258 | ;; generated-autoload-file: "../loaddefs.el" | |
06b43459 | 259 | ;; generated-autoload-load-name: "semantic/analyze/complete" |
3d9d8486 CY |
260 | ;; End: |
261 | ||
3999968a | 262 | ;; arch-tag: 97071c7e-2459-4e7a-8875-8cc5bbbc1f4d |
a6de3d1a | 263 | ;;; semantic/analyze/complete.el ends here |