@@ -219,3 +219,136 @@ func Test_shadowLoad_sectionsDoNotInherit(t *testing.T) {
219219 t .Errorf ("[*.txt] should hold only its own styles; got %v" , got )
220220 }
221221}
222+
223+ // A level set under a section belongs to that section. Collecting them all in
224+ // one map let the last section in the file decide the level everywhere. See
225+ // #965.
226+ func Test_processConfig_sectionLevels (t * testing.T ) {
227+ cases := []struct {
228+ description string
229+ body string
230+ levels map [string ]map [string ]string
231+ global map [string ]string
232+ }{
233+ {
234+ description : "one section overrides a shared style" ,
235+ body : `[*.{html,md}]
236+ BasedOnStyles = Vale
237+
238+ [*.md]
239+ Vale.Spelling = warning
240+ ` ,
241+ levels : map [string ]map [string ]string {
242+ "*.{html,md}" : {},
243+ "*.md" : {"Vale.Spelling" : "warning" },
244+ },
245+ global : map [string ]string {},
246+ },
247+ {
248+ description : "each section keeps its own level" ,
249+ body : `[*.html]
250+ Vale.Spelling = error
251+
252+ [*.md]
253+ Vale.Spelling = warning
254+ ` ,
255+ levels : map [string ]map [string ]string {
256+ "*.html" : {"Vale.Spelling" : "error" },
257+ "*.md" : {"Vale.Spelling" : "warning" },
258+ },
259+ global : map [string ]string {},
260+ },
261+ {
262+ description : "a level under [*] stays global" ,
263+ body : `[*]
264+ Vale.Spelling = suggestion
265+
266+ [*.md]
267+ BasedOnStyles = Vale
268+ ` ,
269+ levels : map [string ]map [string ]string {
270+ "*.md" : {},
271+ },
272+ global : map [string ]string {"Vale.Spelling" : "suggestion" },
273+ },
274+ {
275+ description : "YES and NO carry no level" ,
276+ body : `[*.md]
277+ Vale.Spelling = YES
278+ Vale.Repetition = NO
279+ ` ,
280+ levels : map [string ]map [string ]string {
281+ "*.md" : {},
282+ },
283+ global : map [string ]string {},
284+ },
285+ }
286+
287+ for _ , c := range cases {
288+ t .Run (c .description , func (t * testing.T ) {
289+ uCfg , err := shadowLoad ([]byte (c .body ))
290+ if err != nil {
291+ t .Fatal (err )
292+ }
293+
294+ conf , err := NewConfig (& CLIFlags {})
295+ if err != nil {
296+ t .Fatal (err )
297+ }
298+
299+ if _ , err = processConfig (uCfg , conf , false ); err != nil {
300+ t .Fatal (err )
301+ }
302+
303+ for sec , want := range c .levels {
304+ got := conf .SLevels [sec ]
305+ if len (got ) != len (want ) {
306+ t .Fatalf ("SLevels[%q] = %v, want %v" , sec , got , want )
307+ }
308+ for k , v := range want {
309+ if got [k ] != v {
310+ t .Errorf ("SLevels[%q][%q] = %q, want %q" , sec , k , got [k ], v )
311+ }
312+ }
313+ }
314+
315+ if len (conf .RuleToLevel ) != len (c .global ) {
316+ t .Fatalf ("RuleToLevel = %v, want %v" , conf .RuleToLevel , c .global )
317+ }
318+ for k , v := range c .global {
319+ if conf .RuleToLevel [k ] != v {
320+ t .Errorf ("RuleToLevel[%q] = %q, want %q" , k , conf .RuleToLevel [k ], v )
321+ }
322+ }
323+ })
324+ }
325+ }
326+
327+ // A file reports a rule at the level its own sections gave it, falling back to
328+ // the level the rule was compiled with.
329+ func TestFileLevel (t * testing.T ) {
330+ f := File {Levels : map [string ]string {
331+ "Vale.Spelling" : "warning" ,
332+ "proselint" : "suggestion" ,
333+ }}
334+
335+ tests := []struct {
336+ name string
337+ rule string
338+ compiled string
339+ want string
340+ }{
341+ {"the rule itself" , "Vale.Spelling" , "error" , "warning" },
342+ {"its style" , "proselint.Typography" , "error" , "suggestion" },
343+ {"neither" , "Microsoft.Wordiness" , "error" , "error" },
344+ }
345+
346+ for _ , tt := range tests {
347+ t .Run (tt .name , func (t * testing.T ) {
348+ if got := f .Level (tt .rule , tt .compiled ); got != tt .want {
349+ t .Errorf ("Level(%q, %q) = %q, want %q" ,
350+ tt .rule , tt .compiled , got , tt .want )
351+ }
352+ })
353+ }
354+ }
0 commit comments