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

fix: remove the possible duplicate output introduced in a052dd8 #737

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 33 additions & 29 deletions src/cider/nrepl/middleware/out.clj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,32 @@ Please do not inline; they must not be recomputed at runtime."}
(catch Exception ~'e
(unsubscribe-session ~'session))))))

(defn- dispatch-string
([messages type ^String x]
(.write ^Writer (original-output type) x)
(with-out-binding [printer messages type]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(.write printer x)))
([messages type ^String x ^Integer off ^Integer len]
(.write ^Writer (original-output type) x off len)
(with-out-binding [printer messages type]
(.write printer x off len))))

(defn- dispatch-int
([messages type ^Integer x]
(.write ^Writer (original-output type) x)
(with-out-binding [printer messages type]
(.write printer x))))

(defn- dispatch-chars
([messages type ^{:tag "[C"} x]
(.write ^Writer (original-output type) x)
(with-out-binding [printer messages type]
(.write printer x)))
([messages type ^{:tag "[C"} x ^Integer off ^Integer len]
(.write ^Writer (original-output type) x off len)
(with-out-binding [printer messages type]
(.write printer x off len))))

(defn forking-printer
"Returns a PrintWriter suitable for binding as *out* or *err*. All
operations are forwarded to all output bindings in the sessions of
Expand All @@ -54,36 +80,14 @@ Please do not inline; they must not be recomputed at runtime."}
;; as `int` and `char[]` aren't supported by proxy.
(write
([x]
(with-out-binding [printer messages type]
(cond
(string? x)
(do
(.write ^Writer (original-output type) ^String x)
(.write printer ^String x))

(integer? x)
(do
(.write ^Writer (original-output type) ^int x)
(.write printer ^int x))
:else
(do
(.write ^Writer (original-output type)
^{:tag "[C"} x)
(.write printer ^{:tag "[C"} x)))))
(cond
(string? x) (dispatch-string messages type x)
(integer? x) (dispatch-int messages type x)
:else (dispatch-chars messages type x)))
([x ^Integer off ^Integer len]
(with-out-binding [printer messages type]
(cond
(string? x)
(do
(.write ^Writer (original-output type)
^String x off len)
(.write printer ^String x off len))

:else
(do
(.write ^Writer (original-output type)
^{:tag "[C"} x off len)
(.write printer ^{:tag "[C"} x off len))))))
(if (string? x)
(dispatch-string messages type x off len)
(dispatch-chars messages type x off len))))
(flush []
(.flush ^Writer (original-output type))
(with-out-binding [printer messages type]
Expand Down
82 changes: 57 additions & 25 deletions test/clj/cider/nrepl/middleware/out_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -47,58 +47,90 @@
(defn- forking-printer-test-streams
[]
(let [out-writer (StringWriter.)
message-writer (StringWriter.)
message {:session (atom {#'*out* message-writer})}
printer (o/forking-printer [message] :out)]
message-writers [(StringWriter.) (StringWriter.)]
messages [{:session (atom {#'*out* (message-writers 0)})}
{:session (atom {#'*err* (message-writers 1)})}]
printers [(o/forking-printer [(messages 0) (messages 1)] :out)
(o/forking-printer [(messages 0) (messages 1)] :err)]]
{:out-writer out-writer
:message-writer message-writer
:printer printer}))
:message-writers message-writers
:printers printers}))

(deftest forking-printer-test
(testing "forking-printer prints to all message streams and original stream"
(testing "with String argument "
(let [{:keys [^StringWriter out-writer
^StringWriter message-writer
^PrintWriter printer]}
message-writers
printers]}
(forking-printer-test-streams)]
(with-original-output [{:out out-writer}]
(.write printer "Hello")
(.write ^PrintWriter (printers 0) "Hello")
(is (= "Hello" (.toString out-writer)))
(is (= "Hello" (.toString message-writer))))))
(is (= "Hello" (.toString ^StringWriter (message-writers 0))))
(is (= "" (.toString ^StringWriter (message-writers 1)))))
(with-original-output [{:err out-writer}]
(.write ^PrintWriter (printers 1) "Hello")
(is (= "HelloHello" (.toString out-writer)))
(is (= "Hello" (.toString ^StringWriter (message-writers 0))))
(is (= "Hello" (.toString ^StringWriter (message-writers 1)))))))
(testing "with int"
(let [{:keys [^StringWriter out-writer
^StringWriter message-writer
^PrintWriter printer]}
message-writers
printers]}
(forking-printer-test-streams)
an-int (int 32)]
(with-original-output [{:out out-writer}]
(.write printer an-int)
(.write ^PrintWriter (printers 0) an-int)
(is (= " " (.toString out-writer)))
(is (= " " (.toString message-writer))))))
(is (= " " (.toString ^StringWriter (message-writers 0))))
(is (= "" (.toString ^StringWriter (message-writers 1)))))
(with-original-output [{:err out-writer}]
(.write ^PrintWriter (printers 1) an-int)
(is (= " " (.toString out-writer)))
(is (= " " (.toString ^StringWriter (message-writers 0))))
(is (= " " (.toString ^StringWriter (message-writers 1)))))))
(testing "with char array"
(let [{:keys [^StringWriter out-writer
^StringWriter message-writer
^PrintWriter printer]}
message-writers
printers]}
(forking-printer-test-streams)]
(with-original-output [{:out out-writer}]
(.write printer (char-array "and"))
(.write ^PrintWriter (printers 0) (char-array "and"))
(is (= "and" (.toString out-writer)))
(is (= "and" (.toString message-writer))))))
(is (= "and" (.toString ^StringWriter (message-writers 0))))
(is (= "" (.toString ^StringWriter (message-writers 1)))))
(with-original-output [{:err out-writer}]
(.write ^PrintWriter (printers 1) (char-array "and"))
(is (= "andand" (.toString out-writer)))
(is (= "and" (.toString ^StringWriter (message-writers 0))))
(is (= "and" (.toString ^StringWriter (message-writers 1)))))))
(testing "with String with offsets"
(let [{:keys [^StringWriter out-writer
^StringWriter message-writer
^PrintWriter printer]}
message-writers
printers]}
(forking-printer-test-streams)]
(with-original-output [{:out out-writer}]
(.write printer "12 good34" 3 4)
(.write ^PrintWriter (printers 0) "12 good34" 3 4)
(is (= "good" (.toString out-writer)))
(is (= "good" (.toString message-writer))))))
(is (= "good" (.toString ^StringWriter (message-writers 0))))
(is (= "" (.toString ^StringWriter (message-writers 1)))))
(with-original-output [{:err out-writer}]
(.write ^PrintWriter (printers 1) "12 good34" 3 4)
(is (= "goodgood" (.toString out-writer)))
(is (= "good" (.toString ^StringWriter (message-writers 0))))
(is (= "good" (.toString ^StringWriter (message-writers 1)))))))
(testing "with char array with offsets"
(let [{:keys [^StringWriter out-writer
^StringWriter message-writer
^PrintWriter printer]}
message-writers
printers]}
(forking-printer-test-streams)]
(with-original-output [{:out out-writer}]
(.write printer (char-array " bye67") 1 3)
(.write ^PrintWriter (printers 0) (char-array " bye67") 1 3)
(is (= "bye" (.toString out-writer)))
(is (= "bye" (.toString message-writer))))))))
(is (= "bye" (.toString ^StringWriter (message-writers 0))))
(is (= "" (.toString ^StringWriter (message-writers 1)))))
(with-original-output [{:err out-writer}]
(.write ^PrintWriter (printers 1) (char-array " bye67") 1 3)
(is (= "byebye" (.toString out-writer)))
(is (= "bye" (.toString ^StringWriter (message-writers 0))))
(is (= "bye" (.toString ^StringWriter (message-writers 1)))))))))