-
Notifications
You must be signed in to change notification settings - Fork 147
/
values.ex
71 lines (61 loc) · 1.88 KB
/
values.ex
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
69
70
71
defmodule Surface.Directive.Values do
use Surface.Directive
def extract({":values", {:attribute_expr, value, expr_meta}, attr_meta}, meta) do
expr_meta = Helpers.to_meta(expr_meta, meta)
attr_meta = Helpers.to_meta(attr_meta, meta)
%AST.Directive{
module: __MODULE__,
name: :values,
value: directive_value(value, expr_meta),
meta: attr_meta
}
end
def extract(_, _), do: []
def process(
%AST.Directive{
value: %AST.AttributeExpr{value: value} = expr,
meta: meta
},
%type{attributes: attributes} = node
)
when type in [AST.Tag, AST.VoidTag] do
attr_names = for %AST.Attribute{name: name} <- attributes, do: name
new_expr =
quote generated: true do
for {name, value} <- unquote(value) || [],
attr_name = :"phx-value-#{name}",
not Enum.member?(unquote(Macro.escape(attr_names)), attr_name) do
unquote(__MODULE__).validate_value!(name, value)
{attr_name, {Surface.TypeHandler.attribute_type_and_opts(attr_name), to_string(value)}}
end
end
%{
node
| attributes: [
%AST.DynamicAttribute{
name: :values,
meta: meta,
expr: %AST.AttributeExpr{expr | value: new_expr}
}
| attributes
]
}
end
defp directive_value(value, meta) do
AST.AttributeExpr.new(
Surface.TypeHandler.expr_to_quoted!(value, ":values", :map, meta),
value,
meta
)
end
def validate_value!(name, value) do
unless String.Chars.impl_for(value) do
message = """
invalid value for key "#{inspect(name)}" in attribute ":values".
Expected a type that implements the String.Chars protocol (e.g. string, boolean, integer, atom, ...), \
got: #{inspect(value)}\
"""
IOHelper.runtime_error(message)
end
end
end