borkdude / speculative

Unofficial community-driven specs for clojure.core
Eclipse Public License 1.0
188 stars 16 forks source link

Better way of disabling instrumentation for specs that do not work or are useless under instrumentation #276

Closed borkdude closed 5 years ago

borkdude commented 5 years ago

See https://github.com/borkdude/speculative-kaocha-plugin/issues/2.

When a user calls (stest/instrument) in their project, specs like hash-map will create errors (see https://github.com/borkdude/speculative/issues/264).

Previously this was fixed by moving these specs to a different namespace (speculative.core.extra), but this was later reverted. The reason is that this doesn't compose: some specs work in one environment (CLJ) but not in another (CLJS) so each environment would need its own namespace for this.

Another way for disabling "unwanted" specs could be the use of an a special variable that indicates that they should be defined. For JVM and Node an environment variable could work, for CLJS a goog.define could work.

Prototype:

(ns conditional-fdef
  (:require [clojure.spec.alpha :as s]))

(def blacklist '#{clojure.core/hash-map})
(defn ignore-blacklist? []
  (= "true" (System/getenv "SPECULATIVE_IGNORE_BLACKLIST")))

(defmacro fdef [sym & {:keys [:args :fn :ret]}]
  (when (or (ignore-blacklist?)
            (not (contains? blacklist sym)))
    `(s/fdef ~sym
       :args ~args
       :fn ~fn
       :ret ~ret)))

(s/fdef clojure.core/hash-map
  :args (s/cat :pairs (s/* (s/cat :k any? :v any?)))
  :ret map?)

Maybe even better would be to make the blacklist overridable via a variable. If users do not want a blacklist, they can override it with an empty blacklist.

Another option could be to "unload" fdefs before users call (stest/instrument) and do something with the spec registry. See https://dev.clojure.org/jira/browse/CLJ-2060 This may be the most straightforward option: include a unload-blacklisted function in speculative.instrument.