Fix Cmd+click navigating to file instead of definition (#49012)

Wuji Chen and Claude Opus 4.6 created

## Summary

- Tighten `link_pattern_file_candidates` regex from `\(([^)]*)\)` to
`]\(([^)]*)\)` so only Markdown link syntax `[title](path)` triggers
path extraction from parentheses
- Prevents function call arguments like `do_work(file2)` from being
incorrectly resolved as file paths, which preempted LSP go-to-definition

Closes #48938

## Test plan

- [x] `cargo test -p editor hover_links` — all 12 tests pass
- [x] New unit tests verify: function calls don't extract arguments as
file candidates; Markdown links still extract correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Release Notes:

- Fixed Cmd+click navigating to file instead of definition in certain
cases

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Change summary

crates/editor/src/hover_links.rs | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)

Detailed changes

crates/editor/src/hover_links.rs 🔗

@@ -673,7 +673,7 @@ pub(crate) async fn find_file(
 // (literally, [LinkTitle](link_file.txt)) as a candidate.
 fn link_pattern_file_candidates(candidate: &str) -> Vec<(String, Range<usize>)> {
     static MD_LINK_REGEX: LazyLock<Regex> =
-        LazyLock::new(|| Regex::new(r"\(([^)]*)\)").expect("Failed to create REGEX"));
+        LazyLock::new(|| Regex::new(r"]\(([^)]*)\)").expect("Failed to create REGEX"));
 
     let candidate_len = candidate.len();
 
@@ -1444,14 +1444,26 @@ mod tests {
             candidates,
             vec!["LinkTitle](link\\ _file.txt)", "link\\ _file.txt",]
         );
-        //
-        // Square brackets not strictly necessary
+        // Parentheses without preceding `]` should not extract inner content,
+        // to avoid matching function calls like `do_work(file2)` as file paths.
         let candidates: Vec<String> = link_pattern_file_candidates("(link_file.txt)")
             .into_iter()
             .map(|(c, _)| c)
             .collect();
+        assert_eq!(candidates, vec!["(link_file.txt)"]);
 
-        assert_eq!(candidates, vec!["(link_file.txt)", "link_file.txt",]);
+        let candidates: Vec<String> = link_pattern_file_candidates("do_work(file2);")
+            .into_iter()
+            .map(|(c, _)| c)
+            .collect();
+        assert_eq!(candidates, vec!["do_work(file2);"]);
+
+        // Markdown links should still extract the path
+        let candidates: Vec<String> = link_pattern_file_candidates("](readme.md)")
+            .into_iter()
+            .map(|(c, _)| c)
+            .collect();
+        assert_eq!(candidates, vec!["](readme.md)", "readme.md"]);
 
         // No nesting
         let candidates: Vec<String> =