1
16
17 package warn
18
19 import "testing"
20
21 func TestModuleDocstring(t *testing.T) {
22 checkFindings(t, "module-docstring", ``,
23 []string{},
24 scopeBzl|scopeDefault)
25
26 checkFindings(t, "module-docstring", `
27 # empty file`,
28 []string{},
29 scopeBzl|scopeDefault)
30
31 checkFindings(t, "module-docstring", `
32 """This is the module"""
33
34 load("foo", "bar")
35
36 bar()`,
37 []string{},
38 scopeBzl|scopeDefault)
39
40 checkFindings(t, "module-docstring", `
41 load("foo", "bar")
42
43 """This is the module"""
44
45 bar()`,
46 []string{":1: The file has no module docstring."},
47 scopeBzl|scopeDefault)
48
49 checkFindings(t, "module-docstring", `
50 # comment
51
52 # comment
53 """This is the module"""
54
55 load("foo", "bar")
56
57 bar()`,
58 []string{},
59 scopeBzl|scopeDefault)
60
61 checkFindings(t, "module-docstring", `
62 # comment
63
64 load("foo", "bar")
65
66 # comment
67 """This is the module"""
68
69 bar()`,
70 []string{":3: The file has no module docstring."},
71 scopeBzl|scopeDefault)
72
73 checkFindings(t, "module-docstring", `
74 def foo(bar):
75 if bar:
76 f()
77 return g()`,
78 []string{":1: The file has no module docstring."},
79 scopeBzl|scopeDefault)
80 }
81
82 func TestFunctionDocstringExists(t *testing.T) {
83 checkFindings(t, "function-docstring", `
84 def f(x):
85 # short function
86 return x
87 `,
88 []string{},
89 scopeEverywhere)
90
91 checkFindings(t, "function-docstring", `
92 def f(x):
93 """Short function with a docstring"""
94 return x
95 `,
96 []string{},
97 scopeEverywhere)
98
99 checkFindings(t, "function-docstring", `
100 def f(x):
101 # long function
102 x += 1
103 x *= 2
104 x /= 3
105 x -= 4
106 x %= 5
107 return x
108 `,
109 []string{":1: The function \"f\" has no docstring."},
110 scopeEverywhere)
111
112 checkFindings(t, "function-docstring", `
113 def f(x):
114 def g(x):
115 # long function
116 x += 1
117 x *= 2
118 x /= 3
119 x -= 4
120 x %= 5
121 return x
122 return g
123 `,
124 []string{},
125 scopeEverywhere)
126
127 checkFindings(t, "function-docstring", `
128 def _f(x):
129 # long private function
130 x += 1
131 x *= 2
132 x /= 3
133 x -= 4
134 x %= 5
135 return x
136 `,
137 []string{},
138 scopeEverywhere)
139 }
140
141 func TestFunctionDocstringHeader(t *testing.T) {
142 checkFindings(t, "function-docstring-header", `
143 def f():
144 """This is a function.
145 this is the description
146 """
147 pass
148 pass
149 pass
150 pass
151 pass
152 `,
153 []string{`2: The docstring for the function "f" should start with a one-line summary.`},
154 scopeEverywhere)
155
156 checkFindings(t, "function-docstring-header", `
157 def f():
158 def g():
159 """This is a function.
160 this is the description
161 """
162 pass
163 pass
164 pass
165 pass
166 pass
167 return f
168 `,
169 []string{`3: The docstring for the function "g" should start with a one-line summary.`},
170 scopeEverywhere)
171
172 checkFindings(t, "function-docstring-header", `
173 def _f(x):
174 """Long private function
175 with a docstring"""
176 x += 1
177 x *= 2
178 x /= 3
179 x -= 4
180 x %= 5
181 return x
182 `,
183 []string{
184 `:2: The docstring for the function "_f" should start with a one-line summary.`,
185 },
186 scopeEverywhere)
187
188 checkFindings(t, "function-docstring-header", `
189 def f(x):
190 """Long function with a docstring
191
192 Docstring
193 body
194 """
195 x += 1
196 x *= 2
197 x /= 3
198 x -= 4
199 x %= 5
200 return x
201 `,
202 []string{},
203 scopeEverywhere)
204
205 checkFindings(t, "function-docstring-header", `
206 def f():
207 """
208
209 This is a function.
210
211 This is a
212 multiline description"""
213 pass
214 pass
215 pass
216 pass
217 pass
218 `,
219 []string{},
220 scopeEverywhere)
221
222 checkFindings(t, "function-docstring-header", `
223 def f():
224 """\r
225 Header in a CRLF formatted file.\r
226 \r
227 This is a\r
228 multiline description"""
229 `,
230 []string{},
231 scopeEverywhere)
232
233 }
234
235 func TestFunctionDocstringArgs(t *testing.T) {
236 checkFindings(t, "function-docstring-args", `
237 def f(x):
238 """This is a function.
239
240 Documented here:
241 http://example.com
242
243 Args:
244 x: something, as described at
245 http://example.com
246
247 Returns:
248 something, as described at
249 https://example.com
250 """
251 pass
252 pass
253 pass
254 pass
255 pass
256 return x
257 `,
258 []string{},
259 scopeEverywhere)
260
261 checkFindings(t, "function-docstring-args", `
262 def f(x):
263 """This is a function.
264
265 Args:
266 x: something
267 """
268 passf
269 pass
270 pass
271 pass
272 pass
273 `,
274 []string{},
275 scopeEverywhere)
276
277 checkFindings(t, "function-docstring-args", `
278 def f(x, y):
279 """Short function with a docstring
280
281 Arguments:
282 x: smth
283 """
284 return x + y
285 `,
286 []string{
287 `2: Argument "y" is not documented.`,
288 `4: Prefer "Args:" to "Arguments:" when documenting function arguments.`,
289 },
290 scopeEverywhere)
291
292 checkFindings(t, "function-docstring-args", `
293 def f():
294 def g(x, y):
295 """Short function with a docstring
296
297 Arguments:
298 x: smth
299 """
300 return x + y
301 return g
302 `,
303 []string{
304 `3: Argument "y" is not documented.`,
305 `5: Prefer "Args:" to "Arguments:" when documenting function arguments.`,
306 },
307 scopeEverywhere)
308
309 checkFindings(t, "function-docstring-args", `
310 def f():
311 def g(x, y):
312 """Short function with a docstring
313 """
314 return x + y
315 return g
316 `,
317 []string{},
318 scopeEverywhere)
319
320 checkFindings(t, "function-docstring-args", `
321 def _f(x, y):
322 """Long private function
323
324 Args:
325 x: something
326 z: something
327 """
328 x *= 2
329 x /= 3
330 x -= 4
331 x %= 5
332 return x
333 `,
334 []string{
335 `:2: Argument "y" is not documented.`,
336 `:6: Argument "z" is documented but doesn't exist in the function signature.`,
337 },
338 scopeEverywhere)
339
340 checkFindings(t, "function-docstring-args", `
341 def f(x, y):
342 """This is a function.
343
344 Arguments:
345 x: something
346 y: something (this is in fact the description of x continued)
347 z: something else
348
349 Returns:
350 None
351 """
352 pass
353 pass
354 pass
355 pass
356 pass
357 `,
358 []string{
359 `2: Argument "y" is not documented.`,
360 `4: Prefer "Args:" to "Arguments:" when documenting function arguments.`,
361 `7: Argument "z" is documented but doesn't exist in the function signature.`,
362 }, scopeEverywhere)
363
364 checkFindings(t, "function-docstring-args", `
365 def my_function(x, y, z = None, *args, **kwargs):
366 """This is a function.
367 """
368 pass
369 pass
370 pass
371 pass
372 pass
373 `,
374 []string{
375 `2: Arguments "x", "y", "z", "*args", "**kwargs" are not documented.
376
377 If the documentation for the arguments exists but is not recognized by Buildifier
378 make sure it follows the line "Args:" which has the same indentation as the opening """,
379 and the argument description starts with "<argument_name>:" and indented with at least
380 one (preferably two) space more than "Args:", for example:
381
382 def my_function(x):
383 """Function description.
384
385 Args:
386 x: argument description, can be
387 multiline with additional indentation.
388 """`,
389 },
390 scopeEverywhere)
391
392 checkFindings(t, "function-docstring-args", `
393 def f(x, y, z = None, *args, **kwargs):
394 """This is a function.
395
396 Args:
397 x (Map[string, int]): x
398 y (deprecated, mutable): y
399 z: z
400 *args (List<string>): the args
401 **kwargs: the kwargs
402 """
403 pass
404 pass
405 pass
406 pass
407 pass
408 `,
409 []string{},
410 scopeEverywhere)
411
412 checkFindings(t, "function-docstring-args", `
413 def f(x, *, y, z = None):
414 """This is a function.
415
416 Args:
417 x: x
418 y: y
419 z: z
420 """
421 pass
422 `,
423 []string{},
424 scopeEverywhere)
425
426 checkFindings(t, "function-docstring-args", `
427 def f(x, *, y, z = None):
428 """This is a function.
429
430 Args:
431 x: x
432 *: a separator
433 y: y
434 : argument without a name
435 z: z
436 """
437 pass
438 `,
439 []string{
440 `6: Argument "*" is documented but doesn't exist in the function signature.`,
441 `8: Argument "" is documented but doesn't exist in the function signature.`,
442 },
443 scopeEverywhere)
444
445 checkFindings(t, "function-docstring-args", `
446 def f(x):
447 """
448 This is a function.
449
450 Args:
451
452 The function signature is extremely complicated
453
454 x: something
455 Returns:
456 nothing
457 """
458 pass
459 pass
460 pass
461 pass
462 pass
463 return None
464 `,
465 []string{},
466 scopeEverywhere)
467
468 checkFindings(t, "function-docstring-args", `
469 def f(foobar, *bar, **baz):
470 """Some function
471
472 Args:
473 foobar: something
474 foo: something
475 bar: something
476 baz: something
477 """
478 pass
479 `,
480 []string{
481 `:2: Arguments "*bar", "**baz" are not documented.`,
482 `:6: Argument "foo" is documented but doesn't exist in the function signature.`,
483 `:7: Argument "bar" is documented but doesn't exist in the function signature. Do you mean "*bar"?`,
484 `:8: Argument "baz" is documented but doesn't exist in the function signature. Do you mean "**baz"?`,
485 },
486 scopeEverywhere)
487
488 checkFindings(t, "function-docstring-args", `
489 def f(x: int, y: str, z: bool = False, *, *bar: List[int], **baz: Mapping[str, bool]):
490 """Some function
491
492 Args:
493 x: something
494 t: something
495 """
496 pass
497 `,
498 []string{
499 `:2: Arguments "y", "z", "*bar", "**baz" are not documented.`,
500 `:6: Argument "t" is documented but doesn't exist in the function signature.`,
501 },
502 scopeEverywhere)
503 }
504
505 func TestFunctionDocstringReturn(t *testing.T) {
506 checkFindings(t, "function-docstring-return", `
507 def f(x):
508 """This is a function.
509
510 Args:
511 x: something
512
513 Returns:
514 something
515 """
516 pass
517 pass
518 pass
519 pass
520 pass
521 return x
522 `,
523 []string{},
524 scopeEverywhere)
525
526 checkFindings(t, "function-docstring-return", `
527 def f(x):
528 """This is a function.
529
530 Args:
531 x: something
532 """
533 pass
534 pass
535 pass
536 pass
537 pass
538 `,
539 []string{},
540 scopeEverywhere)
541
542 checkFindings(t, "function-docstring-return", `
543 def f(x):
544 """This is a function.
545
546 Args:
547 x: something
548 """
549 def g(y):
550 return y
551
552 pass
553 pass
554 pass
555 pass
556 pass
557 `,
558 []string{},
559 scopeEverywhere)
560
561 checkFindings(t, "function-docstring-return", `
562 def f(x):
563 """This is a function.
564
565 Args:
566 x: something
567 """
568 pass
569 pass
570 pass
571 pass
572 pass
573 return x
574 `,
575 []string{`2: Return value of "f" is not documented.`},
576 scopeEverywhere)
577
578 checkFindings(t, "function-docstring-return", `
579 def f():
580 def g(x):
581 """This is a function.
582
583 Args:
584 x: something
585 """
586 pass
587 pass
588 pass
589 pass
590 pass
591 return x
592 return g
593 `,
594 []string{},
595 scopeEverywhere)
596
597 checkFindings(t, "function-docstring-return", `
598 def f(x):
599 """This is a function.
600
601 Args:
602 x: something
603 """
604 pass
605 pass
606 pass
607 pass
608 pass
609 if foo:
610 return
611 else:
612 return x
613 `,
614 []string{`2: Return value of "f" is not documented.`},
615 scopeEverywhere)
616 }
617
View as plain text