-
Notifications
You must be signed in to change notification settings - Fork 11
/
helpers.jl
68 lines (57 loc) · 2.07 KB
/
helpers.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
macro endpoint(fun::Expr, epargs=:auto)
fname = fun.args[1]
fargs = fun.args[2:end]
epargs === :auto && (epargs = Expr(:tuple, map(ex -> ex.args[1], fargs)...))
ex = quote
export $fname
Base.@__doc__ $fname(f::Forge, $(fargs...); kwargs...) =
request(f, $fname, endpoint(f, $fname, $epargs...); kwargs...)
end
esc(ex)
end
"""
@json struct T ... end
Create a type that can be parsed from JSON.
"""
macro json(def::Expr)
T = def.args[2]
renames = Expr[]
names = Symbol[]
for field in def.args[3].args
field isa Expr || continue
if field.head === :(::)
push!(names, field.args[1])
# Make the field nullable.
field.args[2] = :(Union{$(field.args[2]), Nothing})
elseif field.head === :call && field.args[1] === :(=>)
push!(names, field.args[2])
# Convert from => to::F to to::F, and record the old name.
from = QuoteNode(field.args[2])
to, F = field.args[3].args
field.head = :(::)
field.args = [to, :(Union{$F, Nothing})]
push!(renames, :($to => (; name=$from)))
else
@warn "Invalid field expression $field"
end
end
# Add a field for unhandled keys.
push!(def.args[3].args, :(_extras::NamedTuple))
# Document the struct.
def = :(Base.@__doc__ $def)
# Create a keyword constructor.
kws = map(name -> Expr(:kw, name, :nothing), names)
cons = :($T(; $(kws...), kwargs...) = $T($(names...), (; kwargs...)))
# Apply the kwargs format with any renames.
fmt = :(JSON2.@format $T keywordargs)
isempty(renames) || push!(fmt.args, Expr(:block, renames...))
# Set the default parse options,
dfkws = quote
if isdefined(@__MODULE__, :JSON_OPTS)
# This isn't how you're "supposed" to do this, but I'm not quite sure
# how to pass these options as literal keywords to @format.
JSON2.defaultkwargs(::Type{$T}) = JSON_OPTS
end
end
esc(Expr(:block, def, cons, fmt, dfkws))
end