@@ -284,6 +284,80 @@ def test_check_for_subdir_mention(self):
284284 coder .check_for_file_mentions (f"Please check `{ fname } `" )
285285
286286 self .assertEqual (coder .abs_fnames , set ([str (fname .resolve ())]))
287+
288+ def test_get_file_mentions_various_formats (self ):
289+ with GitTemporaryDirectory ():
290+ io = InputOutput (pretty = False , yes = True )
291+ coder = Coder .create (self .GPT35 , None , io )
292+
293+ # Create test files
294+ test_files = [
295+ "file1.txt" ,
296+ "file2.py" ,
297+ "dir/nested_file.js" ,
298+ "dir/subdir/deep_file.html" ,
299+ "file with spaces.txt" ,
300+ "special_chars!@#.md" ,
301+ ]
302+
303+ for fname in test_files :
304+ fpath = Path (fname )
305+ fpath .parent .mkdir (parents = True , exist_ok = True )
306+ fpath .touch ()
307+
308+ # Mock get_addable_relative_files to return our test files
309+ coder .get_addable_relative_files = MagicMock (return_value = set (test_files ))
310+
311+ # Test different mention formats
312+ test_cases = [
313+ # Simple plain text mentions
314+ (f"You should edit { test_files [0 ]} first" , {test_files [0 ]}),
315+
316+ # Multiple files in plain text
317+ (f"Edit both { test_files [0 ]} and { test_files [1 ]} " , {test_files [0 ], test_files [1 ]}),
318+
319+ # Files in backticks
320+ (f"Check the file `{ test_files [2 ]} `" , {test_files [2 ]}),
321+
322+ # Files in code blocks
323+ (f"```\n { test_files [3 ]} \n ```" , {test_files [3 ]}),
324+
325+ # Files in code blocks with language specifier
326+ (f"```python\n with open('{ test_files [1 ]} ', 'r') as f:\n data = f.read()\n ```" , {test_files [1 ]}),
327+
328+ # Files with Windows-style paths
329+ (f"Edit the file { test_files [2 ].replace ('/' , '\\ ' )} " , {test_files [2 ]}),
330+
331+ # Files with spaces
332+ (f"Look at '{ test_files [4 ]} '" , {test_files [4 ]}),
333+
334+ # Files with different quote styles
335+ (f'Check "{ test_files [5 ]} " now' , {test_files [5 ]}),
336+
337+ # Files mentioned in markdown links
338+ (f"See the file [{ test_files [0 ]} ]({ test_files [0 ]} )" , {test_files [0 ]}),
339+
340+ # All files in one complex message
341+ (
342+ f"First, edit `{ test_files [0 ]} `. Then modify { test_files [1 ]} .\n "
343+ f"```js\n // Update this file\n const file = '{ test_files [2 ]} ';\n ```\n "
344+ f"Finally check { test_files [3 ].replace ('/' , '\\ ' )} " ,
345+ {test_files [0 ], test_files [1 ], test_files [2 ], test_files [3 ]}
346+ ),
347+
348+ # Mention with SEARCH/REPLACE format
349+ (
350+ f"{ test_files [1 ]} \n ````python\n <<<<<<< SEARCH\n def old_function():\n pass\n =======\n "
351+ f"def new_function():\n return True\n >>>>>>> REPLACE\n ````" ,
352+ {test_files [1 ]}
353+ ),
354+ ]
355+
356+ for content , expected_mentions in test_cases :
357+ with self .subTest (content = content ):
358+ mentioned_files = coder .get_file_mentions (content )
359+ self .assertEqual (mentioned_files , expected_mentions ,
360+ f"Failed to extract mentions from: { content } " )
287361
288362 def test_get_file_mentions_path_formats (self ):
289363 with GitTemporaryDirectory ():
0 commit comments