-
Notifications
You must be signed in to change notification settings - Fork 7
/
defexception.clj
48 lines (37 loc) · 1.72 KB
/
defexception.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(ns com.rpl.defexception
(:require [clojure.string :as string]
[com.rpl.defexception.impl :as impl]))
(defmacro defexception
"Dynamically creates an clojure.lang.ExceptionInfo class using JVM
bytecode. The exception class inherits its behavior from
clojure.lang.ExceptionInfo yet will be its own type.
This means that an instance of this exception will respond to
`clojure.core/ex-data` and can have an optional Throwable `cause` arg.
This will create a constructor function much similar to the one
created for Records.
Example Usage:
(defexception MyException) => user.MyException
(->MyException)
(->MyException {:hello 1})
(->MyException \"This is a message\")
(->MyException \"This is a message\" {:hello 1})
(->MyException \"This is a message\" {:hello 1} (Exception. \"A cause\"))
(ex-data (->MyException {:hello 1})) => {:hello 1}
(ex-data (->MyException \"This is a message\" {:hello 1})) => {:hello 1}
(.getMessage (->MyException \"This is a message\")) => \"This is a message\"
or invoke the constructors directly
(user/MyException. \"This is a Message\" {})
(user/MyException. \"This is a Message\" {} (Exception. \"A message\"))"
[t]
(let [class-name (str (string/replace (str *ns*) "-" "_") "." t)]
`(let [x# (impl/load-or-mk-ex-info-class ~class-name)]
(import ~(symbol class-name))
(defn ~(symbol (str "->" t))
([] (impl/make-ex x# nil {} nil))
([~'msg-o-data]
(if (map? ~'msg-o-data)
(impl/make-ex x# nil ~'msg-o-data nil)
(impl/make-ex x# ~'msg-o-data {} nil)))
([~'msg ~'data] (impl/make-ex x# ~'msg ~'data nil))
([~'msg ~'data ~'cause] (impl/make-ex x# ~'msg ~'data ~'cause)))
x#)))