Malli schemas for Ant tasks and types, derived at runtime from
Ant's own IntrospectionHelper.
Why malli? Schemas here are values, not macros — which means we can
manufacture them on the fly from reflection data without a single
defmacro and without stuffing things into a global registry the
generator has to know about. They are also easy to transform,
which matters for Ant: the underlying setters all accept String
but the conceptual type might be boolean, int, File, or an
enum. Malli's string-transformer plus a few custom decoders gives
us validation without forcing users to type strings everywhere.
Two entry points:
(schema-for :copy) ; -> a [:map ...] schema (validate :copy attrs) ; -> nil if valid, else humanized errors
Malli schemas for Ant tasks and types, derived at runtime from Ant's own `IntrospectionHelper`. Why malli? Schemas here are values, not macros — which means we can manufacture them on the fly from reflection data without a single `defmacro` and without stuffing things into a global registry the generator has to know about. They are also easy to *transform*, which matters for Ant: the underlying setters all accept `String` but the conceptual type might be `boolean`, `int`, `File`, or an enum. Malli's `string-transformer` plus a few custom decoders gives us validation without forcing users to type strings everywhere. Two entry points: (schema-for :copy) ; -> a [:map ...] schema (validate :copy attrs) ; -> nil if valid, else humanized errors
(schema-for tag)(schema-for tag {:keys [closed? parent]})Return a cached malli schema for a tag (e.g. :copy). Returns nil
for unknown tags. With :closed? true, the schema rejects unknown
attributes (useful for catching typos like :tdoir).
Pass :parent <parent-tag> to scope the schema to the specific
class that tag resolves to under that parent -- relevant for
context-ambiguous tags like :attribute (different classes under
<macrodef> vs <manifest>). Without a parent, the schema is the
union over every recorded class.
Return a cached malli schema for a tag (e.g. `:copy`). Returns nil for unknown tags. With `:closed? true`, the schema rejects unknown attributes (useful for catching typos like `:tdoir`). Pass `:parent <parent-tag>` to scope the schema to the specific class that tag resolves to under that parent -- relevant for context-ambiguous tags like `:attribute` (different classes under <macrodef> vs <manifest>). Without a parent, the schema is the union over every recorded class.
(validate tag attrs)(validate tag attrs opts)Validate an attribute map against the schema for tag. Returns nil
if valid, a humanized error map otherwise. Returns nil if the tag is
unknown -- we don't want validation to refuse to run for tasks
loaded via <taskdef>.
Options: :closed? reject unknown attributes too (default false). :parent <parent-tag> used to disambiguate context-sensitive nested tags. Lets <attribute> under <macrodef> validate against MacroDef$Attribute even though the same tag means Manifest$Attribute under <manifest>.
Validate an attribute map against the schema for `tag`. Returns nil
if valid, a humanized error map otherwise. Returns nil if the tag is
unknown -- we don't want validation to refuse to run for tasks
loaded via `<taskdef>`.
Options:
:closed? reject unknown attributes too (default false).
:parent <parent-tag> used to disambiguate context-sensitive
nested tags. Lets <attribute> under <macrodef>
validate against MacroDef$Attribute even though the
same tag means Manifest$Attribute under <manifest>.(validate! tag attrs)(validate! tag attrs opts)Like validate, but throws when invalid. Returns nil on success.
Like `validate`, but throws when invalid. Returns nil on success.
(validate-tree element)(validate-tree element opts)Walk a element tree and collect all validation errors as a vector of
{:tag :path :errors} maps. With :closed? true, issues may also
include :suggestions for likely misspelled attribute names. Empty
vector means everything checks out.
Attributes with manual metadata of exactly Required: Yes are reported
as missing before Ant runs. Conditional requirements such as Yes, unless ... are deliberately left to Ant.
Threads parent context down so context-ambiguous nested tags
(:attribute under <macrodef> vs <manifest>, :element under
<scriptdef> vs <macrodef>, ...) validate against the correct
class for their parent.
Options forwarded to validate (notably :closed?).
Walk a element tree and collect all validation errors as a vector of
`{:tag :path :errors}` maps. With `:closed? true`, issues may also
include `:suggestions` for likely misspelled attribute names. Empty
vector means everything checks out.
Attributes with manual metadata of exactly `Required: Yes` are reported
as missing before Ant runs. Conditional requirements such as `Yes, unless
...` are deliberately left to Ant.
Threads parent context down so context-ambiguous nested tags
(`:attribute` under <macrodef> vs <manifest>, `:element` under
<scriptdef> vs <macrodef>, ...) validate against the correct
class for their parent.
Options forwarded to `validate` (notably `:closed?`).cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |