diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d562a5ea6..ac2dbb3ec3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,10 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixes +- Vue templates are indexed as uses: `:prop="x"`, `@event="save"`, `v-if` / `v-for` / `v-model` values and `{{ mustache }}` expressions now link to the script state, functions and imports they bind, so "where is `myLinkBrandingLocked` used" answers from the graph and `codegraph_explore` shows the template lines that bind a symbol you named. + +- `codegraph_explore` no longer spends its budget on files that match only a plain word in the query when the query also names a symbol exactly: after the named symbol's file, files wired to that symbol come before an unrelated file that shares a word like "section". + - The Claude Code prompt hook no longer runs on the task-notification messages Claude Code injects when a background agent finishes, removing a multi-second stall on every such turn. (#1832) - Rust calls on `self` now stay with the enclosing type instead of linking to an unrelated type’s same-named method. Thanks @L4XB. (#1861) diff --git a/__tests__/explore-nl-stopword-collision.test.ts b/__tests__/explore-nl-stopword-collision.test.ts index df67b016f2..579eb49f44 100644 --- a/__tests__/explore-nl-stopword-collision.test.ts +++ b/__tests__/explore-nl-stopword-collision.test.ts @@ -174,3 +174,52 @@ describe('codegraph_explore — interface members never corroborate a bare word' expect(files[0]).toBe('src/extensionHostProcess.ts'); }); }); + +describe('codegraph_explore — precise-before-plain file tier', () => { + let testDir: string; + let cg: CodeGraph; + + afterEach(() => { + cg?.destroy(); + if (testDir && fs.existsSync(testDir)) fs.rmSync(testDir, { recursive: true, force: true }); + }); + + it('a file tied to the exactly-named symbol outranks files that match only a plain query word', async () => { + // `WorkspaceMyLinkView appearance section myLinkBrandingLocked` rendered the + // view first and then filled the budget with a PHP layout class that matched + // only "section", ahead of everything wired to `myLinkBrandingLocked`. + testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-precise-first-')); + const profile = path.join(testDir, 'src', 'profile'); + const layout = path.join(testDir, 'src', 'layout'); + fs.mkdirSync(profile, { recursive: true }); + fs.mkdirSync(layout, { recursive: true }); + fs.writeFileSync(path.join(profile, 'branding.ts'), + 'export function myLinkBrandingLocked(plan: string): boolean {\n' + + " return plan !== 'pro';\n" + + '}\n'); + fs.writeFileSync(path.join(profile, 'panel.ts'), + "import { myLinkBrandingLocked } from './branding';\n" + + 'export function drawOwnDomainPanel(plan: string): string {\n' + + " return myLinkBrandingLocked(plan) ? 'upgrade' : 'edit';\n" + + '}\n'); + // A dense mesh of `section` symbols: FTS roots for the plain word "section". + fs.writeFileSync(path.join(layout, 'sections.ts'), + 'export function section(name: string): string {\n return renderSection(name);\n}\n' + + 'export function renderSection(name: string): string {\n return sectionHeader(name) + sectionBody(name);\n}\n' + + 'export function sectionHeader(name: string): string {\n return `
{{ $t('label') }} {{ 'isActive' }}
+