Fix bug with pretty-print-validate-packages
[sheep] / src / main / docgen.lisp
1 (in-package #:docgen)
2
3 (define-condition validation-failure nil ((msg :initarg :msg :reader validation-failure-msg))
4  (:documentation "Used internally for docgen parts to signal a validation error."))
5
6 (defun get-symb-type (symb)
7  (cond
8   ;((documentation symb 'variable) :variable)
9   ((documentation symb 'structure) :structure)
10   ((documentation symb 'function) :function)))
11
12 (defun validate-package (pkg)
13  "VALIDATE-PACKAGE PKG => FAILURES
14
15   FAILURES: FAILURE*
16   FAILURE: (:failure SYMB MSG)
17
18 ARGUMENTS AND VALUES:
19
20   PKG: A package symbol
21   SYMB: Symbol the check failed on
22   MSG: Message containing information about the failure
23
24 DESCRIPTION:
25
26   VALIDATE-PACKAGE takes in PKG and validates that all the external symbols
27   adhere to documentation guidelines, exist, and can be parsed to be used
28   for exporting.
29
30   Only one error per symbol will be reported at a time, all concatenated to
31   a list in the aforementioned form."
32  (macrolet
33   ((with-success-check (symb &rest f)
34     `(handler-case
35       (progn ,@f :success)
36       (validation-failure (v) (list :failure ,symb (validation-failure-msg v))))))
37   (let
38    ((symbs nil))
39    (do-external-symbols (symb pkg) (push symb symbs))
40    (setf symbs (sort symbs #'string< :key #'symbol-name))
41    (remove :success
42     (append
43      (list (with-success-check pkg (docgen-pkg:doc->ast (find-package pkg))))
44      (mapcar
45       (lambda (symb)
46        (with-success-check symb
47         (case (get-symb-type symb)
48          (:function (docgen-func:doc->ast symb))
49          (:structure (docgen-struc:doc->ast symb))
50          (t (error (make-condition 'validation-failure :msg (format nil "Symbol ~A has no documentation" symb)))))))
51       symbs))))))
52
53 (defun pretty-print-validate-packages (&rest pkgs)
54  "PRETTY-PRINT-VALIDATE-PACKAGES &rest PKGS => SUCCESS
55
56   PKGS: PKG*
57
58 ARGUMENTS AND VALUES:
59
60   SUCCESS: Whether or not all symbols passed validation
61   PKG: A package symbol
62
63 DESCRIPTION:
64
65   PRETTY-PRINT-VALIDATE-PACKAGES takes PKGS and runs validation on all of them.
66   It dumps to standard out failures as it comes upon them, finally returning
67   whether it was successful or not.
68
69   This can be used in travis tests to ensure that documentation can be generated
70   at a later date.
71
72 EXAMPLES:
73
74   (pretty-print-validate-packages :pkg1 :pkg2) => t"
75  (every
76   #'identity
77   (mapcar
78    (lambda (pkg)
79     (let
80      ((failures (validate-package pkg)))
81      (mapcar
82       (lambda (failure)
83        (format t "In ~A : ~A, documentation error found:~%  ~A~%" pkg (second failure) (third failure)))
84       failures)
85      (not failures)))
86    pkgs)))
87
88 (defun table-of-contents (pkg)
89  (format nil "## Contents~%~%~{~{* **~A [~A](#~A)** - ~A~}~%~}"
90   (let
91    ((symbs nil))
92    (do-external-symbols (symb pkg) (push symb symbs))
93    (setf symbs (sort symbs #'string< :key #'symbol-name))
94    (mapcar
95     (lambda (symb)
96      (case (get-symb-type symb)
97       (:function
98        (list
99         (docgen-func:ast->category-name (docgen-func:doc->ast symb))
100         (docgen-func:ast->short-name (docgen-func:doc->ast symb))
101         (docgen-func:ast->link (docgen-func:doc->ast symb))
102         (docgen-func:ast->short-desc (docgen-func:doc->ast symb))))
103       (:structure
104        (list
105         (docgen-struc:ast->category-name (docgen-struc:doc->ast symb))
106         (docgen-struc:ast->short-name (docgen-struc:doc->ast symb))
107         (docgen-struc:ast->link (docgen-struc:doc->ast symb))
108         (docgen-struc:ast->short-desc (docgen-struc:doc->ast symb))))))
109     symbs))))
110
111 (defun export-package (pkg)
112  "EXPORT-PACKAGE PKG => MARKDOWN
113
114 ARGUMENTS AND VALUES:
115
116   PKG: A package symbol
117   MARKDOWN: A string containing the markdown representation of this packages documentation
118
119 DESCRIPTION:
120
121   EXPORT-PACKAGE takes in PKG and converts all the documentation for the symbols
122   into markdown with the hope of emulating the hyperspec style.
123
124   It should only be run after the package has been validated, as it assumes that
125   all documentation it gets will be valid."
126  (let
127   ((symbs nil))
128   (do-external-symbols (symb pkg) (push symb symbs))
129   (setf symbs (sort symbs #'string< :key #'symbol-name))
130   (with-output-to-string (str)
131    (format str "~A~%~%" (docgen-pkg:ast->md (docgen-pkg:doc->ast (find-package pkg))))
132    (format str "~A~%" (table-of-contents pkg))
133    (format str "~{~A~^~%~}"
134     (mapcar
135      (lambda (symb)
136       (case (get-symb-type symb)
137        (:function (docgen-func:ast->md (docgen-func:doc->ast symb)))
138        (:structure (docgen-struc:ast->md (docgen-struc:doc->ast symb)))))
139      symbs)))))