|
1 | 1 | (ns ^:no-doc lread.test-doc-blocks.impl.body-prep
|
2 | 2 | "Prep a doc block to be converted into a test."
|
3 |
| - (:require [clojure.string :as string])) |
| 3 | + (:require [clojure.string :as string] |
| 4 | + [rewrite-clj.zip :as z])) |
| 5 | + |
| 6 | +(defn- parseable? [s] |
| 7 | + (try |
| 8 | + (let [zloc (z/of-string s)] |
| 9 | + (not= :forms (z/tag zloc))) |
| 10 | + (catch Exception _ex |
| 11 | + false))) |
4 | 12 |
|
5 | 13 | (defn ^:no-doc prep-block-for-conversion-to-test
|
6 | 14 | "Convert doc block to Clojure that can be more easily parsed.
|
|
29 | 37 | "
|
30 | 38 | [block-text]
|
31 | 39 | (let [re-editor-style-out-expected #"^\s*(?:;;\s*){0,1}(=stdout=>|=stderr=>)(?:\s*$| {0,1}(.*))"
|
32 |
| - re-out-continue #"^\s*;+(?:\s*$| {0,1}(.*))" |
33 |
| - re-editor-style-expected #"^\s*(?:;;\s*){0,1}(=clj=>|=cljs=>|=>)\s*(.*$)"] |
34 |
| - (-> (loop [acc {:body ""} |
| 40 | + re-line-continue #"^\s*;+(?:\s*$| {0,1}(.*))" |
| 41 | + re-editor-style-expected #"^\s*(?:;;\s*){0,1}(=clj=>|=cljs=>|=>)\s*(.*$)"] |
| 42 | + (-> (loop [{:keys [body parsing assert-token expectation eo-assert?] :as state} {:body ""} |
35 | 43 | [line :as lines] (string/split-lines block-text)]
|
36 | 44 | (let [line (and line (string/trimr line))
|
37 |
| - [_ assert-token payload] (when line |
38 |
| - (or (re-matches re-editor-style-expected line) |
39 |
| - (re-matches re-editor-style-out-expected line)))] |
| 45 | + [_ line-assert-token line-payload] (when line |
| 46 | + (or (re-matches re-editor-style-expected line) |
| 47 | + (re-matches re-editor-style-out-expected line)))] |
40 | 48 | (cond
|
41 |
| - ;; expectation ends |
42 |
| - (and (:out acc) (or (not line) |
43 |
| - assert-token |
44 |
| - (not (re-matches re-out-continue line)) |
45 |
| - (re-matches re-editor-style-expected line))) |
46 |
| - (recur (as-> acc acc |
47 |
| - (case (:style acc) |
48 |
| - :out |
49 |
| - (update acc :body str (str (:out-token acc) " " |
50 |
| - (conj (:out acc)) "\n")) |
51 |
| - :editor |
52 |
| - (update acc :body str (str (:assert-token acc) " " |
53 |
| - (string/join "\n" (:out acc)) |
54 |
| - "\n"))) |
55 |
| - (dissoc acc :out :out-token :assert-token :style)) |
56 |
| - lines) |
| 49 | + (= :eval-expectation parsing) |
| 50 | + (cond |
| 51 | + ;; end of eval expectation? |
| 52 | + (or (not line) eo-assert?) |
| 53 | + (recur {:body (str body |
| 54 | + assert-token " " |
| 55 | + (string/join "\n" expectation) |
| 56 | + "\n")} |
| 57 | + lines) |
| 58 | + |
| 59 | + :else |
| 60 | + (let [[_ line-continue] (re-matches re-line-continue line) |
| 61 | + eval-line (or line-continue line)] |
| 62 | + (recur (let [{:keys [expectation] :as state} (update state :expectation conj (or eval-line ""))] |
| 63 | + (if (parseable? (string/join "\n" expectation)) |
| 64 | + (assoc state :eo-assert? true) |
| 65 | + state)) |
| 66 | + (rest lines)))) |
| 67 | + |
| 68 | + (= :out-expectation parsing) |
| 69 | + (cond |
| 70 | + ;; end of expecation? |
| 71 | + (or (not line) |
| 72 | + line-assert-token |
| 73 | + eo-assert? |
| 74 | + (not (re-matches re-line-continue line))) |
| 75 | + (recur {:body (str body |
| 76 | + assert-token " " |
| 77 | + (conj expectation) |
| 78 | + "\n")} |
| 79 | + lines) |
| 80 | + |
| 81 | + (re-matches re-line-continue line) |
| 82 | + (let [[_ line-continue] (re-matches re-line-continue line)] |
| 83 | + (recur (update state :expectation conj (or line-continue "")) |
| 84 | + (rest lines))) |
| 85 | + |
| 86 | + :else |
| 87 | + (recur (assoc state :eo-assert? true) lines)) |
57 | 88 |
|
58 | 89 | ;; all done?
|
59 | 90 | (not line)
|
60 |
| - acc |
61 |
| - |
62 |
| - ;; collecting expectation |
63 |
| - (and (:out acc) |
64 |
| - (not assert-token) |
65 |
| - (re-matches re-out-continue line)) |
66 |
| - (let [[_ out-line] (re-matches re-out-continue line)] |
67 |
| - (recur (update acc :out conj (or out-line "")) |
68 |
| - (rest lines))) |
69 |
| - |
70 |
| - ;; out expectation starts |
71 |
| - (or (= "=stdout=>" assert-token) |
72 |
| - (= "=stderr=>" assert-token)) |
73 |
| - (recur (assoc acc |
74 |
| - :style :out |
75 |
| - :out (if payload [payload] []) |
76 |
| - :out-token assert-token) |
| 91 | + state |
| 92 | + |
| 93 | + ;; start of out expection |
| 94 | + (or (= "=stdout=>" line-assert-token) |
| 95 | + (= "=stderr=>" line-assert-token)) |
| 96 | + (recur (assoc state |
| 97 | + :parsing :out-expectation |
| 98 | + :expectation (if line-payload [line-payload] []) |
| 99 | + :assert-token line-assert-token) |
77 | 100 | (rest lines))
|
78 | 101 |
|
79 |
| - ;; editor style evaluation expectation: |
80 |
| - ;; actual |
81 |
| - ;; ;;=> expected |
82 |
| - assert-token |
83 |
| - (recur (assoc acc |
84 |
| - :out (if payload [payload] []) |
85 |
| - :style :editor |
86 |
| - :assert-token assert-token) |
| 102 | + ;; editor style expectation |
| 103 | + line-assert-token |
| 104 | + (recur (let [{:keys [expectation] :as state} (assoc state |
| 105 | + :parsing :eval-expectation |
| 106 | + :expectation (if line-payload [line-payload] []) |
| 107 | + :assert-token line-assert-token)] |
| 108 | + (if (parseable? (string/join "\n" expectation)) |
| 109 | + (assoc state :eo-assert? true) |
| 110 | + state)) |
87 | 111 | (rest lines))
|
88 | 112 |
|
89 |
| - ;; other lines |
90 | 113 | :else
|
91 |
| - (recur (update acc :body str (str line "\n")) |
| 114 | + (recur (update state :body str (str line "\n")) |
92 | 115 | (rest lines)))))
|
93 | 116 | :body)))
|
94 | 117 |
|
95 | 118 |
|
96 | 119 | (comment
|
| 120 | + (parseable? " , ") |
| 121 | + |
97 | 122 | (prep-block-for-conversion-to-test ";; =stdout=> line1
|
98 | 123 | ; line2")
|
| 124 | + ;; => "=stdout=> [\"line1\" \"line2\"]\n" |
99 | 125 |
|
100 | 126 | (prep-block-for-conversion-to-test
|
101 | 127 | "(assoc {} :foo :bar :baz :kikka)
|
102 | 128 | ;; => {:foo :bar
|
103 | 129 | ; :baz :kikka}"
|
104 | 130 | )
|
105 |
| - ) |
| 131 | + ;; => "(assoc {} :foo :bar :baz :kikka)\n=> {:foo :bar\n :baz :kikka}\n" |
| 132 | + |
| 133 | + (prep-block-for-conversion-to-test |
| 134 | + "(assoc {} :foo :bar :baz :kikka) |
| 135 | +;; => ^{:foo :bar |
| 136 | +;; :baz :kikka} [] |
| 137 | +;; some other comment |
| 138 | +;; more comments |
| 139 | +;; =stdout=> foo |
| 140 | +" |
| 141 | +) |
| 142 | + ;; => "(assoc {} :foo :bar :baz :kikka)\n=> ^{:foo :bar\n :baz :kikka} []\n;; some other comment\n;; more comments\n=stdout=> [\"foo\"]\n" |
| 143 | + |
| 144 | + |
| 145 | + (parseable? " ") |
| 146 | + ;; => false |
| 147 | + (parseable? " 32 ") |
| 148 | + ;; => true |
| 149 | + |
| 150 | + ;; only :a will be significant |
| 151 | + (parseable? ":a 2 3") |
| 152 | + ;; => true |
| 153 | + |
| 154 | + (parseable? "[:a 2\n;;some foo\n 3]") |
| 155 | + ;; => true |
| 156 | + |
| 157 | + (parseable? ";; foo") |
| 158 | + ;; => false |
| 159 | + |
| 160 | + ;; for now don't skip discards, user should get error for this eventualy |
| 161 | + (parseable? "#_ 3") |
| 162 | + ;; => true |
| 163 | + |
| 164 | + :eoc) |
0 commit comments