-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.clj
74 lines (61 loc) · 2.14 KB
/
core.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
(ns exegesis.core
(:refer-clojure :exclude [name methods])
(:require
[exegesis.internal
:refer [annotations
parameter-annotations
annotation-type
declared-methods
declared-fields
name
invoke]])
(:import
[java.lang.reflect Method]
[java.lang.annotation Annotation]))
(defn- as-map [^Annotation annotation]
{:instance annotation})
(defn- with-type
[{:keys [instance]
:as ^Annotation annotation}]
(let [^Class type (annotation-type instance)]
(assoc annotation :type type)))
(defn- with-elements
[{:keys [instance type]
:as ^Annotation annotation}]
(let [methods (declared-methods type)
elements (set (map
(fn [^Method method]
{:name (symbol (name method))
:value (invoke method instance)})
methods))]
(assoc annotation :elements elements)))
(defn- ->annotation-detail [annotation]
(-> annotation
as-map
with-type
with-elements))
(defn- ->annotation-details [annotations]
(set (map ->annotation-detail annotations)))
(defn- type-annotation-info [type]
{:annotations (->annotation-details (annotations type))})
(defn- parameters-annotation-info [method]
(vec (map ->annotation-details (parameter-annotations method))))
(defn- method-annotation-info [method]
{:name (symbol (name method))
:annotations (->annotation-details (annotations method))
:parameters (parameters-annotation-info method)})
(defn- methods-annotation-info [type]
(set (map method-annotation-info (declared-methods type))))
(defn- field-annotation-info [field]
{:name (symbol (name field))
:annotations (->annotation-details (annotations field))})
(defn- fields-annotation-info [type]
(set (map field-annotation-info (declared-fields type))))
(defn- context-class
[obj]
(if (class? obj) obj (type obj)))
(defn annotation-info [type-or-object]
(let [class (context-class type-or-object)]
{:type (type-annotation-info class)
:fields (fields-annotation-info class)
:methods (methods-annotation-info class)}))