DOCUMENTATION injects deprecation notes into docstrings
[sbcl.git] / src / pcl / documentation.lisp
blob86c1ee8685f3600cbef7f94c9d9ef59654cf8189
1 ;;;; implementation of CL:DOCUMENTATION
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
6 ;;;; This software is in the public domain and is provided with absolutely no
7 ;;;; warranty. See the COPYING and CREDITS files for more information.
9 (in-package "SB-PCL")
11 (defun fun-doc (x)
12 (if (typep x 'generic-function)
13 (slot-value x '%documentation)
14 (%fun-doc x)))
16 (defun (setf fun-doc) (new-value x)
17 (if (typep x 'generic-function)
18 (setf (slot-value x '%documentation) new-value)
19 (setf (%fun-doc x) new-value)))
21 ;;; FIXME: There's already fun-name in code/describe.lisp, but it's
22 ;;; loaded after PCL, so it cannot be used, because we set
23 ;;; some documentation at the end of this file.
24 (defun fun-name (x)
25 (if (typep x 'generic-function)
26 (sb-pcl:generic-function-name x)
27 (%fun-name x)))
29 (defun real-function-name (name)
30 ;; Resolve the actual name of the function named by NAME
31 ;; e.g. (setf (name-function 'x) #'car)
32 ;; (real-function-name 'x) => CAR
33 (cond ((not (fboundp name))
34 nil)
35 ((and (symbolp name)
36 (special-operator-p name))
37 (%fun-name (fdefinition name)))
38 ((and (symbolp name)
39 (macro-function name))
40 (let ((name (%fun-name (macro-function name))))
41 (and (consp name)
42 (eq (car name) 'macro-function)
43 (cadr name))))
45 (fun-name (fdefinition name)))))
47 (defun ignore-nil-doc (type)
48 (style-warn "Ignoring documentation of type ~a for ~a."
49 type nil))
51 (defun set-function-name-documentation (name documentation)
52 (cond ((not name)
53 (ignore-nil-doc 'function))
54 ((not (legal-fun-name-p name))
55 nil)
56 ((not (equal (real-function-name name) name))
57 (setf (random-documentation name 'function) documentation))
59 (setf (fun-doc (or (and (symbolp name)
60 (macro-function name))
61 (fdefinition name)))
62 documentation)))
63 documentation)
65 ;;; Deprecation note
67 (defun maybe-add-deprecation-note (namespace name documentation)
68 (unless (member namespace '(function variable type))
69 (return-from maybe-add-deprecation-note documentation))
70 (binding* (((state since replacements)
71 (deprecated-thing-p namespace name))
72 (note (when state
73 (with-output-to-string (stream)
74 (sb-impl::print-deprecation-message
75 'function name (first since) (second since)
76 replacements stream)))))
77 (cond
78 ((and documentation note)
79 (concatenate
80 'string note #.(format nil "~2%") documentation))
81 (documentation)
82 (note))))
84 (defmethod documentation :around ((x t) (doc-type t))
85 (let ((namespace (cond
86 ((typep x 'function)
87 'function)
88 ((eq doc-type 'compiler-macro)
89 'function)
90 ((typep x 'class)
91 'type)
92 ((eq doc-type 'structure)
93 'type)
95 doc-type)))
96 (name (cond
97 ((typep x 'function)
98 (fun-name x))
99 ((typep x 'class)
100 (class-name x))
102 x)))
103 (documentation (call-next-method)))
104 (maybe-add-deprecation-note namespace name documentation)))
106 ;;; functions, macros, and special forms
108 (flet ((maybe-function-documentation (name)
109 (cond
110 ((not (legal-fun-name-p name)))
111 ((random-documentation name 'function))
112 ;; Nothing under the name, check the function object.
113 ((fboundp name)
114 (fun-doc (cond
115 ((and (symbolp name) (special-operator-p name))
116 (fdefinition name))
117 ((and (symbolp name) (macro-function name)))
118 ((fdefinition name))))))))
120 (defmethod documentation ((x function) (doc-type (eql 't)))
121 (fun-doc x))
123 (defmethod documentation ((x function) (doc-type (eql 'function)))
124 (fun-doc x))
126 (defmethod documentation ((x list) (doc-type (eql 'compiler-macro)))
127 (awhen (compiler-macro-function x)
128 (documentation it t)))
130 (defmethod documentation ((x list) (doc-type (eql 'function)))
131 (maybe-function-documentation x))
133 (defmethod documentation ((x symbol) (doc-type (eql 'function)))
134 (maybe-function-documentation x))
136 (defmethod documentation ((x symbol) (doc-type (eql 'compiler-macro)))
137 (awhen (compiler-macro-function x)
138 (documentation it t)))
140 (defmethod documentation ((x symbol) (doc-type (eql 'setf)))
141 (fdocumentation x 'setf)))
143 (defmethod documentation ((x symbol) (doc-type (eql 'optimize)))
144 (random-documentation x 'optimize))
146 (defmethod (setf documentation) (new-value (x function) (doc-type (eql 't)))
147 (setf (fun-doc x) new-value))
149 (defmethod (setf documentation) (new-value (x function) (doc-type (eql 'function)))
150 (setf (fun-doc x) new-value))
152 (defmethod (setf documentation) (new-value (x list) (doc-type (eql 'function)))
153 (set-function-name-documentation x new-value))
155 (defmethod (setf documentation) (new-value (x list) (doc-type (eql 'compiler-macro)))
156 (awhen (compiler-macro-function x)
157 (setf (documentation it t) new-value)))
159 (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'function)))
160 (set-function-name-documentation x new-value))
162 (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'compiler-macro)))
163 (cond (x
164 (awhen (compiler-macro-function x)
165 (setf (documentation it t) new-value)))
167 (ignore-nil-doc 'compiler-macro)
168 new-value)))
170 (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'setf)))
171 (cond (x
172 (setf (fdocumentation x 'setf) new-value))
174 (ignore-nil-doc 'setf)
175 new-value)))
177 ;;; method combinations
178 (defmethod documentation ((x method-combination) (doc-type (eql 't)))
179 (slot-value x '%documentation))
181 (defmethod documentation
182 ((x method-combination) (doc-type (eql 'method-combination)))
183 (slot-value x '%documentation))
185 (defmethod documentation ((x symbol) (doc-type (eql 'method-combination)))
186 (random-documentation x 'method-combination))
188 (defmethod (setf documentation)
189 (new-value (x method-combination) (doc-type (eql 't)))
190 (setf (slot-value x '%documentation) new-value))
192 (defmethod (setf documentation)
193 (new-value (x method-combination) (doc-type (eql 'method-combination)))
194 (setf (slot-value x '%documentation) new-value))
196 (defmethod (setf documentation)
197 (new-value (x symbol) (doc-type (eql 'method-combination)))
198 (cond (x
199 (setf (random-documentation x 'method-combination) new-value))
201 (ignore-nil-doc 'method-combination)
202 new-value)))
204 ;;; methods
205 (defmethod documentation ((x standard-method) (doc-type (eql 't)))
206 (slot-value x '%documentation))
208 (defmethod (setf documentation)
209 (new-value (x standard-method) (doc-type (eql 't)))
210 (setf (slot-value x '%documentation) new-value))
212 ;;; packages
214 ;;; KLUDGE: It's nasty having things like this accessor
215 ;;; (PACKAGE-DOC-STRING) floating around out in this mostly-unrelated
216 ;;; source file. Perhaps it would be better to support WARM-INIT-FORMS
217 ;;; by analogy with the existing !COLD-INIT-FORMS and have them be
218 ;;; EVAL'ed after basic warm load is done? That way things like this
219 ;;; could be defined alongside the other code which does low-level
220 ;;; hacking of packages.. -- WHN 19991203
222 (defmethod documentation ((x package) (doc-type (eql 't)))
223 (package-doc-string x))
225 (defmethod (setf documentation) (new-value (x package) (doc-type (eql 't)))
226 (setf (package-doc-string x) new-value))
228 ;;; types, classes, and structure names
229 (defmethod documentation ((x structure-class) (doc-type (eql 't)))
230 (fdocumentation (class-name x) 'type))
232 (defmethod documentation ((x structure-class) (doc-type (eql 'type)))
233 (fdocumentation (class-name x) 'type))
235 (defmethod documentation ((x class) (doc-type (eql 't)))
236 (slot-value x '%documentation))
238 (defmethod documentation ((x class) (doc-type (eql 'type))) ; TODO setf
239 (slot-value x '%documentation))
241 (defmethod (setf documentation) (new-value
242 (x class)
243 (doc-type (eql 't)))
244 (setf (slot-value x '%documentation) new-value))
246 (defmethod (setf documentation) (new-value
247 (x class)
248 (doc-type (eql 'type)))
249 (setf (slot-value x '%documentation) new-value))
251 ;;; although the CLHS doesn't mention this, it is reasonable to assume
252 ;;; that parallel treatment of condition-class was intended (if
253 ;;; condition-class is in fact not implemented as a standard-class or
254 ;;; structure-class).
255 (defmethod documentation ((x condition-class) (doc-type (eql 't)))
256 (fdocumentation (class-name x) 'type))
258 (defmethod documentation ((x condition-class) (doc-type (eql 'type)))
259 (fdocumentation (class-name x) 'type))
261 (defmethod documentation ((x symbol) (doc-type (eql 'type)))
262 (or (fdocumentation x 'type)
263 (awhen (find-class x nil)
264 (slot-value it '%documentation))))
266 (defmethod documentation ((x symbol) (doc-type (eql 'structure)))
267 (fdocumentation x 'structure))
269 (defmethod (setf documentation) (new-value
270 (x structure-class)
271 (doc-type (eql 't)))
272 (setf (fdocumentation (class-name x) 'type) new-value))
274 (defmethod (setf documentation) (new-value
275 (x structure-class)
276 (doc-type (eql 'type)))
277 (setf (fdocumentation (class-name x) 'type) new-value))
279 (defmethod (setf documentation) (new-value
280 (x condition-class)
281 (doc-type (eql 't)))
282 (setf (fdocumentation (class-name x) 'type) new-value))
284 (defmethod (setf documentation) (new-value
285 (x condition-class)
286 (doc-type (eql 'type)))
287 (setf (fdocumentation (class-name x) 'type) new-value))
289 (defmethod (setf documentation) (new-value (x symbol) (doc-type (eql 'type)))
290 (if (or (structure-type-p x) (condition-type-p x))
291 (setf (fdocumentation x 'type) new-value)
292 (let ((class (find-class x nil)))
293 (if class
294 (setf (slot-value class '%documentation) new-value)
295 (setf (fdocumentation x 'type) new-value)))))
297 (defmethod (setf documentation) (new-value
298 (x symbol)
299 (doc-type (eql 'structure)))
300 (cond (x
301 (setf (fdocumentation x 'structure) new-value))
303 (ignore-nil-doc 'structure)
304 new-value)))
306 ;;; variables
307 (defmethod documentation ((x symbol) (doc-type (eql 'variable)))
308 (fdocumentation x 'variable))
310 (defmethod (setf documentation) (new-value
311 (x symbol)
312 (doc-type (eql 'variable)))
313 (cond (x
314 (setf (fdocumentation x 'variable) new-value))
316 (ignore-nil-doc 'variable)
317 new-value)))
319 ;;; default if DOC-TYPE doesn't match one of the specified types
320 (defmethod documentation (object doc-type)
321 (warn "unsupported DOCUMENTATION: type ~S for object of type ~S"
322 doc-type
323 (type-of object))
324 nil)
326 ;;; default if DOC-TYPE doesn't match one of the specified types
327 (defmethod (setf documentation) (new-value object doc-type)
328 ;; CMU CL made this an error, but since ANSI says that even for supported
329 ;; doc types an implementation is permitted to discard docs at any time
330 ;; for any reason, this feels to me more like a warning. -- WHN 19991214
331 (warn "discarding unsupported DOCUMENTATION of type ~S for object ~S"
332 doc-type
333 (type-of object))
334 new-value)
336 ;;; extra-standard methods, for getting at slot documentation
337 (defmethod documentation ((slotd standard-slot-definition) (doc-type (eql 't)))
338 (declare (ignore doc-type))
339 (slot-value slotd '%documentation))
341 (defmethod (setf documentation)
342 (new-value (slotd standard-slot-definition) (doc-type (eql 't)))
343 (declare (ignore doc-type))
344 (setf (slot-value slotd '%documentation) new-value))
346 ;;; Now that we have created the machinery for setting documentation, we can
347 ;;; set the documentation for the machinery for setting documentation.
348 #+sb-doc
349 (setf (documentation 'documentation 'function)
350 "Return the documentation string of Doc-Type for X, or NIL if none
351 exists. System doc-types are VARIABLE, FUNCTION, STRUCTURE, TYPE, SETF, and T.
353 Function documentation is stored separately for function names and objects:
354 DEFUN, LAMBDA, &co create function objects with the specified documentation
355 strings.
357 \(SETF (DOCUMENTATION NAME 'FUNCTION) STRING)
359 sets the documentation string stored under the specified name, and
361 \(SETF (DOCUMENTATION FUNC T) STRING)
363 sets the documentation string stored in the function object.
365 \(DOCUMENTATION NAME 'FUNCTION)
367 returns the documentation stored under the function name if any, and
368 falls back on the documentation in the function object if necessary.")