Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various Enhancements #179

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
### Notes about this fork

- Focused on extracting structured data (EDN) from jars.
- Any writing-related (HTML etc.) dependencies have been removed, code is kept to keep diff to mainline manageable.
- Various tweaks have been done to align the results of Clojure and ClojureScript analysis.


---

# Codox

A tool for generating API documentation from Clojure or ClojureScript
Expand Down
4 changes: 4 additions & 0 deletions codox/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{:paths ["src" "resources" "test-sources"]
:deps {org.clojure/clojure {:mvn/version "1.9.0"}
org.clojure/tools.namespace {:mvn/version "0.2.11"}
org.clojure/clojurescript {:mvn/version "1.10.339"}}}
50 changes: 29 additions & 21 deletions codox/src/codox/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"Main namespace for generating documentation"
(:use [codox.utils :only (add-source-paths)])
(:require [clojure.string :as str]
[clojure.pprint]
[clojure.java.shell :as shell]
[codox.reader.clojure :as clj]
[codox.reader.clojurescript :as cljs]
[codox.reader.plaintext :as text]))

(defn- writer [{:keys [writer]}]
Expand All @@ -19,29 +21,9 @@
(throw
(Exception. (str "Could not resolve codox writer " writer-sym))))))

(defn- macro? [var]
(= (:type var) :macro))

(defn- read-macro-namespaces [paths read-opts]
(->> (clj/read-namespaces paths read-opts)
(map (fn [ns] (update-in ns [:publics] #(filter macro? %))))
(remove (comp empty? :publics))))

(defn- merge-namespaces [namespaces]
(for [[name namespaces] (group-by :name namespaces)]
(assoc (first namespaces) :publics (mapcat :publics namespaces))))

(defn- cljs-read-namespaces [paths read-opts]
;; require is here to allow Clojure 1.3 and 1.4 when not using ClojureScript
(require 'codox.reader.clojurescript)
(let [reader (find-var 'codox.reader.clojurescript/read-namespaces)]
(merge-namespaces
(concat (reader paths read-opts)
(read-macro-namespaces paths read-opts)))))

(def ^:private namespace-readers
{:clojure clj/read-namespaces
:clojurescript cljs-read-namespaces})
:clojurescript cljs/read-namespaces})

(defn- var-symbol [namespace var]
(symbol (name (:name namespace)) (name (:name var))))
Expand Down Expand Up @@ -125,3 +107,29 @@
(write-fn (assoc options
:namespaces namespaces
:documents documents)))))

(defn -main
"The main entry point for reading API information from files in a directory.

To analyze a project (debugging etc.) follow these steps:

1. unzip the project's jar into a directory
2. add the project's coordinates to the local `deps.edn` file
3. add the jar contents directory to `:paths` in `deps.edn`

You can then call this main function as follows:

clj -m codox.main clojurescript jar-contents-dir/
clj -m codox.main clojure jar-contents-dir/"
[lang path]
(println "Analyzing lang:" lang)
(println "Analyzing path:" path)
(assert (#{"clojure" "clojurescript"} lang))
(->> (generate-docs {:writer 'clojure.core/identity
:source-paths [path]
:language (keyword lang)})
:namespaces
;; Walk/realize entire structure, otherwise "Excluding ->Xyz"
;; messages will be mixed with the pretty printed output
(clojure.walk/prewalk identity)
clojure.pprint/pprint))
4 changes: 2 additions & 2 deletions codox/src/codox/reader/clojure.clj
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@

(defn- find-namespaces [file]
(cond
(.isDirectory file) (ns/find-namespaces-in-dir file)
(jar-file? file) (ns/find-namespaces-in-jarfile (JarFile. file))))
(.isDirectory file) (set (ns/find-namespaces-in-dir file))
(jar-file? file) (set (ns/find-namespaces-in-jarfile (JarFile. file)))))

(defn read-namespaces
"Read Clojure namespaces from a set of source directories (defaults
Expand Down
32 changes: 18 additions & 14 deletions codox/src/codox/reader/clojurescript.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
(:require [clojure.java.io :as io]
[cljs.analyzer :as an]
[cljs.analyzer.api :as ana]
[cljs.closure]
[cljs.env]
[clojure.string :as str]))

(defn- cljs-filename? [filename]
Expand All @@ -15,7 +17,7 @@
(-> file .getName cljs-filename?)))

