diff --git a/src/doctest.lisp b/src/doctest.lisp index f592d73..a1a17bb 100644 --- a/src/doctest.lisp +++ b/src/doctest.lisp @@ -255,13 +255,28 @@ (with-input-from-string (docstring (or documentation "")) (run-doctests docstring output))) +(defun parse-lambda-body (body) + (values (and (stringp (car body)) (cdr body) (pop body)) + (and (consp (car body)) (eq 'declare (caar body)) (pop body)) + body)) + +(defun parse-function-lambda-expression (function) + (multiple-value-bind (lambda-expression closure-p name) (function-lambda-expression function) + (declare (ignore closure-p)) + (let ((parameters (cadr lambda-expression)) + (lambda-body (cddr lambda-expression))) + (multiple-value-bind (docstring declare body) (parse-lambda-body lambda-body) + (values name parameters docstring declare body))))) + (defun extract-function-documentation-and-name (function) ;; ABCL doesn't give documentation for (documentation function 'function) for all expressions. ;; We try function-lambda-expression too - (multiple-value-bind (lambda-expression closure-p name) (function-lambda-expression function) - (declare (ignore closure-p)) - (values (or (documentation function 'function) (third lambda-expression)) - (symbol-name name)))) + (multiple-value-bind (name parameters docstring declare body) (parse-function-lambda-expression function) + (declare (ignore parameters declare body)) + (values (or (documentation function 'function) + docstring + "") + name))) (defun test-function (function &key (output t)) "Test-function extracts and tests code snippets in 's documentation diff --git a/tests/doctest.lisp b/tests/doctest.lisp index c41cd8e..608b929 100644 --- a/tests/doctest.lisp +++ b/tests/doctest.lisp @@ -16,6 +16,39 @@ (assert-equalp expected-output actual-output)) (values (first result) (second result)))) +(defun test-parse-function-lambda-expression (function &key + (expected-parameters nil) + (expected-docstring nil) + (expected-declare nil) + (expected-body nil)) + (multiple-value-bind (name parameters docstring declare body) (doctest::parse-function-lambda-expression function) + (assert-true name) + (assert-equalp expected-parameters parameters) + (assert-equalp expected-docstring docstring) + (assert-equalp expected-declare declare) + (assert-equalp expected-body body))) + +(define-test parse-function-lambda-expression () + (test-parse-function-lambda-expression (lambda ())) + (test-parse-function-lambda-expression (lambda (a b)) + :expected-parameters '(a b)) + (test-parse-function-lambda-expression (lambda () "body") + :expected-body '("body")) + (test-parse-function-lambda-expression (lambda () (declare) "body") + :expected-declare '(declare) + :expected-body '("body")) + (test-parse-function-lambda-expression (lambda () "docstring" "body") + :expected-docstring "docstring" + :expected-body '("body")) + (test-parse-function-lambda-expression (lambda () "docstring" (declare) "body") + :expected-docstring "docstring" + :expected-declare '(declare) + :expected-body '("body")) + (test-parse-function-lambda-expression (lambda () (declare)) + :expected-declare '(declare)) + (test-parse-function-lambda-expression (lambda () "docstring" (declare)) + :expected-docstring "docstring" + :expected-declare '(declare))) (define-test doctest () ;; Test the documentation for the library itself