@@ -99,6 +99,299 @@ mod tests {
9999 " )
100100 }
101101
102+ #[ test]
103+ fn add_ignore_existing_comment ( ) {
104+ let test = CodeActionTest :: with_source ( r#"b = <START>a<END> / 10 # fmt: off"# ) ;
105+
106+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
107+ info[code-action]: Ignore 'unresolved-reference' for this line
108+ --> main.py:1:5
109+ |
110+ 1 | b = a / 10 # fmt: off
111+ | ^
112+ |
113+ - b = a / 10 # fmt: off
114+ 1 + b = a / 10 # fmt: off # ty:ignore[unresolved-reference]
115+ " )
116+ }
117+
118+ #[ test]
119+ fn add_ignore_trailing_whitespace ( ) {
120+ let test = CodeActionTest :: with_source ( r#"b = <START>a<END> / 10 "# ) ;
121+
122+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
123+ info[code-action]: Ignore 'unresolved-reference' for this line
124+ --> main.py:1:5
125+ |
126+ 1 | b = a / 10
127+ | ^
128+ |
129+ - b = a / 10
130+ 1 + b = a / 10 # ty:ignore[unresolved-reference]
131+ " )
132+ }
133+
134+ #[ test]
135+ fn add_code_existing_ignore ( ) {
136+ let test = CodeActionTest :: with_source (
137+ r#"
138+ b = <START>a<END> / 0 # ty:ignore[division-by-zero]
139+ "# ,
140+ ) ;
141+
142+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
143+ info[code-action]: Ignore 'unresolved-reference' for this line
144+ --> main.py:2:17
145+ |
146+ 2 | b = a / 0 # ty:ignore[division-by-zero]
147+ | ^
148+ |
149+ 1 |
150+ - b = a / 0 # ty:ignore[division-by-zero]
151+ 2 + b = a / 0 # ty:ignore[division-by-zero, unresolved-reference]
152+ 3 |
153+ " )
154+ }
155+
156+ #[ test]
157+ fn add_code_existing_ignore_with_reason ( ) {
158+ let test = CodeActionTest :: with_source (
159+ r#"
160+ b = <START>a<END> / 0 # ty:ignore[division-by-zero] some explanation
161+ "# ,
162+ ) ;
163+
164+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
165+ info[code-action]: Ignore 'unresolved-reference' for this line
166+ --> main.py:2:17
167+ |
168+ 2 | b = a / 0 # ty:ignore[division-by-zero] some explanation
169+ | ^
170+ |
171+ 1 |
172+ - b = a / 0 # ty:ignore[division-by-zero] some explanation
173+ 2 + b = a / 0 # ty:ignore[division-by-zero] some explanation # ty:ignore[unresolved-reference]
174+ 3 |
175+ " )
176+ }
177+
178+ #[ test]
179+ fn add_code_existing_ignore_start_line ( ) {
180+ let test = CodeActionTest :: with_source (
181+ r#"
182+ b = (
183+ <START>a # ty:ignore[division-by-zero]
184+ /
185+ 0<END>
186+ )
187+ "# ,
188+ ) ;
189+
190+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
191+ info[code-action]: Ignore 'unresolved-reference' for this line
192+ --> main.py:3:21
193+ |
194+ 2 | b = (
195+ 3 | / a # ty:ignore[division-by-zero]
196+ 4 | | /
197+ 5 | | 0
198+ | |_____________________^
199+ 6 | )
200+ |
201+ 1 |
202+ 2 | b = (
203+ - a # ty:ignore[division-by-zero]
204+ 3 + a # ty:ignore[division-by-zero, unresolved-reference]
205+ 4 | /
206+ 5 | 0
207+ 6 | )
208+ " )
209+ }
210+
211+ #[ test]
212+ fn add_code_existing_ignore_end_line ( ) {
213+ let test = CodeActionTest :: with_source (
214+ r#"
215+ b = (
216+ <START>a
217+ /
218+ 0<END> # ty:ignore[division-by-zero]
219+ )
220+ "# ,
221+ ) ;
222+
223+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
224+ info[code-action]: Ignore 'unresolved-reference' for this line
225+ --> main.py:3:21
226+ |
227+ 2 | b = (
228+ 3 | / a
229+ 4 | | /
230+ 5 | | 0 # ty:ignore[division-by-zero]
231+ | |_____________________^
232+ 6 | )
233+ |
234+ 2 | b = (
235+ 3 | a
236+ 4 | /
237+ - 0 # ty:ignore[division-by-zero]
238+ 5 + 0 # ty:ignore[division-by-zero, unresolved-reference]
239+ 6 | )
240+ 7 |
241+ " )
242+ }
243+
244+ #[ test]
245+ fn add_code_existing_ignores ( ) {
246+ let test = CodeActionTest :: with_source (
247+ r#"
248+ b = (
249+ <START>a # ty:ignore[division-by-zero]
250+ /
251+ 0<END> # ty:ignore[division-by-zero]
252+ )
253+ "# ,
254+ ) ;
255+
256+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r"
257+ info[code-action]: Ignore 'unresolved-reference' for this line
258+ --> main.py:3:21
259+ |
260+ 2 | b = (
261+ 3 | / a # ty:ignore[division-by-zero]
262+ 4 | | /
263+ 5 | | 0 # ty:ignore[division-by-zero]
264+ | |_____________________^
265+ 6 | )
266+ |
267+ 1 |
268+ 2 | b = (
269+ - a # ty:ignore[division-by-zero]
270+ 3 + a # ty:ignore[division-by-zero, unresolved-reference]
271+ 4 | /
272+ 5 | 0 # ty:ignore[division-by-zero]
273+ 6 | )
274+ " )
275+ }
276+
277+ #[ test]
278+ fn add_code_interpolated_string ( ) {
279+ let test = CodeActionTest :: with_source (
280+ r#"
281+ b = f"""
282+ {<START>a<END>}
283+ more text
284+ """
285+ "# ,
286+ ) ;
287+
288+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r#"
289+ info[code-action]: Ignore 'unresolved-reference' for this line
290+ --> main.py:3:18
291+ |
292+ 2 | b = f"""
293+ 3 | {a}
294+ | ^
295+ 4 | more text
296+ 5 | """
297+ |
298+ 2 | b = f"""
299+ 3 | {a}
300+ 4 | more text
301+ - """
302+ 5 + """ # ty:ignore[unresolved-reference]
303+ 6 |
304+ "# )
305+ }
306+
307+ #[ test]
308+ fn add_code_multiline_interpolation ( ) {
309+ let test = CodeActionTest :: with_source (
310+ r#"
311+ b = f"""
312+ {
313+ <START>a<END>
314+ }
315+ more text
316+ """
317+ "# ,
318+ ) ;
319+
320+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r#"
321+ info[code-action]: Ignore 'unresolved-reference' for this line
322+ --> main.py:4:17
323+ |
324+ 2 | b = f"""
325+ 3 | {
326+ 4 | a
327+ | ^
328+ 5 | }
329+ 6 | more text
330+ |
331+ 1 |
332+ 2 | b = f"""
333+ 3 | {
334+ - a
335+ 4 + a # ty:ignore[unresolved-reference]
336+ 5 | }
337+ 6 | more text
338+ 7 | """
339+ "# )
340+ }
341+
342+ #[ test]
343+ fn add_code_followed_by_multiline_string ( ) {
344+ let test = CodeActionTest :: with_source (
345+ r#"
346+ b = <START>a<END> + """
347+ more text
348+ """
349+ "# ,
350+ ) ;
351+
352+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r#"
353+ info[code-action]: Ignore 'unresolved-reference' for this line
354+ --> main.py:2:17
355+ |
356+ 2 | b = a + """
357+ | ^
358+ 3 | more text
359+ 4 | """
360+ |
361+ 1 |
362+ 2 | b = a + """
363+ 3 | more text
364+ - """
365+ 4 + """ # ty:ignore[unresolved-reference]
366+ 5 |
367+ "# )
368+ }
369+
370+ #[ test]
371+ fn add_code_followed_by_continuation ( ) {
372+ let test = CodeActionTest :: with_source (
373+ r#"
374+ b = <START>a<END> \
375+ + "test"
376+ "# ,
377+ ) ;
378+
379+ assert_snapshot ! ( test. code_actions( & UNRESOLVED_REFERENCE ) , @r#"
380+ info[code-action]: Ignore 'unresolved-reference' for this line
381+ --> main.py:2:17
382+ |
383+ 2 | b = a \
384+ | ^
385+ 3 | + "test"
386+ |
387+ 1 |
388+ 2 | b = a \
389+ - + "test"
390+ 3 + + "test" # ty:ignore[unresolved-reference]
391+ 4 |
392+ "# )
393+ }
394+
102395 pub ( super ) struct CodeActionTest {
103396 pub ( super ) db : ty_project:: TestDb ,
104397 pub ( super ) file : File ,
0 commit comments