(defn- remove-quote [x]
(if (and (list? x) (= (first x) 'quote))
(if (and (seq? x) (= (first x) 'quote))
(second x)
x))

Expand Down Expand Up @@ -50,15 +52,16 @@
:else :var))

(defn- read-var [file vars var]
(-> var
(select-keys [:name :line :arglists :doc :dynamic :added :deprecated :doc/format])
(update-some :name (comp symbol name))
(update-some :arglists remove-quote)
(update-some :doc correct-indent)
(assoc-some :file (.getPath file)
:type (var-type var)
:members (map (partial read-var file vars)
(protocol-methods var vars)))))
(let [vt (var-type var)]
(-> var
(select-keys [:name :line :arglists :doc :dynamic :added :deprecated :doc/format])
(update-some :name (comp symbol name))
(update-some :arglists remove-quote)
(update-some :doc correct-indent)
(assoc-some :file (if (= vt :macro) (:file var) (.getPath file))
:type vt
:members (map (partial read-var file vars)
(protocol-methods var vars))))))

(defn- read-publics [state namespace file]
(let [vars (vals (ana/ns-publics state namespace))]
Expand All @@ -70,10 +73,11 @@
(sort-by (comp str/lower-case :name)))))

(defn- analyze-file [file]
(let [state (ana/empty-state)]
(binding [an/*analyze-deps* false]
(ana/no-warn
(ana/analyze-file state file {})))
(let [opts (cljs.closure/add-implicit-options {})
state (cljs.env/default-compiler-env opts)]
(ana/no-warn
(cljs.closure/validate-opts opts)
(ana/analyze-file state file opts))
state))

(defn- read-file [path file exception-handler]
Expand Down
18 changes: 18 additions & 0 deletions codox/test-sources/codox_test/macro.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(ns codox-test.macro)

(defmacro test
[a b]
`(+ ~a ~b))

(defmacro test2
[a & xs]
`(reduce + ~a ~(vec xs)))

;; https://github.com/jarohen/nomad/blob/5520c332c5c6d5eef4dcb0930c735900d63dea2a/src/nomad/config.clj#L98-L111

(defn with-config-override* [{:keys [switches secret-keys override-switches] :as opts-override} f]
nil)

(doto (defmacro with-config-override [opts & body]
`(with-config-override* ~opts (fn [] ~@body)))
(alter-meta! assoc :arglists '([{:keys [switches secret-keys override-switches] :as opts-override} & body])))
9 changes: 9 additions & 0 deletions codox/test-sources/codox_test/multimethod.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(ns codox-test.multimethod)

(defmulti start (fn [k opts] k))

(defmethod start :car [_ opts]
(println "Starting car..." opts))

(defmethod start :helicopter [_ opts]
(println "Starting helicopter..." opts))
3 changes: 3 additions & 0 deletions codox/test-sources/codox_test/record.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(ns codox-test.record)

(defrecord CodoxSystem [components])
4 changes: 4 additions & 0 deletions codox/test-sources/codox_test/spec.cljc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(ns codox-test.spec
(:require [clojure.spec.test.alpha :as st]))

(st/with-instrument-disabled (+ 1 2 3))
4 changes: 4 additions & 0 deletions codox/test-sources/codox_test/spec_two.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(ns codox-test.spec-two
(:require [clojure.spec.test.alpha :as st]))

(st/with-instrument-disabled (+ 1 2 3))