137
|
1
|
;;; lib/doc/package.lisp --- Package Documentation |
|
2
|
|
262
|
3
|
;; Package documentation abstractions and machinery |
|
4
|
|
|
5
|
;;; Commentary: |
|
6
|
|
|
7
|
;; We usually think of packages as composed of one or more files, but |
|
8
|
;; this is not always the case in Lisp. Packages can be defined in a |
|
9
|
;; REPL with no underlying source files, or via macros, which can |
|
10
|
;; obfuscate the origin of a form. |
|
11
|
|
|
12
|
;; The good news is that packages are 'real' objects that are exposed |
|
13
|
;; to us after load-time. If we are willing to wait for the packages |
|
14
|
;; to actually be loaded in a Lisp image before attempting to compile |
|
15
|
;; 'package documentation' this makes everything incredibly easy with |
|
16
|
;; SB-INTROSPECT and friends. |
|
17
|
|
|
18
|
;; All that remains is to provide an interface for linking the various |
|
19
|
;; downstream *-DOCUMENTATION objects with a compiled |
|
20
|
;; PACKAGE-DEFINITION object. |
|
21
|
|
|
22
|
;; The logical next step is linking PACKAGE-DOCUMENTATION objects with |
|
23
|
;; other PACKAGE-DEFINITIONs. |
137
|
24
|
|
|
25
|
;;; Code: |
|
26
|
(in-package :doc) |
262
|
27
|
|
|
28
|
(defclass package-documentation () |
|
29
|
((package :initform *package* :initarg :package :type package :accessor doc-package) |
|
30
|
(files :initform #() :initarg :files :type (array file-documentation) :accessor doc-files) |
|
31
|
(symbols :initform #() :initarg :symbols :type (array symbol-documentation) :accessor doc-symbols))) |
|
32
|
|
|
33
|
(defun package-documentation (&optional package (for :external)) |
|
34
|
"Return a PACKAGE-DOCUMENTATION object from PACKAGE." |
|
35
|
(unless (packagep package) |
|
36
|
(if (or (null package) (eq t package)) |
|
37
|
(setf package *package*) |
|
38
|
(setf package (find-package package)))) |
|
39
|
(let ((paths) |
|
40
|
(symbols (make-array (sb-c::package-external-symbol-count package) |
|
41
|
:element-type 'symbol-documentation |
|
42
|
:fill-pointer 0))) |
|
43
|
;; TODO: we always want external symbols, we need XOR |
|
44
|
(case for |
|
45
|
(:internal (do-symbols* (s package) |
|
46
|
(let ((doc (symbol-documentation s))) |
|
47
|
(dolist (p (symbol-doc-files doc)) |
|
48
|
(pushnew p paths)) |
|
49
|
(vector-push-extend doc symbols 8)))) |
|
50
|
(:external (do-external-symbols (s package) |
|
51
|
(let ((doc (symbol-documentation s))) |
|
52
|
(dolist (p (symbol-doc-files doc)) |
|
53
|
(pushnew p paths)) |
|
54
|
(vector-push doc symbols)))) |
|
55
|
(t (loop for s being each present-symbol in package |
|
56
|
do (let ((doc (symbol-documentation s))) |
|
57
|
(dolist (p (symbol-doc-files doc)) |
|
58
|
(unless (null p) |
|
59
|
(pushnew p paths))) |
|
60
|
(vector-push doc symbols))))) |
|
61
|
(make-instance 'package-documentation |
|
62
|
:package package |
|
63
|
:files (map 'vector #'file-documentation paths) |
|
64
|
:symbols symbols))) |
|
65
|
|
|
66
|
(defmethod print-object ((self package-documentation) stream) |
|
67
|
(with-slots (package files symbols) self |
|
68
|
(print-unreadable-object (self stream :type t) |
|
69
|
(format stream "~A :symbols ~A :files ~A" (package-name package) (length symbols) (length files))))) |
|
70
|
|
|
71
|
;; (package-used-by-list (doc-package (package-documentation (find-package :std)))) |
|
72
|
;; (sb-introspect:allocation-information (make-instance 'package-documentation)) |
|
73
|
;; sb-introspect:definition-source |
|
74
|
|
|
75
|
;; (sb-introspect::object-size-histogram :static) |
|
76
|
;; (sb-introspect:find-definition-source (find-package :doc)) |
|
77
|
;; (sb-introspect:find-definition-sources-by-name 'std-error :condition) |
|
78
|
|
|
79
|
;; (package-documentation) |