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

Support for Specs #67

Open
martinklepsch opened this issue Jun 8, 2018 · 6 comments
Open

Support for Specs #67

martinklepsch opened this issue Jun 8, 2018 · 6 comments
Labels

Comments

@martinklepsch
Copy link
Member

@martinklepsch martinklepsch commented Jun 8, 2018

This has been on the back of my mind for a while and came up in discussions around this project regularly. The gist: it would be nice to be able to view specs alongside documentation.

A few raw ideas/thoughts:

  • With enough information we could show a spec like (s/keys :req [:some.ns/id]) and the user could click on the :some.ns/id keyword and it would get augmented (replaced?) with it's respective spec

  • ⚠️ Currently specs don't contain any metadata about where they have been defined. This makes it impossible to tell from which artefact a spec originates. Tying specs to artifacts is important to:

    • only extract specs from the artefact under analysis and not it's dependencies
    • avoid conflicts between identically named specs at the storage layer

    Potential solutions:

    1. Wait until issues mentioned here are addressed.
    2. Fork spec, implement metadata features and inject our version into the analysis runtime.
    3. Store specs in the global namespace and hope conflicts aren't too problematic. Note that the same spec packaged in two different versions of the same artefact will also introduce a conflict.
@martinklepsch

This comment has been minimized.

Copy link
Member Author

@martinklepsch martinklepsch commented Jun 8, 2018

we should probably embrace spec's global namespacing

Scratch that, this works if we have a set of artifacts at one version per artifact but it breaks down if we have artifacts of multiple versions.

@kkinnear

This comment has been minimized.

Copy link
Contributor

@kkinnear kkinnear commented Jun 21, 2018

A bit of a nit, but zprint will print specs nicely out of the box, and even better with a small incoming options map. It will format them to whatever width you want (like we did the parameter list). Let me know if you get to the point where you want to format them and I'll lend a hand.

@martinklepsch

This comment has been minimized.

Copy link
Member Author

@martinklepsch martinklepsch commented Jun 21, 2018

@kkinnear thanks for that offer, definitely intending to zprint all the things 😄

More generally one unknown related to this issue is: We have the spec registry but we need to be able to associate specs with an artifact/namespace defining those specs. I took a cursory look at the spec registry but couldn't immediately figure out where a spec has been defined. If any of you know how to do this some guidance would be greatly appreciated 🙂

@kkinnear

This comment has been minimized.

Copy link
Contributor

@kkinnear kkinnear commented Jun 23, 2018

I'm not sure just exactly what you are trying to do, but here is my take on the spec registry (i.e., what you get from (clojure.spec.alpha/registry).

It appears to be a map, with keys that are function names or spec names. The values look to be other spec names (i.e., references to keys in the same map), or spec objects. The spec objects can be turned into something interesting with (describe), but also have meta-data on them. Here is what you get for the specs for the function clojurecore/defn. (s is clojure.spec.alpha here):

zprint.core=> (def r ('clojure.core/defn (s/registry)))
#'zprint.core/r
zprint.core=> r
#object[clojure.spec.alpha$fspec_impl$reify__2451 0x4129b1a2 "clojure.spec.alpha$fspec_impl$reify__2451@4129b1a2"]
zprint.core=> (s/describe r)
(fspec :args :clojure.core.specs.alpha/defn-args :ret any? :fn nil)
zprint.core=> (meta r)
{:line 1697, :column 5, :clojure.spec.alpha/name clojure.core/defn}
zprint.core=> (namespace (:clojure.spec.alpha/name (meta r)))
"clojure.core"
zprint.core=> (name (:clojure.spec.alpha/name (meta r)))
"defn"

so if you have the spec object, you can go back and find out the key that it lives under in the registry. If that is what you want to do. Presumably that key also tells you where it was defined.

Here is an example of one of my zprint specs (which is not associated with a function):

zprint.core=> (def r (:zprint.spec/tuning (s/registry)))
#'zprint.core/r
zprint.core=> r
#object[clojure.spec.alpha$merge_spec_impl$reify__2124 0x7e3ca5a1 "clojure.spec.alpha$merge_spec_impl$reify__2124@7e3ca5a1"]
zprint.core=> (s/describe r)
(merge (keys :opt-un [:zprint.spec/hang-flow :zprint.spec/hang-type-flow :zprint.spec/hang-flow-limit :zprint.spec/general-hang-adjust :zprint.spec/hang-if-equal-flow?]) (map-of #{:hang-type-flow :hang-flow :general-hang-adjust :hang-if-equal-flow? :hang-flow-limit} (constantly true)))
zprint.core=> (czprint *1)
(merge (keys :opt-un
             [:zprint.spec/hang-flow :zprint.spec/hang-type-flow
              :zprint.spec/hang-flow-limit :zprint.spec/general-hang-adjust
              :zprint.spec/hang-if-equal-flow?])
       (map-of #{:hang-type-flow :hang-flow :general-hang-adjust
                 :hang-if-equal-flow? :hang-flow-limit}
               (constantly true)))
nil
zprint.core=> (namespace (:clojure.spec.alpha/name (meta r)))
"zprint.spec"
zprint.core=> (name (:clojure.spec.alpha/name (meta r)))
"tuning"

The (czprint *1) does in fact replicate how I define this spec.

I have no idea if this is any help (or adds any new information to what you already had figured out), but I pass it along in case it might be useful.

@martinklepsch

This comment has been minimized.

Copy link
Member Author

@martinklepsch martinklepsch commented Jun 25, 2018

Alex Miller pointed me towards this existing Spec ticket about missing :file key in spec metadata: https://dev.clojure.org/jira/browse/CLJ-2037 — this is probably a blocker for now but I assume it shouldn't be too hard to fix.

@martinklepsch

This comment has been minimized.

Copy link
Member Author

@martinklepsch martinklepsch commented Aug 14, 2018

Before CLJ-2037 can be tackled CLJ-2194 is required. According to Alex Miller it will likely take a while before Rich gets back to Spec-work and a community-contributed patch will likely not be merged until then.

A fork might be an option but I'm not really sure I want to go down that route just yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.