1
16
17 package warn
18
19 import "testing"
20
21 func TestMissingReturnValueWarning(t *testing.T) {
22
23 checkFindings(t, "return-value", `
24 def foo():
25 if x:
26 return x
27 else:
28 return
29 `, []string{
30 `:5: Some but not all execution paths of "foo" return a value.`,
31 }, scopeEverywhere)
32
33
34 checkFindings(t, "return-value", `
35 def bar():
36 if x:
37 pass
38 elif y:
39 return y
40 else:
41 for z in t:
42 return
43 `, []string{
44 `:1: Some but not all execution paths of "bar" return a value.
45 The function may terminate by an implicit return in the end.`,
46 `:8: Some but not all execution paths of "bar" return a value.`,
47 }, scopeEverywhere)
48
49
50 checkFindings(t, "return-value", `
51 def foo():
52 if x:
53 return x
54 else:
55 bar()
56 `, []string{
57 `:1: Some but not all execution paths of "foo" return a value.
58 The function may terminate by an implicit return in the end.`,
59 }, scopeEverywhere)
60
61
62 checkFindings(t, "return-value", `
63 def bar():
64 if x:
65 return x
66 elif y:
67 return y
68 else:
69 foo
70 if z:
71 return z
72
73 if foo:
74 return not foo
75 `, []string{
76 `:1: Some but not all execution paths of "bar" return a value.
77 The function may terminate by an implicit return in the end.`,
78 }, scopeEverywhere)
79
80
81 checkFindings(t, "return-value", `
82 def bar():
83 if x:
84 return x
85 elif y:
86 return y
87 else:
88 foo
89 if z:
90 return z
91
92 if foo:
93 return not foo
94 else:
95 fail("unreachable")
96 `, []string{}, scopeEverywhere)
97
98
99 checkFindings(t, "return-value", `
100 def bar():
101 if x:
102 return x
103 elif y:
104 return y
105 else:
106 foo
107 if z:
108 return z
109
110 if foo:
111 return not foo
112 else:
113 foo() or fail("unreachable")
114 `, []string{
115 `:1: Some but not all execution paths of "bar" return a value.
116 The function may terminate by an implicit return in the end.`,
117 }, scopeEverywhere)
118
119
120 checkFindings(t, "return-value", `
121 def bar():
122 if x:
123 x()
124 elif y:
125 return
126 else:
127 foo
128 if z:
129 fail()
130
131 if foo:
132 return
133 `, []string{}, scopeEverywhere)
134
135
136 checkFindings(t, "return-value", `
137 def foobar():
138 pass
139 `, []string{}, scopeEverywhere)
140
141
142 checkFindings(t, "return-value", `
143 def foobar():
144 if foo:
145 fail()
146 `, []string{}, scopeEverywhere)
147
148
149 checkFindings(t, "return-value", `
150 def foo():
151 def bar():
152 pass
153
154 return bar
155 `, []string{}, scopeEverywhere)
156
157
158 checkFindings(t, "return-value", `
159 def foo():
160 def bar():
161 pass
162
163 if bar():
164 return 42
165 `, []string{
166 `:1: Some but not all execution paths of "foo" return a value.
167 The function may terminate by an implicit return in the end.`,
168 }, scopeEverywhere)
169
170
171 checkFindings(t, "return-value", `
172 def foo():
173 def bar():
174 if something:
175 return something
176
177 if bar():
178 return 42
179 return 43
180 `, []string{
181 `:2: Some but not all execution paths of "bar" return a value.
182 The function may terminate by an implicit return in the end.`,
183 }, scopeEverywhere)
184
185
186 checkFindings(t, "return-value", `
187 def foo():
188 def bar():
189 if something:
190 return something
191
192 if bar():
193 return 42
194 `, []string{
195 `:1: Some but not all execution paths of "foo" return a value.
196 The function may terminate by an implicit return in the end.`,
197 `:2: Some but not all execution paths of "bar" return a value.
198 The function may terminate by an implicit return in the end.`,
199 }, scopeEverywhere)
200 }
201
202 func TestUnreachableStatementWarning(t *testing.T) {
203
204 checkFindings(t, "unreachable", `
205 def foo():
206 return
207 bar()
208 baz()
209 `, []string{
210 `:3: The statement is unreachable.`,
211 }, scopeEverywhere)
212
213
214 checkFindings(t, "unreachable", `
215 def foo():
216 return 1
217 return 2
218 `, []string{
219 `:3: The statement is unreachable.`,
220 }, scopeEverywhere)
221
222
223 checkFindings(t, "unreachable", `
224 def foo():
225 fail("die")
226 bar()
227 baz()
228 `, []string{
229 `:3: The statement is unreachable.`,
230 }, scopeEverywhere)
231
232
233 checkFindings(t, "unreachable", `
234 def foo():
235 for x in y:
236 if x:
237 break
238 bar() # unreachable
239 if y:
240 continue
241 bar() # unreachable
242
243 def bar():
244 for x in y:
245 if x:
246 break
247 elif y:
248 continue
249 else:
250 return x
251
252 foo() # unreachable
253 foobar() # potentially reachable
254 `, []string{
255 `:5: The statement is unreachable.`,
256 `:8: The statement is unreachable.`,
257 `:19: The statement is unreachable.`,
258 }, scopeEverywhere)
259
260
261 checkFindings(t, "unreachable", `
262 def foo():
263 if x:
264 return
265 bar()
266 `, []string{}, scopeEverywhere)
267
268
269 checkFindings(t, "unreachable", `
270 def foo():
271 x() or fail("maybe")
272 bar()
273 `, []string{}, scopeEverywhere)
274
275
276 checkFindings(t, "unreachable", `
277 def foo():
278 def bar():
279 fail("die")
280 baz()
281 `, []string{
282 `:4: The statement is unreachable.`,
283 }, scopeEverywhere)
284
285 }
286
287 func TestNoEffect(t *testing.T) {
288 checkFindings(t, "no-effect", `
289 """Docstring."""
290 def bar():
291 """Other Docstring"""
292 fct()
293 pass
294 return 2
295
296 [f() for i in rang(3)] # top-level comprehension is okay
297 `,
298 []string{},
299 scopeEverywhere)
300
301 checkFindings(t, "no-effect", `
302 def foo():
303 [fct() for i in range(3)]
304 `,
305 []string{":2: Expression result is not used. Use a for-loop instead"},
306 scopeEverywhere)
307
308 checkFindings(t, "no-effect", `None`,
309 []string{":1: Expression result is not used."},
310 scopeEverywhere)
311
312 checkFindings(t, "no-effect", `
313 foo # 1
314 foo()
315
316 def bar():
317 [1, 2] # 5
318 if True:
319 "string" # 7
320 `,
321 []string{":1:", ":5:", ":7:"},
322 scopeEverywhere)
323
324 checkFindings(t, "no-effect", `
325 # A comment
326
327 """A docstring"""
328
329 # Another comment
330
331 """Not a docstring"""
332
333 def bar():
334 """A docstring"""
335 foo
336 """ Not a docstring"""
337 return foo
338 `,
339 []string{
340 ":7: Expression result is not used. Docstrings should be the first statements of a file or a function (they may follow comment lines).",
341 ":11: Expression result is not used.",
342 ":12: Expression result is not used. Docstrings should be the first statements of a file or a function (they may follow comment lines).",
343 }, scopeEverywhere)
344
345 checkFindings(t, "no-effect", `
346 foo == bar
347 foo = bar
348 a + b
349 c // d
350 -e
351 foo != bar
352
353 foo += bar
354 bar -= bar
355
356 `,
357 []string{":1:", ":3:", ":4:", ":5:", ":6:"},
358 scopeEverywhere)
359
360 checkFindings(t, "no-effect", `
361 def foo():
362 """Doc."""
363 def bar():
364 """Doc."""
365 foo == bar
366 `,
367 []string{":5:"},
368 scopeEverywhere)
369 }
370
371 func TestWarnUnusedVariable(t *testing.T) {
372 checkFindings(t, "unused-variable", `
373 load(":f.bzl", "x")
374 x = "unused"
375 y = "also unused"
376 z = "name"
377 t = "unused by design" # @unused
378 _foo, _bar = pair #@unused
379 cc_library(name = z)
380
381 def f():
382 pass
383
384 def g():
385 pass
386
387 g() + 3
388 `,
389 []string{":2: Variable \"x\" is unused.",
390 ":3: Variable \"y\" is unused.",
391 ":9: Function \"f\" is unused."},
392 scopeDeclarative)
393
394 checkFindings(t, "unused-variable", `
395 a = 1
396 b = 2
397 c = 3
398 d = (a if b else c) # only d is unused
399 `,
400 []string{":4: Variable \"d\" is unused."},
401 scopeDeclarative)
402
403 checkFindings(t, "unused-variable", `
404 _a = 1
405 _a += 2
406 _b = 3
407 print(_b)
408
409 def _f(): pass
410 def _g(): pass
411 _g()
412 `,
413 []string{
414 ":1: Variable \"_a\" is unused.",
415 ":6: Function \"_f\" is unused.",
416 },
417 scopeEverywhere)
418
419 checkFindings(t, "unused-variable", `
420 a = 1
421
422 def foo(
423 x,
424 y = 0,
425 z = 1):
426 b = 2
427 c = 3
428 d = (a if b else c) # only d is unused
429 e = 7
430 f = 8 # @unused
431 # @unused
432 g = 9
433
434 return e + z
435
436 foo()
437 `,
438 []string{
439 ":4: Variable \"x\" is unused.",
440 ":5: Variable \"y\" is unused.",
441 ":9: Variable \"d\" is unused.",
442 },
443 scopeEverywhere)
444
445 checkFindings(t, "unused-variable", `
446 a = 1
447
448 def foo(a):
449 b = 2
450 return a
451
452 def foo():
453 pass
454
455 def bar(c, cc):
456 d = 3
457 print(c)
458
459 def baz():
460 foo()
461 d = 4
462 return a
463
464 bar()
465 `,
466 []string{
467 ":4: Variable \"b\" is unused.",
468 ":10: Variable \"cc\" is unused.",
469 ":11: Variable \"d\" is unused.",
470 ":14: Function \"baz\" is unused.",
471 ":16: Variable \"d\" is unused.",
472 },
473 scopeEverywhere)
474
475 checkFindings(t, "unused-variable", `
476 def foo():
477 a = 1
478 b = 2
479 c = 3
480
481 def bar(
482 x = a + baz(c = 4),
483 y = b):
484 pass
485
486 foo()
487 `,
488 []string{
489 ":4: Variable \"c\" is unused.",
490 ":6: Function \"bar\" is unused.",
491 ":7: Variable \"x\" is unused.",
492 ":8: Variable \"y\" is unused.",
493 },
494 scopeEverywhere)
495
496 checkFindings(t, "unused-variable", `
497 def foo():
498 a = 1
499 b = 2
500 c = [x for a in aa if a % b for x in a]
501 return c
502
503 foo()
504 `,
505 []string{
506 ":2: Variable \"a\" is unused.",
507 },
508 scopeEverywhere)
509
510 checkFindings(t, "unused-variable", `
511 def foo():
512 a = 1
513 b = 2
514 c = [
515 a + b
516 for a in [b for b in bb if b]
517 if a
518 ]
519 return c
520
521 foo()
522 `,
523 []string{
524 ":2: Variable \"a\" is unused.",
525 },
526 scopeEverywhere)
527
528 checkFindings(t, "unused-variable", `
529 def foo():
530 a = 1
531 b = 2
532
533 def bar(*args):
534 def baz(**kwargs):
535 def foobar(*a,
536 **kw):
537 return b
538 return foobar(**kwargs)
539 return baz(*args)
540 return bar()
541
542 foo()
543 `,
544 []string{
545 ":2: Variable \"a\" is unused.",
546 ":7: Variable \"a\" is unused.",
547 ":8: Variable \"kw\" is unused.",
548 },
549 scopeEverywhere)
550
551 checkFindings(t, "unused-variable", `
552 def foo():
553 a = 1
554 b = 2
555 c = 3
556 d = 4
557 e, f = 5, 6
558
559 for x, yy in xx:
560 for (y, z, _, _t) in yy:
561 print(a + y)
562
563 if bar:
564 print(c)
565 elif baz:
566 print(d)
567 else:
568 print(e)
569
570 foo()
571 `,
572 []string{
573 ":3: Variable \"b\" is unused.",
574 ":6: Variable \"f\" is unused.",
575 ":8: Variable \"x\" is unused.",
576 ":9: Variable \"z\" is unused.",
577 },
578 scopeEverywhere)
579
580 checkFindings(t, "unused-variable", `
581 def foo():
582
583 # @unused
584 def bar():
585 pass
586
587 def baz():
588 pass
589
590 foo()
591 `,
592 []string{
593 ":7: Function \"baz\" is unused.",
594 },
595 scopeEverywhere)
596
597 checkFindings(t, "unused-variable", `
598 def foo(my_iterable, arg, _some_unused_argument, _also_unused = None, *_args, **_kwargs):
599
600 a, b, _c = 1, 2, 3 # ok to not use _c
601 print(a)
602
603 _d, _e = 4, 5 # all are underscored
604 print(_d)
605
606 for f, g, _h, _ in my_iterable: # ok to not use any underscored
607 print(f)
608
609 for _i, (_j, _k) in another_iterable: # ok to not use any of them
610 pass
611
612 [1 for (_y, _z) in bar]
613
614 foo()
615 `,
616 []string{
617 ":1: Variable \"arg\" is unused.",
618 ":3: Variable \"b\" is unused.",
619 ":6: Variable \"_e\" is unused.",
620 ":9: Variable \"g\" is unused.",
621 },
622 scopeEverywhere)
623
624 checkFindings(t, "unused-variable", `
625 def foo(
626 x,
627 _y,
628 z, # @unused
629 t = 42, #@unused
630 *args, # @unused
631 **kwargs, ### also @unused
632 ):
633 pass
634
635 foo()
636 `,
637 []string{
638 ":2: Variable \"x\" is unused.",
639 },
640 scopeEverywhere)
641
642 checkFindings(t, "unused-variable", `
643 def foo(
644 name,
645 x):
646 pass
647
648
649 def bar(
650 name = "",
651 y = 3):
652 pass
653
654
655 foo()
656 bar()
657 `,
658 []string{
659 ":3: Variable \"x\" is unused.",
660 ":9: Variable \"y\" is unused.",
661 },
662 scopeEverywhere)
663 }
664
665 func TestRedefinedVariable(t *testing.T) {
666 checkFindings(t, "redefined-variable", `
667 x = "old_value"
668 x = "new_value"
669 x[1] = "new"
670 cc_library(name = x)`,
671 []string{":2: Variable \"x\" has already been defined."},
672 scopeEverywhere)
673
674 checkFindings(t, "redefined-variable", `
675 x = "a"
676
677 def foo():
678 x = "b"
679 y = "c"
680 y = "d"
681
682 def bar():
683 x = "e"
684 y = "f"
685 y = "g"`,
686 []string{},
687 scopeEverywhere)
688
689 checkFindings(t, "redefined-variable", `
690 x = [1, 2, 3]
691 y = [a for a in b]
692 z = list()
693 n = 43
694
695 x += something()
696 y += something()
697 z += something()
698 n += something()
699 x -= something()`,
700 []string{
701 ":9: Variable \"n\" has already been defined.",
702 ":10: Variable \"x\" has already been defined.",
703 },
704 scopeEverywhere)
705
706 checkFindings(t, "redefined-variable", `
707 x = [1, 2, 3]
708 y = [a for a in b]
709 z = list()
710
711 a = something()
712 b = something()
713 c = something()
714 d = something()
715 e = something()
716
717 a += x
718 b += y
719 c += z
720 d += [42]
721 e += foo`,
722 []string{
723 ":15: Variable \"e\" has already been defined.",
724 },
725 scopeEverywhere)
726 }
727
728 func TestWarnUnusedLoad(t *testing.T) {
729 checkFindingsAndFix(t, "load", `
730 load(":f.bzl", "s1", "s2")
731 load(":bar.bzl", "s1")
732 foo(name = s1)`, `
733 load(":f.bzl", "s1")
734 load(":bar.bzl", "s1")
735 foo(name = s1)`,
736 []string{
737 ":1: Loaded symbol \"s2\" is unused.",
738 ":2: A different symbol \"s1\" has already been loaded on line 1.",
739 },
740 scopeEverywhere)
741
742 checkFindingsAndFix(t, "load", `
743 load("foo", "b", "a", "c")
744 load("foo", "a", "d", "e")
745
746 z = a + b + d`, `
747 load("foo", "a", "b")
748 load("foo", "d")
749
750 z = a + b + d`,
751 []string{
752 ":1: Loaded symbol \"c\" is unused.",
753 ":2: Symbol \"a\" has already been loaded on line 1.",
754 ":2: Loaded symbol \"e\" is unused.",
755 },
756 scopeEverywhere)
757
758 checkFindingsAndFix(t, "load", `
759 load("foo", "a")
760 a(1)
761 load("bar", "a")
762 a(2)
763 load("bar", a = "a")
764 a(3)
765 load("bar", a = "b")
766 a(4)
767 load("foo", "a")
768 a(5)
769 load("foo", "a")
770 a(6)
771 load("foo", a = "a")
772 a(7)`, `
773 load("foo", "a")
774 a(1)
775 load("bar", "a")
776 a(2)
777
778 a(3)
779 load("bar", a = "b")
780 a(4)
781 load("foo", "a")
782 a(5)
783
784 a(6)
785
786 a(7)`,
787 []string{
788 ":3: A different symbol \"a\" has already been loaded on line 1.",
789 ":5: Symbol \"a\" has already been loaded on line 3.",
790 ":7: A different symbol \"a\" has already been loaded on line 5.",
791 ":9: A different symbol \"a\" has already been loaded on line 7.",
792 ":11: Symbol \"a\" has already been loaded on line 9.",
793 ":13: Symbol \"a\" has already been loaded on line 11.",
794 },
795 scopeEverywhere)
796
797 checkFindingsAndFix(t, "load", `
798 load(
799 ":f.bzl",
800 "s1",
801 "s2", # @unused (s2)
802 )
803
804 # @unused - both s3 and s4
805 load(
806 ":f.bzl",
807 "s3",
808 "s4",
809 )`, `
810 load(
811 ":f.bzl",
812 "s2", # @unused (s2)
813 )
814
815 # @unused - both s3 and s4
816 load(
817 ":f.bzl",
818 "s3",
819 "s4",
820 )`,
821 []string{":3: Loaded symbol \"s1\" is unused."},
822 scopeEverywhere)
823
824 checkFindingsAndFix(t, "load", `
825 load(":f.bzl", "x")
826 x = "unused"`, `
827 x = "unused"`,
828 []string{":1: Loaded symbol \"x\" is unused."},
829 scopeEverywhere)
830
831 checkFindings(t, "load", `
832 load(
833 ":f.bzl",
834 "s1",
835 )
836
837 def test(x: s1):
838 pass
839 `,
840 []string{},
841 scopeEverywhere)
842 checkFindings(t, "load", `
843 load(
844 ":f.bzl",
845 "s1",
846 "s2",
847 )
848
849 def test(x: s1) -> List[s2]:
850 pass
851 `,
852 []string{},
853 scopeEverywhere)
854 checkFindingsAndFix(t, "load", `
855 load(
856 ":f.bzl",
857 "s1",
858 "s2",
859 )
860
861 load(
862 ":s.bzl",
863 "s3",
864 )
865
866 def test(x: s1) -> List[s2]:
867 pass
868 `, `
869 load(
870 ":f.bzl",
871 "s1",
872 "s2",
873 )
874
875 def test(x: s1) -> List[s2]:
876 pass
877 `,
878 []string{
879 ":9: Loaded symbol \"s3\" is unused.",
880 },
881 scopeEverywhere)
882 }
883
884 func TestUninitializedVariable(t *testing.T) {
885 checkFindings(t, "uninitialized", `
886 def foo(x):
887 if bar:
888 x = 1
889 y = 2
890
891 bar = True
892 print(x + y)
893 `,
894 []string{
895 ":2: Variable \"bar\" may not have been initialized.",
896 ":7: Variable \"y\" may not have been initialized.",
897 },
898 scopeEverywhere)
899
900 checkFindings(t, "uninitialized", `
901 def foo(x):
902 for t in s:
903 x = 1
904 y = 2
905
906 print(x + y)
907 `,
908 []string{
909 ":6: Variable \"y\" may not have been initialized.",
910 },
911 scopeEverywhere)
912
913 checkFindings(t, "uninitialized", `
914 def foo():
915 if bar:
916 x = 1
917 y = 2
918 else:
919 if foobar:
920 x = 3
921 y = 4
922 else:
923 x = 5
924
925 print(x + y)
926 `,
927 []string{
928 ":12: Variable \"y\" may not have been initialized.",
929 },
930 scopeEverywhere)
931
932 checkFindings(t, "uninitialized", `
933 def foo(x):
934 if bar:
935 t = 1
936 else:
937 for t in maybe_empty:
938 pass
939
940 print(t)
941 `,
942 []string{
943 ":8: Variable \"t\" may not have been initialized.",
944 },
945 scopeEverywhere)
946
947 checkFindings(t, "uninitialized", `
948 def foo(x):
949 if bar:
950 t = 1
951 else:
952 for y in maybe_empty:
953 return
954
955 print(t)
956 `,
957 []string{
958 ":8: Variable \"t\" may not have been initialized.",
959 },
960 scopeEverywhere)
961
962 checkFindings(t, "uninitialized", `
963 def foo(x):
964 if bar:
965 for t in [2, 3]:
966 pass
967
968 print(t)
969 `,
970 []string{
971 ":6: Variable \"t\" may not have been initialized.",
972 },
973 scopeEverywhere)
974
975 checkFindings(t, "uninitialized", `
976 def foo(x):
977 print(t) # maybe global or loaded
978 `,
979 []string{},
980 scopeEverywhere)
981
982 checkFindings(t, "uninitialized", `
983 def foo(x):
984 if bar:
985 y = 1
986
987 print(y)
988 x, y = y, x
989 print(y)
990 `,
991 []string{
992 ":5: Variable \"y\" may not have been initialized.",
993 ":6: Variable \"y\" may not have been initialized.",
994 },
995 scopeEverywhere)
996
997 checkFindings(t, "uninitialized", `
998 def foo():
999 if a:
1000 x = 1
1001 y = 1
1002 z = 1
1003 elif b:
1004 x = 2
1005 z = 2
1006 t = 2
1007 else:
1008 x = 3
1009 y = 3
1010 t = 3
1011
1012 print(x + y + z + t)
1013 `,
1014 []string{
1015 ":15: Variable \"y\" may not have been initialized.",
1016 ":15: Variable \"z\" may not have been initialized.",
1017 ":15: Variable \"t\" may not have been initialized.",
1018 },
1019 scopeEverywhere)
1020
1021 checkFindings(t, "uninitialized", `
1022 def foo(y):
1023 if y < 0:
1024 x = -1
1025 elif y > 0:
1026 x = 1
1027 else:
1028 fail()
1029
1030 print(x)
1031 `,
1032 []string{},
1033 scopeEverywhere)
1034
1035 checkFindings(t, "uninitialized", `
1036 def foo(y):
1037 if y < 0:
1038 x = -1
1039 elif y > 0:
1040 x = 1
1041 else:
1042 if z:
1043 fail("z")
1044 else:
1045 fail("not z")
1046
1047 print(x)
1048 `,
1049 []string{},
1050 scopeEverywhere)
1051
1052 checkFindings(t, "uninitialized", `
1053 def foo(y):
1054 if y < 0:
1055 return
1056 elif y > 0:
1057 x = 1
1058 else:
1059 return x # not initialized
1060
1061 print(x)
1062 `,
1063 []string{
1064 ":7: Variable \"x\" may not have been initialized.",
1065 },
1066 scopeEverywhere)
1067
1068 checkFindings(t, "uninitialized", `
1069 def foo(y):
1070 if y < 0:
1071 return
1072 elif y > 0:
1073 x = 1
1074 else:
1075 pass
1076
1077 print(x) # not initialized
1078 `,
1079 []string{
1080 ":9: Variable \"x\" may not have been initialized.",
1081 },
1082 scopeEverywhere)
1083
1084 checkFindings(t, "uninitialized", `
1085 def foo():
1086 for x in y:
1087 print(x)
1088 print(x.attr)
1089
1090 print(x)
1091 print(x.attr)
1092 `,
1093 []string{
1094 ":6: Variable \"x\" may not have been initialized.",
1095 ":7: Variable \"x\" may not have been initialized.",
1096 },
1097 scopeEverywhere)
1098
1099 checkFindings(t, "uninitialized", `
1100 def foo():
1101 for x in y:
1102 a = x
1103 print(a)
1104
1105 print(a)
1106 `,
1107 []string{
1108 ":6: Variable \"a\" may not have been initialized.",
1109 },
1110 scopeEverywhere)
1111
1112 checkFindings(t, "uninitialized", `
1113 def f():
1114 if foo:
1115 x = foo
1116
1117 f(x = y)
1118 `,
1119 []string{},
1120 scopeEverywhere)
1121
1122 checkFindings(t, "uninitialized", `
1123 def f():
1124 if foo:
1125 x = foo
1126
1127 f(x + y)
1128 `,
1129 []string{
1130 ":5: Variable \"x\" may not have been initialized.",
1131 },
1132 scopeEverywhere)
1133
1134 checkFindings(t, "uninitialized", `
1135 def f():
1136 if foo:
1137 x = foo
1138
1139 x, y = 1, x
1140 `,
1141 []string{
1142 ":5: Variable \"x\" may not have been initialized.",
1143 },
1144 scopeEverywhere)
1145
1146 checkFindings(t, "uninitialized", `
1147 def f():
1148 if foo:
1149 x = foo
1150
1151 x, y = 1, 2
1152 `,
1153 []string{},
1154 scopeEverywhere)
1155
1156 checkFindings(t, "uninitialized", `
1157 def f(y):
1158 return [x for x in y if x]
1159
1160 x = 1
1161 `,
1162 []string{},
1163 scopeEverywhere)
1164
1165 checkFindings(t, "uninitialized", `
1166 def f():
1167 if foo:
1168 f(x = foo)
1169 else:
1170 x = 3
1171
1172 print(x)
1173 `,
1174 []string{
1175 ":7: Variable \"x\" may not have been initialized.",
1176 },
1177 scopeEverywhere)
1178
1179 checkFindings(t, "uninitialized", `
1180 def foo(x):
1181 for y in x:
1182 if foo:
1183 break
1184 elif bar:
1185 continue
1186 elif baz:
1187 return
1188 else:
1189 z = 3
1190 print(z)
1191 `,
1192 []string{},
1193 scopeEverywhere)
1194
1195 checkFindings(t, "uninitialized", `
1196 def foo(x: int, y: int = 2):
1197 if bar:
1198 x = 1
1199 y = 2
1200 z = 3
1201
1202 print(x + y + z)
1203 `,
1204 []string{
1205 ":7: Variable \"z\" may not have been initialized.",
1206 },
1207 scopeEverywhere)
1208
1209 checkFindings(t, "uninitialized", `
1210 def foo(x: int, y: int = 2):
1211 def bar(y=x):
1212 if baz:
1213 x = 1
1214 y = 2
1215 z = 3
1216
1217 print(x + y + z)
1218
1219 if something:
1220 x = bar()
1221
1222 return x
1223 `,
1224 []string{
1225 ":8: Variable \"x\" may not have been initialized.",
1226 ":8: Variable \"z\" may not have been initialized.",
1227 },
1228 scopeEverywhere)
1229
1230 checkFindings(t, "uninitialized", `
1231 def foo(x: int, y: int = 2):
1232 if bar:
1233 y, z, t = 2, 3, 4
1234 w, s = 5, 6
1235 r = 7
1236
1237 [t for t in range(5)]
1238 [a for a in range(z + y)]
1239 {b: c + s for b, c in [
1240 d * 2 for d in range(t)
1241 if d != baz(r=w)
1242 ]}
1243 `,
1244 []string{
1245 ":8: Variable \"z\" may not have been initialized.",
1246 ":9: Variable \"s\" may not have been initialized.",
1247 ":10: Variable \"t\" may not have been initialized.",
1248 ":11: Variable \"w\" may not have been initialized.",
1249 },
1250 scopeEverywhere)
1251
1252 checkFindings(t, "uninitialized", `
1253 def foo():
1254 x = 1
1255 for y, z in t:
1256 print(y, z)
1257
1258 def bar(x, y, s = z):
1259 pass
1260 `,
1261 []string{
1262 ":6: Variable \"z\" may not have been initialized.",
1263 },
1264 scopeEverywhere)
1265
1266 checkFindings(t, "uninitialized", `
1267 def foo():
1268 for bar in baz:
1269 pass
1270
1271 y = [baz.get(bar) for bar in bars]
1272 x = lambda bar: baz.get(bar)
1273 `,
1274 []string{},
1275 scopeEverywhere)
1276
1277 checkFindings(t, "uninitialized", `
1278 def foo():
1279 def bar(x):
1280 print(x)
1281
1282 for x, y in z:
1283 bar(x)
1284 `,
1285 []string{},
1286 scopeEverywhere)
1287
1288 checkFindings(t, "uninitialized", `
1289 def foo():
1290 [x, y] = [1, 2]
1291 x = 3
1292 print(x)
1293 `,
1294 []string{},
1295 scopeEverywhere)
1296 }
1297
View as plain text