From 095110553830ec910cfac20e4d827b6e752cde58 Mon Sep 17 00:00:00 2001 From: Colby Mchenry Date: Sat, 10 Oct 2026 05:56:32 +0000 Subject: [PATCH] fix(react): a tag that passes type arguments renders its generic component (#2476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The jsx-render pass read a tag's name only where whitespace, `/` or `>` ended it, so a generic component's tag, whose type arguments follow its name, was never read: outline's ` items={…} />` and excalidraw's `` left the parent with no edge to the component it renders. The tag pattern now also ends a name at `<`, as a lookahead, so that `<` still opens the next match, which `opensTag` (#2442) reads as a type argument, not a tag. This lands after the package-import gate for JSX tags (#2475). On main alone the same change also linked 5 package tags to project namesakes by name (refine's react95 `>`, antd `>` and `>`; signoz's antd `>` ×2 to a styled `Form`), which the gate declines. Fresh before/after indexes with the gate as the base: 22 jsx-render edges added and nothing else changed (outline 10 to `PaginatedList`, signoz 8, excalidraw 2, mastodon 2). Each target is what the file's import or own declaration binds, checked with the TypeScript checker with module resolution. refine-examples, bulletproof-react, mantis, proshop_mern, next-saas-starter and create-t3-turbo are byte-identical. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + __tests__/jsx-child-disambiguation.test.ts | 169 ++++++++++++++++++++- __tests__/jsx-render-work.test.ts | 2 +- src/resolution/callback-synthesizer.ts | 6 +- 4 files changed, 173 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d7845d54..946bba27e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `codegraph sync` and the file watcher now link a component to the JSX that renders it, like ``, when the component is added in a file with no JSX of its own, as in `export default function Team() { return null; }`. Before, the link waited for an unrelated change to a file with JSX, or for a re-index, so the new component looked unused. - In JavaScript and TypeScript, a default import now links to what the module's `export default` statement exports, wherever the statement sits in the file. Before, a module that declares its default, like `export default function Vans() {…}` or `export default class Store {…}`, had its default import linked to the first function it exports instead: in a React Router data-router app, where a page exports its `loader` or `action` above the page component, `import Vans, { loader as vansLoader } from './pages/Vans'` made the route `/vans` and every use of `Vans` lead to the loader. A component file that also exports a styled or memoized component no longer hands its default import to that component, and an anonymous default, like `export default function () {…}` or `export default () => …`, is no longer linked to a function exported beside it or nested inside it. Re-index JavaScript and TypeScript projects after upgrading. - In React and Vue, a tag for a component the file imports from a package, like `