Attaching metadata to a Clojure gen-class

4k views Asked by At

Is it possible to attach metadata to a Clojure gen-class?

I am trying to implement a server that uses a library that requires Java annotations added to classes.

From Chas Emerick's, et al., forthcoming book "Programming Clojure" (section 9.7.3), adding annotations to gen-class methods is easy, but there is no mention of adding class-level annotations.

3

There are 3 answers

0
Daniel Kaplan On BEST ANSWER

Yes it is, I found a great example here:

https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/genclass/examples.clj

Here's some code inlined so it doesn't disappear in the future:

(gen-class :name ^{Deprecated {}
                   SuppressWarnings ["Warning1"] ; discarded
                   java.lang.annotation.Target []}
                 clojure.test_clojure.genclass.examples.ExampleAnnotationClass
           :prefix "annot-"
           :methods [[^{Deprecated {}
                        Override {}} ;discarded
                      foo [^{java.lang.annotation.Retention java.lang.annotation.RetentionPolicy/SOURCE
                             java.lang.annotation.Target    [java.lang.annotation.ElementType/TYPE
                                                             java.lang.annotation.ElementType/PARAMETER]}
                           String] void]])
0
zachncst On

To add additional information to this because I can't find it documented anywhere else it's possible to add annotations to constructors as well.

You can add annotations to constructors by adding meta data to the first array of the constructor pair. Like this:

(gen-class
  :name "FooClass"
  :init "init"
  :constructors {^{Inject {}} [Configuration] []}
  :state "state"
  :implements [FooInterface]
  :prefix "ref-")
4
Paul On

I don't think it is possible at this point.

Rich Hickey mentions adding annotations support in this thread https://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117 but as far as I can see this is only for deftype / defrecord. I could be wrong of course.

Both of these

(ns genclass.example
  (:gen-class ^{:doc "example class"}))

and

(ns genclass.example)

(with-meta
  (gen-class
   :name genclass.example.ClassA
   :methods [[hello [] void]])
  {:doc "Example class"})      

fail to compile for me. From the exception

Exception in thread "main" java.lang.IllegalArgumentException: Metadata can only be applied to IMetas (example.clj:4)`

It sounds like this is not possible.