-
Notifications
You must be signed in to change notification settings - Fork 23
/
section.ex
138 lines (108 loc) · 3.48 KB
/
section.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
defmodule Spark.Dsl.Section do
@moduledoc """
Declares a DSL section.
A dsl section allows you to organize related configurations. All extensions
configure sections, they cannot add DSL builders to the top level. This
keeps things organized, and concerns separated.
A section may have nested sections, which will be configured the same as other sections.
Getting the options/entities of a section is done by providing a path, so you would
use the nested path to retrieve that configuration. See `Spark.Dsl.Extension.get_entities/2`
and `Spark.Dsl.Extension.get_opt/4`.
A section may have entities, which are constructors that produce instances of structs.
For more on entities, see `Spark.Dsl.Entity`.
A section may also have a `schema`, which is a `NimbleOptions` schema. Spark will produce
builders for those options, so that they may be configured. They are retrieved with
`Spark.Dsl.Extension.get_opt/4`.
To create a section that is available at the top level (i.e not nested inside of its own name), use
`top_level?: true`. Remember, however, that this has no effect on sections nested inside of other sections.
For a full example, see `Spark.Dsl.Extension`.
"""
defstruct [
:name,
imports: [],
schema: [],
describe: "",
snippet: "",
links: nil,
examples: [],
modules: [],
top_level?: false,
no_depend_modules: [],
auto_set_fields: [],
deprecations: [],
entities: [],
sections: [],
docs: "",
patchable?: false
]
alias Spark.{
Dsl.Entity,
Dsl.Section,
OptionsHelpers
}
@type name :: atom()
@type imports :: [module]
@typedoc """
User provided documentation.
Documentation provided in a `Section`'s `describe` field will be included by `Spark` in any generated documentation that includes the `Section`.
"""
@type describe :: String.t()
@type snippet :: String.t()
@typedoc """
Determines whether a section can be declared directly in a module.
When `top_level?: true`, that Section's DSL can be declared outside of a `do` block in a module.
## Example
A `Section` declared with `top_level?: true`:
```elixir
@my_section %Spark.Dsl.Section{
top_level?: true,
name: :my_section,
schema: [my_field: [type: :atom, required: true]]
}
```
Can be declared like this:
```elixir
defmodule MyDslModule do
my_field :value
end
```
With `top_level?: false`, the DSL section would need to be declared explicitly/:
```elixir
defmodule MyDslModule do
my_section do
my_field :value
end
end
```
"""
@type top_level?() :: boolean()
@type links :: nil | Keyword.t([String.t()])
@type examples() :: [String.t()]
@type modules :: [atom]
@type no_depend_modules() :: [atom]
@type auto_set_fields() :: Keyword.t(any)
@type entities :: [Entity.t()]
@type sections :: [Section.t()]
@typedoc """
Internal field. Not set by user.
"""
@type docs :: String.t()
@type patchable? :: boolean()
@type t :: %Section{
name: name(),
imports: imports(),
schema: OptionsHelpers.schema(),
describe: describe(),
snippet: snippet(),
top_level?: top_level?(),
links: links(),
examples: examples(),
modules: modules(),
no_depend_modules: no_depend_modules(),
auto_set_fields: auto_set_fields(),
entities: entities(),
sections: sections(),
docs: docs(),
patchable?: patchable?()
}
end