Skip to content

Commit 23937e9

Browse files
authored
Merge pull request #19 from JuliaObjects/setproperr
Improve setproperties error message
2 parents 0efa52d + 9515d4a commit 23937e9

File tree

2 files changed

+36
-21
lines changed

2 files changed

+36
-21
lines changed

src/ConstructionBase.jl

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,37 @@ struct NamedTupleConstructor{names} end
3939
end
4040
end
4141

42-
function assert_hasfields(T, fnames)
43-
for fname in fnames
44-
if !(fname in fieldnames(T))
45-
msg = "$T has no field $fname"
46-
throw(ArgumentError(msg))
47-
end
48-
end
49-
end
50-
5142
function setproperties(obj; kw...)
5243
setproperties(obj, (;kw...))
5344
end
5445

5546
@generated function setproperties(obj, patch::NamedTuple)
56-
assert_hasfields(obj, fieldnames(patch))
57-
args = map(fieldnames(obj)) do fn
58-
if fn in fieldnames(patch)
59-
:(patch.$fn)
60-
else
61-
:(obj.$fn)
47+
if issubset(fieldnames(patch), fieldnames(obj))
48+
args = map(fieldnames(obj)) do fn
49+
if fn in fieldnames(patch)
50+
:(patch.$fn)
51+
else
52+
:(obj.$fn)
53+
end
6254
end
55+
return Expr(:block,
56+
Expr(:meta, :inline),
57+
Expr(:call,:(constructorof($obj)), args...)
58+
)
59+
else
60+
:(setproperties_unknown_field_error(obj, patch))
6361
end
64-
Expr(:block,
65-
Expr(:meta, :inline),
66-
Expr(:call,:(constructorof($obj)), args...)
67-
)
62+
end
63+
64+
function setproperties_unknown_field_error(obj, patch)
65+
O = typeof(obj)
66+
P = typeof(patch)
67+
msg = """
68+
Failed to assign properties $(fieldnames(P)) to object with fields $(fieldnames(O)).
69+
You may want to overload
70+
ConstructionBase.setproperties(obj::$O, patch::NamedTuple)
71+
"""
72+
throw(ArgumentError(msg))
6873
end
6974

7075

test/runtests.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@ end
2424
@test setproperties(o, (a=2, b=3.0)) === AB(2,3.0)
2525
@test setproperties(o, a=2, b=3.0) === AB(2,3.0)
2626

27-
@test_throws ArgumentError setproperties(o, (a=2, c=3.0))
28-
@test_throws ArgumentError setproperties(o, a=2, c=3.0)
27+
res = @test_throws ArgumentError setproperties(o, (a=2, this_field_does_not_exist=3.0))
28+
msg = sprint(showerror, res.value)
29+
@test occursin("this_field_does_not_exist", msg)
30+
@test occursin("overload", msg)
31+
@test occursin("ConstructionBase.setproperties", msg)
32+
33+
res = @test_throws ArgumentError setproperties(o, a=2, this_field_does_not_exist=3.0)
34+
msg = sprint(showerror, res.value)
35+
@test occursin("this_field_does_not_exist", msg)
36+
@test occursin("overload", msg)
37+
@test occursin("ConstructionBase.setproperties", msg)
38+
2939
@test setproperties(Empty(), NamedTuple()) === Empty()
3040
@test setproperties(Empty()) === Empty()
3141

0 commit comments

Comments
 (0)