11local Iter = require (' render-markdown.lib.iter' )
22
3+ --- @alias render.md.debug.SpecKind ' type' | ' value'
4+
35--- @class render.md.debug.Spec
6+ --- @field kind render.md.debug.SpecKind
47--- @field message string
58--- @field validation fun ( value : any ): boolean , string ?
69
@@ -56,38 +59,39 @@ function Spec:nested(keys, f, nilable)
5659end
5760
5861--- @param keys string | string[]
59- --- @param input_types type | type[]
62+ --- @param ts type | type[]
6063--- @return render.md.debug.ValidatorSpec
61- function Spec :type (keys , input_types )
62- local types , message = self :handle_types (input_types , ' ' )
63- return self :add (keys , message , function (value )
64+ function Spec :type (keys , ts )
65+ local types , message = self :handle_types ({}, ts )
66+ return self :add (keys , ' type ' , message , function (value )
6467 return vim .tbl_contains (types , type (value ))
6568 end )
6669end
6770
6871--- @param keys string | string[]
6972--- @param values string[]
70- --- @param input_types ? type | type[]
73+ --- @param ts ? type | type[]
7174--- @return render.md.debug.ValidatorSpec
72- function Spec :one_of (keys , values , input_types )
73- local types , message = self :handle_types (input_types , ' one of ' .. vim .inspect (values ))
74- return self :add (keys , message , function (value )
75+ function Spec :one_of (keys , values , ts )
76+ local options = Iter .list .map (values , vim .inspect )
77+ local types , message = self :handle_types (options , ts )
78+ return self :add (keys , ' value' , message , function (value )
7579 return vim .tbl_contains (values , value ) or vim .tbl_contains (types , type (value ))
7680 end )
7781end
7882
7983--- @param keys string | string[]
80- --- @param list_type type
81- --- @param input_types ? type | type[]
84+ --- @param t type
85+ --- @param ts ? type | type[]
8286--- @return render.md.debug.ValidatorSpec
83- function Spec :list (keys , list_type , input_types )
84- local types , message = self :handle_types (input_types , list_type .. ' list ' )
85- return self :add (keys , message , function (value )
87+ function Spec :list (keys , t , ts )
88+ local types , message = self :handle_types ({ t .. ' [] ' }, ts )
89+ return self :add (keys , ' type ' , message , function (value )
8690 if vim .tbl_contains (types , type (value )) then
8791 return true
8892 elseif type (value ) == ' table' then
8993 for i , item in ipairs (value ) do
90- if type (item ) ~= list_type then
94+ if type (item ) ~= t then
9195 return false , string.format (' [%d] is %s' , i , type (item ))
9296 end
9397 end
@@ -99,23 +103,23 @@ function Spec:list(keys, list_type, input_types)
99103end
100104
101105--- @param keys string | string[]
102- --- @param list_type type
103- --- @param input_types ? type | type[]
106+ --- @param t type
107+ --- @param ts ? type | type[]
104108--- @return render.md.debug.ValidatorSpec
105- function Spec :list_or_list_of_list (keys , list_type , input_types )
106- local types , message = self :handle_types (input_types , list_type .. ' list or list of list ' )
107- return self :add (keys , message , function (value )
108- if vim .tbl_contains (types , type (value )) then
109+ function Spec :nested_list (keys , t , ts )
110+ local types , message = self :handle_types ({ t , t .. ' [] ' , t .. ' [][] ' }, ts )
111+ return self :add (keys , ' type ' , message , function (value )
112+ if type ( value ) == t or vim .tbl_contains (types , type (value )) then
109113 return true
110114 elseif type (value ) == ' table' then
111115 for i , item in ipairs (value ) do
112116 if type (item ) == ' table' then
113117 for j , nested in ipairs (item ) do
114- if type (nested ) ~= list_type then
118+ if type (nested ) ~= t then
115119 return false , string.format (' [%d][%d] is %s' , i , j , type (nested ))
116120 end
117121 end
118- elseif type (item ) ~= list_type then
122+ elseif type (item ) ~= t then
119123 return false , string.format (' [%d] is %s' , i , type (item ))
120124 end
121125 end
@@ -128,11 +132,12 @@ end
128132
129133--- @param keys string | string[]
130134--- @param values string[]
131- --- @param input_types ? type | type[]
135+ --- @param ts ? type | type[]
132136--- @return render.md.debug.ValidatorSpec
133- function Spec :one_or_list_of (keys , values , input_types )
134- local types , message = self :handle_types (input_types , ' one or list of ' .. vim .inspect (values ))
135- return self :add (keys , message , function (value )
137+ function Spec :one_or_list_of (keys , values , ts )
138+ local options = ' (' .. table.concat (Iter .list .map (values , vim .inspect ), ' |' ) .. ' )'
139+ local types , message = self :handle_types ({ options , options .. ' []' }, ts )
140+ return self :add (keys , ' type' , message , function (value )
136141 if vim .tbl_contains (types , type (value )) then
137142 return true
138143 elseif type (value ) == ' string' then
@@ -151,41 +156,35 @@ function Spec:one_or_list_of(keys, values, input_types)
151156end
152157
153158--- @private
154- --- @param input_types ? type | type []
155- --- @param prefix string
159+ --- @param custom string []
160+ --- @param ts ? type | type[]
156161--- @return type[] , string
157- function Spec :handle_types (input_types , prefix )
162+ function Spec :handle_types (custom , ts )
158163 local types = nil
159- if input_types == nil then
164+ if ts == nil then
160165 types = {}
161- elseif type (input_types ) == ' string' then
162- types = { input_types }
166+ elseif type (ts ) == ' string' then
167+ types = { ts }
163168 else
164- types = input_types
169+ types = ts
165170 end
166171 if self .nilable and not vim .tbl_contains (types , ' nil' ) then
167172 table.insert (types , ' nil' )
168173 end
169- local message = prefix
170- if # types > 0 then
171- if # message > 0 then
172- message = message .. ' or '
173- end
174- message = message .. ' type ' .. table.concat (types , ' or ' )
175- end
176- return types , message
174+ return types , table.concat (vim .list_extend (custom , types ), ' or ' )
177175end
178176
179177--- @private
180178--- @param keys string | string[]
179+ --- @param kind render.md.debug.SpecKind
181180--- @param message string
182181--- @param validation fun ( v : any ): boolean , string ?
183182--- @return render.md.debug.ValidatorSpec
184- function Spec :add (keys , message , validation )
183+ function Spec :add (keys , kind , message , validation )
185184 if self .config ~= nil then
186185 keys = type (keys ) == ' table' and keys or { keys }
187186 for _ , key in ipairs (keys ) do
188- self .specs [key ] = { message = message , validation = validation }
187+ self .specs [key ] = { kind = kind , message = message , validation = validation }
189188 end
190189 end
191190 return self
@@ -223,7 +222,13 @@ function Validator:check(path, config, specs)
223222 local value = config [key ]
224223 local ok , info = spec .validation (value )
225224 if not ok then
226- local message = string.format (' %s.%s: expected %s, got %s' , path , key , spec .message , type (value ))
225+ local message = string.format (' %s.%s - expected: %s' , path , key , spec .message )
226+ if spec .kind == ' type' then
227+ message = message .. string.format (' , but got: %s' , type (value ))
228+ end
229+ if spec .kind == ' value' then
230+ message = message .. string.format (' , but got: %s' , vim .inspect (value ))
231+ end
227232 if info ~= nil then
228233 message = message .. string.format (' , info: %s' , info )
229234 end
@@ -232,7 +237,7 @@ function Validator:check(path, config, specs)
232237 end
233238 for key , _ in pairs (config ) do
234239 if specs [key ] == nil then
235- local message = string.format (' %s.%s: is not a valid key' , path , key )
240+ local message = string.format (' %s.%s - invalid key' , path , key )
236241 table.insert (self .errors , message )
237242 end
238243 end
0 commit comments