diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn new file mode 100644 index 0000000..b1c2dc8 --- /dev/null +++ b/.clj-kondo/config.edn @@ -0,0 +1,2 @@ +{:lint-as {flanders.macros/defleaf schema.core/defrecord + flanders.core/def-entity-type clojure.core/def}} diff --git a/.clj-kondo/prismatic/schema/config.edn b/.clj-kondo/prismatic/schema/config.edn new file mode 100644 index 0000000..2c341bc --- /dev/null +++ b/.clj-kondo/prismatic/schema/config.edn @@ -0,0 +1 @@ +{:lint-as {schema.test/deftest clojure.test/deftest}} diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..611b74e --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,4 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((clojure-mode . ((cider-clojure-cli-aliases . ":test")))) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..88700ea --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,42 @@ +name: Code check + +on: push + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '8' + + - name: Install clojure tools + uses: DeLaGuardo/setup-clojure@12.1 + with: + lein: latest + cli: latest + clj-kondo: latest + + - name: Check clojure code + run: + clj-kondo --lint ./src --lint ./test + + - name: Cache lein project dependencies + uses: actions/cache@v3 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-clojure-${{ hashFiles('**/project.clj', '**/deps.edn') }} + restore-keys: | + ${{ runner.os }}-clojure + + - name: Run Clojure CLI tests + run: + clojure -X:test + + - name: Run leiningen tests + run: + lein test diff --git a/.gitignore b/.gitignore index c53038e..b6b063a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ pom.xml.asc /.nrepl-port .hgignore .hg/ +/.clj-kondo/.cache +/.lsp/.cache +/.cpcache/ diff --git a/deps.edn b/deps.edn new file mode 100644 index 0000000..72ed94a --- /dev/null +++ b/deps.edn @@ -0,0 +1,11 @@ +{:paths ["src"] + :deps {metosin/ring-swagger {:mvn/version "0.26.2"} + metosin/schema-tools {:mvn/version "0.13.1"} + org.clojure/clojure {:mvn/version "1.10.1"} + org.clojure/core.match {:mvn/version "1.0.0"} + org.clojure/test.check {:mvn/version "1.1.1"} + prismatic/schema {:mvn/version "1.4.1"}} + :aliases {:test {:extra-paths ["test"] + :extra-deps {io.github.cognitect-labs/test-runner {:git/tag "v0.5.1" :git/sha "dfb30dd"}} + :main-opts ["-m" "cognitect.test-runner"] + :exec-fn cognitect.test-runner.api/test}}} diff --git a/project.clj b/project.clj index becb65e..796a8a6 100644 --- a/project.clj +++ b/project.clj @@ -3,14 +3,9 @@ :url "http://github.com/threatgrid/flanders" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :pedantic? :abort - :dependencies [[org.clojure/clojure "1.10.1"] + :dependencies [[metosin/ring-swagger "0.26.2"] + [metosin/schema-tools "0.13.1"] + [org.clojure/clojure "1.10.1"] [org.clojure/core.match "1.0.0"] - [cheshire "5.9.0"] - - [prismatic/schema "1.1.12"] - [metosin/ring-swagger "0.26.2"] - [metosin/schema-tools "0.12.2"]] - :global-vars {*warn-on-reflection* true} - :profiles {:dev - {:dependencies [[org.clojure/test.check "1.0.0"]]}}) + [org.clojure/test.check "1.1.1"] + [prismatic/schema "1.4.1"]]) diff --git a/src/flanders/core.cljc b/src/flanders/core.cljc index 7cf5596..49e1790 100644 --- a/src/flanders/core.cljc +++ b/src/flanders/core.cljc @@ -1,12 +1,11 @@ (ns flanders.core (:refer-clojure :exclude [int key keyword map name num str type]) - (:require #?(:clj [clojure.core :as core] - :cljs [cljs.core :as core]) - #?(:clj [clojure.spec.alpha :as spec] - :cljs [cljs.spec.alpha :as spec]) - [clojure.zip :as z] - [flanders.types :as ft] - [schema.core :as s])) + (:require + #?(:clj [clojure.core :as core] + :cljs [cljs.core :as core]) + #?(:clj [clojure.spec.alpha :as spec] + :cljs [cljs.spec.alpha :as spec]) + [flanders.types :as ft])) ;; ---------------------------------------------------------------------- ;; Defining Branch Nodes @@ -111,7 +110,7 @@ A signature can be variadic by specifying the `:rest-parameter` argument." [& {:keys [parameters rest-parameter return] :as opts}] - (if (some? parameters) + (when (some? parameters) (assert (sequential? parameters) ":parameters argument must be `sequential?`")) (let [return (if (some? return) return diff --git a/src/flanders/example.cljc b/src/flanders/example.cljc index 4ecb606..53b5e99 100644 --- a/src/flanders/example.cljc +++ b/src/flanders/example.cljc @@ -1,20 +1,28 @@ (ns flanders.example - (:require [flanders.predicates :as fp] - [flanders.schema :as fs] - #?(:clj [flanders.types :as ft] - :cljs [flanders.types - :as ft - :refer [AnythingType BooleanType EitherType - InstType IntegerType KeywordType - MapEntry MapType NumberType - SequenceOfType SetOfType SignatureType - StringType]])) - #?(:clj (:import [flanders.types - AnythingType BooleanType EitherType InstType - IntegerType KeywordType MapEntry MapType - NumberType SequenceOfType SetOfType SignatureType - StringType] - [java.util Date]))) + (:require + #?(:clj [flanders.types :as ft] + :cljs [flanders.types + :as ft + :refer [AnythingType BooleanType EitherType InstType IntegerType + KeywordType MapEntry MapType NumberType SequenceOfType + SetOfType SignatureType StringType]]) + [flanders.schema :as fs]) + #?(:clj (:import + [flanders.types + AnythingType + BooleanType + EitherType + InstType + IntegerType + KeywordType + MapEntry + MapType + NumberType + SequenceOfType + SetOfType + SignatureType + StringType] + [java.util Date]))) (defprotocol JsonExampleNode (->example [node f])) diff --git a/src/flanders/macros.cljc b/src/flanders/macros.cljc index 07f066e..5d1fc64 100644 --- a/src/flanders/macros.cljc +++ b/src/flanders/macros.cljc @@ -1,12 +1,12 @@ (ns flanders.macros - (:require [flanders.protocols - :refer [branch? node-children make-node TreeNode]] - [schema.core :as s])) + (:require + [flanders.protocols :as p] + [schema.core :as s])) (defmacro defleaf [name argsv & sexprs] `(s/defrecord ~name ~argsv - TreeNode - (branch? [_#] false) - (node-children [_#] nil) - (make-node [this# _#] this#) + p/TreeNode + (~'branch? [_#] false) + (~'node-children [_#] nil) + (~'make-node [this# _#] this#) ~@sexprs)) diff --git a/src/flanders/markdown.cljc b/src/flanders/markdown.cljc index f52b708..969d5c6 100644 --- a/src/flanders/markdown.cljc +++ b/src/flanders/markdown.cljc @@ -1,24 +1,34 @@ (ns flanders.markdown (:refer-clojure :exclude [type]) - (:require [clojure.string :as str] - [clojure.zip :as z] - #?(:clj [flanders.macros :refer [defleaf]] - :cljs [flanders.macros :refer-macros [defleaf]]) - [flanders.predicates :as fp] - [flanders.schema :as fs] - #?(:clj [flanders.types] - :cljs [flanders.types - :refer [AnythingType BooleanType EitherType InstType - IntegerType KeywordType MapEntry MapType - ParameterListType NumberType - SequenceOfType SetOfType SignatureType - StringType]]) - [flanders.utils :as fu]) - #?(:clj (:import [flanders.types - AnythingType BooleanType EitherType InstType - IntegerType KeywordType MapEntry MapType - NumberType ParameterListType SequenceOfType - SetOfType SignatureType StringType]))) + (:require + #?(:clj [flanders.macros :refer [defleaf]] + :cljs [flanders.macros :refer-macros [defleaf]]) + #?(:clj [flanders.types] + :cljs [flanders.types + :refer [AnythingType BooleanType EitherType InstType IntegerType + KeywordType MapEntry MapType NumberType ParameterListType + SequenceOfType SetOfType SignatureType StringType]]) + [clojure.string :as str] + [clojure.zip :as z] + [flanders.predicates :as fp] + [flanders.schema :as fs] + [flanders.utils :as fu]) + #?(:clj (:import + [flanders.types + AnythingType + BooleanType + EitherType + InstType + IntegerType + KeywordType + MapEntry + MapType + NumberType + ParameterListType + SequenceOfType + SetOfType + SignatureType + StringType]))) (defprotocol MarkdownNode (->markdown-part [node depth]) @@ -27,10 +37,8 @@ (defleaf ReferenceNode [text anchor jump-anchor]) (defn ready-for-table [str] - (-> str - (str/replace #"\n" " ") - (str/replace #"\|" "\\\\|") - )) + (str/replace str #"(\n|\|)" {"\n" " " + "\\|" "\\\\|"})) (defn ->default [{:keys [default values]}] (when (and default (> (count values) 1)) @@ -42,7 +50,7 @@ ([{:keys [description] :as node} leaf?] (when (seq description) (str (if leaf? " * " "") - (if-some [name (get node :name)] + (when-some [name (get node :name)] (str "*" name "* ")) description (if leaf? "\n" "\n\n"))))) @@ -88,25 +96,12 @@ (str "* " type-str " Key\n") (str "* " type-str " Value\n")))) -(defn- ->schema-str [this loc] - (let [schema (pr-str (fs/->schema-at-loc this loc)) - schema (cond - (str/starts-with? schema "(enum") "(enum ...)" - (= "java.lang.String" schema) "Str" - (= "java.lang.Boolean" schema) "Bool" - :else schema)] - (str " * Plumatic Schema: " - (if (fp/sequential? loc) - (str "[" schema "]") - schema) - "\n"))) - (defn- ->values [{v :values}] (when (and v (> (count v) 1)) (str " * Allowed Values:\n" (str/join - (->> (sort (seq v)) - (map #(str " * " % "\n"))))))) + (->> (sort (seq v)) + (map #(str " * " % "\n"))))))) (defn- ->comment ([node] @@ -160,7 +155,7 @@ (defn- ->map-summary "Build the TOC for the given map" - [map-node map-loc] + [_ map-loc] (let [row-vs (loop [loc (-> map-loc z/node fu/->ddl-zip) row-m nil entries []] @@ -226,14 +221,14 @@ text) MapEntry - (->markdown-part [{:keys [key required?] :as this} loc] + (->markdown-part [{:keys [_ required?] :as this} loc] (str "entry-anchor loc) "\">\n" (->entry-header this loc) (->description this) (if required? "* This entry is required" "* This entry is optional") "\n" - (when (some-> loc z/down z/rightmost z/node fp/sequence-of?) + (when (some-> loc z/down z/rightmost z/node fp/seq-of?) "* This entry's type is sequential (allows zero or more values)\n") (when (some-> loc z/down z/rightmost z/node fp/set-of?) "* This entry's type is a set (allows zero or more distinct values)\n") @@ -243,19 +238,19 @@ (->short-description [_] "Property") SequenceOfType - (->markdown-part [{:keys [description]} loc] + (->markdown-part [_ _] nil) (->short-description [this] (str (->short-description (:type this)) " List")) SetOfType - (->markdown-part [{:keys [description]} loc] + (->markdown-part [_ _] nil) (->short-description [this] (str "#{" (->short-description (:type this)) "}")) ParameterListType - (->markdown-part [this loc] + (->markdown-part [_ _] nil) (->short-description [this] (str/join ", " (map (fn [schema] @@ -265,10 +260,10 @@ (get this :parameters)))) SignatureType - (->markdown-part [{:keys [description parameters] :as this} loc] - (str (if-some [fn-name (get this :name)] + (->markdown-part [{:keys [description] :as this} _] + (str (when-some [fn-name (get this :name)] (str "# `" fn-name "`" "\n\n")) - (if (not (str/blank? description)) + (when (not (str/blank? description)) (str "### Description" "\n\n" description @@ -298,7 +293,7 @@ (str "(" parameter-list-str ", " rest-parameter-str ") => " return-str)))) EitherType - (->markdown-part [this loc] + (->markdown-part [this _] (str (->description this :leaf) (->comment this) (->usage this :leaf) @@ -307,7 +302,7 @@ (->short-description [_] "Either") AnythingType - (->markdown-part [this loc] + (->markdown-part [this _] (str (->description this :leaf) (->comment this :leaf) (->usage this :leaf) @@ -315,7 +310,7 @@ (->short-description [_] "Anything") BooleanType - (->markdown-part [this loc] + (->markdown-part [this _] (str (->description this :leaf) (->comment this :leaf) (->usage this :leaf) @@ -356,7 +351,7 @@ (->short-description [this] (str (:name this) "String")) InstType - (->markdown-part [this loc] + (->markdown-part [this _] (str (->description this :leaf) (->comment this :leaf) (->usage this :leaf) @@ -413,7 +408,7 @@ (recur (z/next current-map-loc) maps-to-walk result-maps - map-counter ))))) + map-counter))))) (defn ->markdown [ddl-root] (let [[first-map & rest-maps] (find-maps ddl-root)] diff --git a/src/flanders/munge.clj b/src/flanders/munge.clj index 112659b..47d66a8 100644 --- a/src/flanders/munge.clj +++ b/src/flanders/munge.clj @@ -1,32 +1,17 @@ (ns flanders.munge - (:require [clojure - [zip :as z]] - [flanders - [navigation :as fn] - [predicates :as fp] - [protocols :as fprot] - [utils :as fu]])) - -(defn- dynaload - "Copyright (c) Rich Hickey (EPL 1.0). Copied from gen.clj" - [s] - (let [ns (namespace s)] - (assert ns) - (require (symbol ns)) - (let [v (resolve s)] - (if v - @v - (throw (RuntimeException. (str "Var " s " is not on the classpath"))))))) - -(def generator? - (let [g? (delay (dynaload 'clojure.test.check.generators/generator?))] - @g?)) + (:require + [clojure.test.check.generators :as gen] + [clojure.zip :as z] + [flanders.navigation :as fn] + [flanders.predicates :as fp] + [flanders.protocols :as fprot] + [flanders.utils :as fu])) (defmulti munge-action (fn [_ rule] (let [action (last rule)] (cond (fn? action) :apply-fn - (generator? action) :use-gen + (gen/generator? action) :use-gen :else action)))) (defn- entry-under-map [loc kw] diff --git a/src/flanders/navigation.cljc b/src/flanders/navigation.cljc index 6d0ed16..776112b 100644 --- a/src/flanders/navigation.cljc +++ b/src/flanders/navigation.cljc @@ -1,7 +1,8 @@ (ns flanders.navigation - (:require [clojure.zip :as z] - [flanders.predicates :as fp] - [flanders.utils :as fu])) + (:require + [clojure.zip :as z] + [flanders.predicates :as fp] + [flanders.utils :as fu])) (defn- keyword-key "Given a zip location of a KeywordType, if it is the :key of a diff --git a/src/flanders/predicates.cljc b/src/flanders/predicates.cljc index 23d4c53..d0abe00 100644 --- a/src/flanders/predicates.cljc +++ b/src/flanders/predicates.cljc @@ -1,15 +1,16 @@ (ns flanders.predicates - (:refer-clojure - :exclude [key keyword keyword? map map? sequential?]) - (:require [clojure.zip :as z] - [flanders.protocols :as prots] - #?(:clj [flanders.types] - :cljs [flanders.types - :refer [EitherType KeywordType MapEntry MapType - SequenceOfType SetOfType]])) - (:import #?(:clj [flanders.types - EitherType KeywordType MapEntry MapType SequenceOfType - SetOfType]))) + (:refer-clojure :exclude [key keyword keyword? map map? sequential?]) + (:require + #?(:clj [flanders.types] + :cljs [flanders.types + :refer [EitherType KeywordType MapEntry MapType + SequenceOfType SetOfType]]) + [clojure.zip :as z] + [flanders.protocols :as prots]) + (:import + #?(:clj [flanders.types + EitherType KeywordType MapEntry MapType SequenceOfType + SetOfType]))) ;; ---------------------------------------------------------------------- ;; about nodes diff --git a/src/flanders/schema.cljc b/src/flanders/schema.cljc index 557daaf..f81fb67 100644 --- a/src/flanders/schema.cljc +++ b/src/flanders/schema.cljc @@ -1,26 +1,34 @@ (ns flanders.schema (:refer-clojure :exclude [type key]) - (:require #?(:clj [clojure.core.match :refer [match]] - :cljs [cljs.core.match :refer-macros [match]]) - [clojure.zip :as z] - [flanders.predicates :as fp] - #?(:clj [flanders.types] - :cljs [flanders.types - :refer [AnythingType BooleanType EitherType - InstType IntegerType KeywordType - MapEntry MapType NumberType - ParameterListType SequenceOfType - SetOfType SignatureType StringType]]) - [flanders.protocols :as prots] - [flanders.utils :as fu] - #?(:clj [ring.swagger.json-schema :as rs]) - [schema.core :as s] - [schema-tools.core :as st]) - #?(:clj (:import [flanders.types - AnythingType BooleanType EitherType InstType - IntegerType KeywordType MapEntry MapType - NumberType ParameterListType SequenceOfType - SetOfType SignatureType StringType]))) + (:require + #?(:clj [clojure.core.match :refer [match]] + :cljs [cljs.core.match :refer-macros [match]]) + #?(:clj [flanders.types] + :cljs [flanders.types + :refer [AnythingType BooleanType EitherType InstType IntegerType + KeywordType MapEntry MapType NumberType ParameterListType + SequenceOfType SetOfType SignatureType StringType]]) + #?(:clj [ring.swagger.json-schema :as rs]) + [flanders.predicates :as fp] + [flanders.protocols :as prots] + [schema-tools.core :as st] + [schema.core :as s]) + #?(:clj (:import + [flanders.types + AnythingType + BooleanType + EitherType + InstType + IntegerType + KeywordType + MapEntry + MapType + NumberType + ParameterListType + SequenceOfType + SetOfType + SignatureType + StringType]))) (defprotocol SchemaNode (->schema' [node f])) @@ -86,7 +94,7 @@ #{(f type)}) SignatureType - (->schema' [{:keys [parameters rest-parameter return name]} f] + (->schema' [{:keys [parameters rest-parameter return]} f] (let [parameters (f parameters)] (s/make-fn-schema (f return) (if (some? rest-parameter) @@ -123,7 +131,7 @@ description)) KeywordType - (->schema' [{:keys [description key? open? values] :as node} _] + (->schema' [{:keys [description key? open? values]} _] (let [kw-schema (match [key? open? (seq values)] [_ true _ ] s/Keyword diff --git a/src/flanders/spec.clj b/src/flanders/spec.clj index 9ebbcc3..87428b3 100644 --- a/src/flanders/spec.clj +++ b/src/flanders/spec.clj @@ -1,13 +1,25 @@ (ns flanders.spec - (:require [clojure.core.match :refer [match]] - [clojure.spec.alpha :as s] - [clojure.zip :as z] - [flanders.types] - [flanders.utils :as fu]) - (:import [flanders.types - AnythingType BooleanType EitherType InstType IntegerType - KeywordType MapEntry MapType NumberType SequenceOfType - SetOfType SignatureType StringType])) + (:require + [clojure.core.match :refer [match]] + [clojure.spec.alpha :as s] + [clojure.zip :as z] + [flanders.types] + [flanders.utils :as fu]) + (:import + [flanders.types + AnythingType + BooleanType + EitherType + InstType + IntegerType + KeywordType + MapEntry + MapType + NumberType + SequenceOfType + SetOfType + SignatureType + StringType])) (defprotocol SpecedNode (->spec' [node ns f])) @@ -114,8 +126,7 @@ ;; Using gensym to produce a unique function name pending a ;; better approach. fn-name (str (gensym "fn__") "_" parameter-count - (if (some? rest-parameter) - "*")) + (when (some? rest-parameter) "*")) result-kw (keyword ns fn-name)] (eval `(s/fdef ~result-kw @@ -125,7 +136,7 @@ [(keyword parameter-name) (f parameter (str ns "." parameter-name))])) (range) parameters) - ~@(if (some? rest-parameter) + ~@(when (some? rest-parameter) [:a* `(s/* ~(f rest-parameter (str ns ".a*")))])) :ret ~(if (some? return) (f return (str ns ".return")) @@ -163,7 +174,7 @@ :else (set values)))) KeywordType - (->spec' [{:keys [gen open? spec values] :as node} _ _] + (->spec' [{:keys [open? spec values] :as node} _ _] (with-gen node (match [(some? spec) open? values] [true _ _ ] spec @@ -172,7 +183,7 @@ :else (set values)))) NumberType - (->spec' [{:keys [gen open? spec values] :as node} _ _] + (->spec' [{:keys [open? spec values] :as node} _ _] (with-gen node (match [(some? spec) open? (seq values)] [true _ _ ] spec @@ -181,7 +192,7 @@ :else (set values)))) StringType - (->spec' [{:keys [gen open? spec values] :as node} _ _] + (->spec' [{:keys [open? spec values] :as node} _ _] (with-gen node (match [(some? spec) open? (seq values)] [true _ _ ] spec @@ -222,8 +233,8 @@ (assoc-generator current-loc))))))) (s/fdef ->spec - :args (s/cat :node speced-node? :ns ns-str?) - :ret #(satisfies? s/Spec %)) + :args (s/cat :node speced-node? :ns ns-str?) + :ret #(satisfies? s/Spec %)) (defn ->spec [node ns] (letfn [(recursive-spec [node ns] diff --git a/src/flanders/type_script.clj b/src/flanders/type_script.clj index 09c97d6..e4f3c3e 100644 --- a/src/flanders/type_script.clj +++ b/src/flanders/type_script.clj @@ -2,8 +2,24 @@ "Render flanders.types types as TypeScript types. See: https://github.com/microsoft/TypeScript/blob/f30e8a284ac479a96ac660c94084ce5170543cc4/doc/spec.md#A" - (:require [clojure.string :as string] - [flanders.types])) + (:require + [clojure.string :as string] + [flanders.protocols :as fp]) + (:import + [flanders.types + AnythingType + BooleanType + EitherType + InstType + IntegerType + KeywordType + MapEntry + MapType + NumberType + SequenceOfType + SetOfType + SignatureType + StringType])) (def ^{:dynamic true} *flags* @@ -38,8 +54,8 @@ "Render `x` as a TypeScript type e.g. one of * UnionOrIntersectionOrPrimaryType, -   * FunctionType, or -   * ConstructorType + * FunctionType, or + * ConstructorType as defined in the TypeScript grammar." [x] @@ -52,14 +68,14 @@ (defn type-script-interface-declaration [x] - (if (satisfies? TypeScriptInterfaceDeclaration x) + (when (satisfies? TypeScriptInterfaceDeclaration x) (-type-script-interface-declaration x))) (defprotocol TypeScriptEnumDeclaration (-type-script-enum-declaration [this])) (defn type-enum-declaration [x] - (if (satisfies? TypeScriptEnumDeclaration x) + (when (satisfies? TypeScriptEnumDeclaration x) (-type-script-enum-declaration x))) (defprotocol TypeScriptPropertyNames @@ -67,7 +83,7 @@ (defn type-script-property-names [x] - (if (satisfies? TypeScriptPropertyNames x) + (when (satisfies? TypeScriptPropertyNames x) (-type-script-property-names x))) (defprotocol TypeScriptPropertySignatures @@ -75,7 +91,7 @@ (defn type-script-property-signatures [x] - (if (satisfies? TypeScriptPropertySignatures x) + (when (satisfies? TypeScriptPropertySignatures x) (-type-script-property-signatures x))) (defprotocol TypeScriptTypeName @@ -88,7 +104,7 @@ (let [x-name (if (satisfies? TypeScriptTypeName x) (-type-script-type-name x) (get x :name))] - (if (string? x-name) + (when (string? x-name) (type-script-munge x-name)))) (defn type-script-qualified-type-name [x] @@ -110,12 +126,12 @@ otherwise." {:private true} [x] - (instance? flanders.types.EitherType x)) + (instance? EitherType x)) (defn type-alias-declaration [x] - (if-some [type-name (type-script-type-name x)] - (if-some [type (type-script-type x)] + (when-some [type-name (type-script-type-name x)] + (when-some [type (type-script-type x)] (format "type %s = %s;" type-name type)))) (defn type-script-declaration @@ -139,24 +155,24 @@ ;; --------------------------------------------------------------------- ;; Protocol implementation -(extend-type flanders.types.AnythingType +(extend-type AnythingType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "any")) -(extend-type flanders.types.BooleanType +(extend-type BooleanType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "boolean")) -(extend-type flanders.types.EitherType +(extend-type EitherType TypeScriptType (-type-script-type [this] (type-script-union (get this :choices)))) -(extend-type flanders.types.KeywordType +(extend-type KeywordType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "string") TypeScriptPropertyNames @@ -166,17 +182,17 @@ (type-script-munge (name value))) (get this :values)))) -(extend-type flanders.types.IntegerType +(extend-type IntegerType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "number")) -(extend-type flanders.types.InstType +(extend-type InstType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "Date | string")) -(extend-type flanders.types.MapEntry +(extend-type MapEntry TypeScriptPropertySignatures (-type-script-property-signatures [this] (let [? (if (get this :required?) "" "?") @@ -189,7 +205,7 @@ (format "%s%s: %s" field-name ? field-type-name)) (type-script-property-names (get this :key)))))) -(extend-type flanders.types.MapType +(extend-type MapType TypeScriptType (-type-script-type [this] (if-some [signatures (seq (type-script-property-signatures this))] @@ -201,7 +217,7 @@ TypeScriptInterfaceDeclaration (-type-script-interface-declaration [this] - (if-some [type-name (type-script-type-name this)] + (when-some [type-name (type-script-type-name this)] (format "interface %s %s" type-name (-type-script-type this)))) TypeScriptPropertySignatures @@ -221,7 +237,7 @@ (string/join ", " (map pr-str (type-script-property-names k)))))) (conj entries (or (some (fn [entry] - (if-not (get entry :required?) + (when-not (get entry :required?) entry)) duplicate-entries) (first duplicate-entries)))) @@ -232,25 +248,25 @@ TypeScriptTypeName (-type-script-type-name [this] (let [this-name (get this :name)] - (if (string? this-name) + (when (string? this-name) this-name)))) -(extend-type flanders.types.NumberType +(extend-type NumberType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "number")) -(extend-type flanders.types.SetOfType +(extend-type SetOfType TypeScriptType (-type-script-type [this] (type-script-sequence-type (get this :type)))) -(extend-type flanders.types.SequenceOfType +(extend-type SequenceOfType TypeScriptType (-type-script-type [this] (type-script-sequence-type (get this :type)))) -(extend-type flanders.types.SignatureType +(extend-type SignatureType TypeScriptType (-type-script-type [this] (let [{:keys [parameters rest-parameter return]} this @@ -260,7 +276,7 @@ (str "a_" i ": " (type-script-qualified-type-name parameter))) (range) parameter-list) - ts-rest-parameter (if (some? rest-parameter) + ts-rest-parameter (when (some? rest-parameter) (str "...a_n: " (type-script-qualified-type-name rest-parameter))) ts-parameter-list (if (some? rest-parameter) (conj ts-parameter-list ts-rest-parameter) @@ -268,9 +284,9 @@ ts-return (type-script-type return)] (str "(" (string/join ", " ts-parameter-list) ") => " ts-return)))) -(extend-type flanders.types.StringType +(extend-type StringType TypeScriptType - (-type-script-type [this] + (-type-script-type [_] "string")) ;; --------------------------------------------------------------------- @@ -340,7 +356,7 @@ (loop [graph graph queue (conj clojure.lang.PersistentQueue/EMPTY root)] (if-some [node (peek queue)] - (let [node-children (flanders.protocols/node-children node) + (let [node-children (fp/node-children node) new-graph (add-edges graph node node-children) new-queue (into (pop queue) node-children)] (recur new-graph new-queue)) @@ -357,22 +373,22 @@ (let [named-nodes (type-script-named-nodes type-graph)] (run! (fn [[ts-name nodes]] - (let [nodes* (distinct nodes)] - (let [duplicate-count (count nodes*)] - (when (< 1 duplicate-count) - (printf "WARNING: %d types produce the TypeScript name `%s`:\n" - duplicate-count - ts-name) - (run! - (fn [node] - (printf " - %s (%s)\n" - (pr-str (get node :name)) - (.getName (class node))) - (print " ") - (prn node) - (print " meta - ") - (prn (meta node))) - nodes*))))) + (let [nodes* (distinct nodes) + duplicate-count (count nodes*)] + (when (< 1 duplicate-count) + (printf "WARNING: %d types produce the TypeScript name `%s`:\n" + duplicate-count + ts-name) + (run! + (fn [node] + (printf " - %s (%s)\n" + (pr-str (get node :name)) + (.getName (class node))) + (print " ") + (prn node) + (print " meta - ") + (prn (meta node))) + nodes*)))) (group-by type-script-type-name named-nodes)))) (defn type-script-declarations @@ -394,7 +410,7 @@ type-script-lines (sequence (comp (mapcat (fn [node] - (if-some [ts (type-script-declaration node)] + (when-some [ts (type-script-declaration node)] (if-some [description (get node :description)] [(string/replace description #"(?m:^)" "// ") ts] [ts])))) diff --git a/src/flanders/types.cljc b/src/flanders/types.cljc index 377e38d..9cc85dc 100644 --- a/src/flanders/types.cljc +++ b/src/flanders/types.cljc @@ -1,10 +1,11 @@ (ns flanders.types (:refer-clojure :exclude [defrecord type MapEntry ->MapEntry]) - (:require #?(:clj [flanders.macros :refer [defleaf]] - :cljs [flanders.macros :refer-macros [defleaf]]) - [flanders.protocols :refer [TreeNode]] - #?(:clj [schema.core :as s :refer [defrecord]] - :cljs [schema.core :as s :refer-macros [defrecord]]))) + (:require + #?(:clj [flanders.macros :refer [defleaf]] + :cljs [flanders.macros :refer-macros [defleaf]]) + #?(:clj [schema.core :as s :refer [defrecord]] + :cljs [schema.core :as s :refer-macros [defrecord]]) + [flanders.protocols :refer [TreeNode]])) (defrecord MapEntry [key :- (s/protocol TreeNode) type :- (s/protocol TreeNode) @@ -122,7 +123,7 @@ TreeNode (branch? [_] true) (node-children [_] (seq parameters)) - (make-node [this new-parameters] + (make-node [_ new-parameters] (ParameterListType. (vec new-parameters)))) (defrecord SignatureType [description :- (s/maybe s/Str) @@ -136,7 +137,7 @@ (if (some? rest-parameter) [parameters return rest-parameter] [parameters return])) - (make-node [this [new-parameters new-return new-rest-parameter]] + (make-node [_ [new-parameters new-return new-rest-parameter]] (SignatureType. description new-parameters new-rest-parameter diff --git a/src/flanders/utils.cljc b/src/flanders/utils.cljc index 2120321..494e125 100644 --- a/src/flanders/utils.cljc +++ b/src/flanders/utils.cljc @@ -1,8 +1,9 @@ (ns flanders.utils - (:require [clojure.zip :as z] - [flanders.predicates :as fp] - [flanders.protocols :refer [branch? node-children make-node]] - [flanders.types :as ft])) + (:require + [clojure.zip :as z] + [flanders.predicates :as fp] + [flanders.protocols :refer [branch? make-node node-children]] + [flanders.types :as ft])) (defn right-loc-seq "Lazy seq of loc and its right siblings" diff --git a/test/flanders/core_test.clj b/test/flanders/core_test.clj index 5b3cc0f..5e8c820 100644 --- a/test/flanders/core_test.clj +++ b/test/flanders/core_test.clj @@ -1,10 +1,11 @@ (ns flanders.core-test - (:require [clojure.test :refer [deftest is]] - [flanders.core :as f]) - (:import (flanders.types EitherType - MapType - SignatureType))) + (:require + [clojure.test :refer [deftest is]] + [flanders.core :as f]) + (:import + (flanders.types EitherType MapType SignatureType))) +#_{:clj-kondo/ignore [:inline-def :clojure-lsp/unused-public-var]} (deftest def-entity-type-test (is (thrown? clojure.lang.ExceptionInfo (f/def-entity-type Foo 'bad))) diff --git a/test/flanders/examples.clj b/test/flanders/examples.clj index 06a9ea3..919e5b7 100644 --- a/test/flanders/examples.clj +++ b/test/flanders/examples.clj @@ -1,5 +1,6 @@ (ns flanders.examples - (:require [flanders.core :as f])) + (:require + [flanders.core :as f])) (f/def-entity-type Example {:description "Example"} diff --git a/test/flanders/markdown_test.clj b/test/flanders/markdown_test.clj index 6eb2d38..13e63c0 100644 --- a/test/flanders/markdown_test.clj +++ b/test/flanders/markdown_test.clj @@ -1,28 +1,29 @@ (ns flanders.markdown-test - (:require [clojure.test :refer [deftest is]] - [flanders.core :as f] - [flanders.markdown :as f.markdown])) + (:require + [clojure.test :refer [deftest is]] + [flanders.core :as f] + [flanders.markdown :as md])) (deftest signature-type->markdown (is (= "### Signature\n\n() => Anything\n\n\n" - (f.markdown/->markdown (f/sig :parameters [])))) + (md/->markdown (f/sig :parameters [])))) (is (= "### Signature\n\n(Integer) => Anything\n\n\n\n" - (f.markdown/->markdown (f/sig :parameters [(f/int)])))) + (md/->markdown (f/sig :parameters [(f/int)])))) (is (= "### Signature\n\n(Integer, String) => Anything\n\n\n\n\n" - (f.markdown/->markdown (f/sig :parameters [(f/int) (f/str)])))) + (md/->markdown (f/sig :parameters [(f/int) (f/str)])))) (is (= "### Signature\n\n(Integer, String, Integer, String) => Anything\n\n\n\n\n\n\n" - (f.markdown/->markdown (f/sig :parameters [(f/int) (f/str) (f/int) (f/str)])))) + (md/->markdown (f/sig :parameters [(f/int) (f/str) (f/int) (f/str)])))) (is (= "### Signature\n\n(Integer, String ...) => Anything\n\n\n\n\n" - (f.markdown/->markdown (f/sig :parameters [(f/int)] :rest-parameter (f/str))))) + (md/->markdown (f/sig :parameters [(f/int)] :rest-parameter (f/str))))) (is (= "### Signature\n\n(Integer, String ...) => Anything\n\n\n\n\n" - (f.markdown/->markdown (f/sig :parameters [(f/int)] :rest-parameter (f/str))))) + (md/->markdown (f/sig :parameters [(f/int)] :rest-parameter (f/str))))) (is (= "# `Foo`\n\n### Description\n\nThe Foo.\n\n### Signature\n\n() => Anything\n\n\n" - (f.markdown/->markdown (f/sig :name "Foo" - :description "The Foo." - :parameters []))))) + (md/->markdown (f/sig :name "Foo" + :description "The Foo." + :parameters []))))) diff --git a/test/flanders/munge_test.clj b/test/flanders/munge_test.clj index 07ea64c..9b0761c 100644 --- a/test/flanders/munge_test.clj +++ b/test/flanders/munge_test.clj @@ -1,8 +1,8 @@ (ns flanders.munge-test - (:require [flanders - [core :as f] - [munge :as m]] - [clojure.test :refer [deftest is testing]])) + (:require + [clojure.test :refer [deftest is testing]] + [flanders.core :as f] + [flanders.munge :as m])) (deftest test-munge (testing "changing a field from optional to required" diff --git a/test/flanders/schema_test.clj b/test/flanders/schema_test.clj index d564941..07aff83 100644 --- a/test/flanders/schema_test.clj +++ b/test/flanders/schema_test.clj @@ -1,15 +1,10 @@ (ns flanders.schema-test - (:require [clojure.test :refer [deftest is]] - [flanders.examples - :refer [Example - OptionalKeywordMapEntryExample]] - [flanders.core :as f] - [flanders.utils :refer [optionalize-all]] - [flanders.schema :as fs] - [schema.core :as s - :refer [Keyword Any]]) - (:import (flanders.types ParameterListType - SignatureType))) + (:require + [clojure.test :refer [deftest is]] + [flanders.core :as f] + [flanders.examples :refer [Example OptionalKeywordMapEntryExample]] + [flanders.schema :as fs] + [schema.core :as s])) (deftest test-valid-schema (is @@ -25,7 +20,7 @@ (deftest test-optional-kw-map-entry (let [expected-schema {#schema.core.OptionalKey{:k :foo} java.lang.String - :relation_info {Keyword Any}}] + :relation_info {s/Keyword s/Any}}] (is (= expected-schema (fs/->schema OptionalKeywordMapEntryExample))))) diff --git a/test/flanders/spec_test.clj b/test/flanders/spec_test.clj index 7ca95ae..97d08c5 100644 --- a/test/flanders/spec_test.clj +++ b/test/flanders/spec_test.clj @@ -1,12 +1,13 @@ (ns flanders.spec-test - (:require [clojure.spec.alpha :as s] - [clojure.spec.test.alpha :as stest] - [clojure.test :refer [deftest is testing use-fixtures]] - [clojure.core.match :refer [match]] - [flanders.core :as f] - [flanders.examples :refer [Example]] - [flanders.spec :as fs] - [flanders.types :as ft])) + (:require + [clojure.core.match :refer [match]] + [clojure.spec.alpha :as s] + [clojure.spec.test.alpha :as stest] + [clojure.test :refer [deftest is testing use-fixtures]] + [flanders.core :as f] + [flanders.examples :refer [Example]] + [flanders.spec :as fs] + [flanders.types :as ft])) (use-fixtures :once (fn [t] diff --git a/test/flanders/type_script_test.clj b/test/flanders/type_script_test.clj index dce9d41..55d2ab9 100644 --- a/test/flanders/type_script_test.clj +++ b/test/flanders/type_script_test.clj @@ -1,8 +1,8 @@ (ns flanders.type-script-test - (:require [clojure.test :refer [deftest is]] - [flanders.core :as f] - [flanders.type-script :as f.ts] - [flanders.types :as f.t])) + (:require + [clojure.test :refer [deftest is]] + [flanders.core :as f] + [flanders.type-script :as f.ts])) (deftest anything-type-test (is (= "any" (f.ts/type-script-type (f/anything))))