fix(lsp): discover all tests when names are duplicated (#34624)
## Summary
The LSP test collector hashes each test's id from `name + parent_chain +
specifier`. When a file contains two tests with the same name (e.g. two
`Deno.test(function foo() {})` calls), they hashed to the same id and
the second one was silently dropped, leaving it invisible in the test
explorer.
Example from the original report:
```js
Deno.test(function addTest() { assertEquals(add(2, 3), 5); });
Deno.test(function foo() {});
Deno.test(function foo() {}); // <- previously not discovered
```
## Fix
Track a per-(parent_id, name) occurrence index (`name_index`) on each
`TestDefinition` and fold it into the id hash when non-zero. The static
collector counts existing matches in `defs` at registration time; the
dynamic test reporter keeps a per-run counter so runtime registrations
resolve to the matching static definitions in source order.
`name_index == 0` preserves the original hash, so existing test ids —
and the assertions in the existing collector unit tests — are unchanged
for the common (unique-name) case.
Steps with duplicate names inside duplicate-named parents are also
handled: a parent's `name_index` is folded into its children's id hash
via the parent-chain walk, so two `step` children under two different
`foo` parents now get distinct ids.
## Test plan
- [x] Existing `cli/lsp/testing/collectors.rs` unit tests pass
unchanged.
- [x] New regression tests added:
- `test_test_collector_duplicate_test_names` — three duplicate-named
top-level tests each get a unique id and `name_index` 0/1/2.
- `test_test_collector_duplicate_test_names_with_steps` — two
`Deno.test("foo", …)` blocks with a `"step"` each both register, and the
two steps belong to different parents.
Closes denoland/deno#20371
Closes denoland/divybot#355
Co-authored-by: divybot <divybot@users.noreply.github.com>
Co-authored-by: Divy Srivastava <me@littledivy.com> E
em committed
7b230eae48434929811d8f68332e973bce7e3bf9
Parent: 95209b3
Committed by GitHub <noreply@github.com>
on 6/1/2026, 1:28:27 AM