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

Add support for cross-platform JVM type hints #442

Merged
merged 2 commits into from Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/clj/schema/macros.clj
Expand Up @@ -101,8 +101,25 @@
(def primitive-sym? '#{float double boolean byte char short int long
floats doubles booleans bytes chars shorts ints longs objects})

(defn valid-tag? [env tag]
(and (symbol? tag) (or (primitive-sym? tag) (class? (resolve env tag)))))
(defn resolve-tag
"Given a Symbol, attempt to return a valid Clojure tag else nil.

Symbols not contained in `primitive-sym?` will be resolved. Symbols
resolved to Vars have thier values checked in an attempt to provide
kgann marked this conversation as resolved.
Show resolved Hide resolved
type hints when possible.

A valid tag is a primitive, Class, or Var containing a Class."
[env tag]
(when (symbol? tag)
(let [resolved (delay (resolve env tag))]
(cond
(or (primitive-sym? tag) (class? @resolved))
tag

(var? @resolved)
(let [v (var-get @resolved)]
(when (class? v)
(symbol (.getName ^Class v))))))))

(defn normalized-metadata
"Take an object with optional metadata, which may include a :tag,
Expand All @@ -118,9 +135,7 @@
(-> (or (meta imeta) {})
(dissoc :tag)
(utils/assoc-when :schema schema
:tag (let [t (or tag schema)]
(when (valid-tag? env t)
t))))))))
:tag (resolve-tag env (or tag schema))))))))

(defn extract-schema-form
"Pull out the schema stored on a thing. Public only because of its use in a public macro."
Expand Down Expand Up @@ -227,9 +242,9 @@
tag? is a prospective tag for the fn symbol based on the output schema.
schema-bindings are bindings to lift eval outwards, so we don't build the schema
every time we do the validation.

:ufv-sym should name a local binding bound to `schema.utils/use-fn-validation`.

5-args arity is deprecated."
([env fn-name output-schema-sym bind-meta arity-form]
(process-fn-arity {:env env :fn-name fn-name :output-schema-sym output-schema-sym
Expand Down
4 changes: 3 additions & 1 deletion test/cljc/schema/core_test.cljc
Expand Up @@ -716,7 +716,8 @@
(testing "primitive" (test-normalized-meta ^long foo nil {:tag long :schema long}))
(testing "class" (test-normalized-meta ^String foo nil {:tag String :schema String}))
(testing "non-tag" (test-normalized-meta ^ASchema foo nil {:schema ASchema}))
(testing "explicit" (test-normalized-meta ^Object foo String {:tag Object :schema String})))
(testing "explicit" (test-normalized-meta ^Object foo String {:tag Object :schema String}))
(testing "xplatform" (test-normalized-meta ^s/Str foo nil {:tag String :schema String})))

(defmacro test-meta-extraction [meta-form arrow-form]
(let [meta-ized (macros/process-arrow-schematized-args {} arrow-form)]
Expand All @@ -729,6 +730,7 @@
(testing "no-tag" (test-meta-extraction [x] [x]))
(testing "old-tags" (test-meta-extraction [^String x] [^String x]))
(testing "new-vs-old-tag" (test-meta-extraction [^String x] [x :- String]))
(testing "xplatform-new-vs-xplatform-old-tag" (test-meta-extraction [^s/Str x] [x :- s/Str]))
(testing "multi vars" (test-meta-extraction [x ^String y z] [x y :- String z])))))

(defprotocol PProtocol
Expand Down