diff --git a/pyrefly/lib/lsp/wasm/inlay_hints.rs b/pyrefly/lib/lsp/wasm/inlay_hints.rs index 03aae383c4..a35a9b0437 100644 --- a/pyrefly/lib/lsp/wasm/inlay_hints.rs +++ b/pyrefly/lib/lsp/wasm/inlay_hints.rs @@ -589,6 +589,7 @@ impl<'a> Transaction<'a> { && param_match.name.as_str() != "__self" && param_match.name.as_str() != "cls" && param_match.name.as_str() != "_cls" + && !matches!(arg, Expr::Name(name) if name.id == *param_match.name) { param_hints.push(( arg.range().start(), diff --git a/pyrefly/lib/test/lsp/inlay_hint.rs b/pyrefly/lib/test/lsp/inlay_hint.rs index a9f2133479..21e7644c53 100644 --- a/pyrefly/lib/test/lsp/inlay_hint.rs +++ b/pyrefly/lib/test/lsp/inlay_hint.rs @@ -608,6 +608,45 @@ test("a", "b") assert_eq!(parameter_name_hint_labels(code, true), vec!["a= ", "b= "]); } +#[test] +fn test_issue_5105_hide_hint_when_arg_matches_param_name() { + // A matching name is hidden while a different name still shows. + let code = r#" +def foo(a: int, b: int) -> None: + pass + +a = 1 +c = 2 +foo(a, c) +"#; + assert_eq!(parameter_name_hint_labels(code, true), vec!["b= "]); + + // Every argument matching leaves no hints. + let code = r#" +def foo(a: int, b: int) -> None: + pass + +a = 1 +b = 2 +foo(a, b) +"#; + assert_eq!(parameter_name_hint_labels(code, true), Vec::::new()); + + // obj.a against parameter a still shows a=, so only plain names are suppressed. + let code = r#" +class Box: + a: int = 1 + +def foo(a: int, b: int) -> None: + pass + +obj = Box() +c = 2 +foo(obj.a, c) +"#; + assert_eq!(parameter_name_hint_labels(code, true), vec!["a= ", "b= "]); +} + #[test] fn test_parameter_name_hints_with_varargs() { let code = r#"