Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- In JavaScript and TypeScript, an import written `import { default as AppRoot } from './routes/app/root'`, as in bulletproof-react's router, now counts as the module's default import, the same as `import AppRoot from './routes/app/root'`. Before, it was read as an import of an export named `default`, which no module has, so a call, a route or a JSX attribute that used `AppRoot` was matched by its name alone: it could link to another file's `AppRoot`, or to nothing when the default export has a name of its own. Svelte, Vue and Astro script blocks are read the same way.
- In React, a component's JSX no longer links it to a class or component that only shares a name with one of its type arguments or with a variable of its own. A type in angle brackets, like `Document` in `<PaginatedList<Document> items={…} />`, `User` in `useState<User>()` or `Entry` in a generic `<Entry extends BaseEntity>(…) =>` component, is no longer read as a tag. A tag naming a variable or parameter the component sets itself, like `<Content>` after `const Content = isDropdown ? DropdownMenu.SubContent : ContextMenu.SubContent` or `<Widget>` in `widgets.map((Widget) => <Widget />)`, now links to nothing, unless the component declares a component of that name inside itself. Before, these linked to an unrelated class or component elsewhere in the repository: outline's document lists showed up among the callers of its `Document` model class, and its menus among the callers of the command bar's `Content`, so `codegraph_explore`, callers and impact followed renders that never happen. Re-index React projects after upgrading.
- In JavaScript and TypeScript, a name imported from a package your `package.json` lists no longer links to a project symbol that only shares its name when `tsconfig.json` or `jsconfig.json` has a catch-all path alias, like `"*": ["./typings/*"]` or `"*": ["src/*", "node_modules/*"]`, or an alias that points the package at a file in `node_modules`, like `"lit/decorators": ["./node_modules/lit/decorators.js"]`. Such an alias made every package look like part of the project, so `import { Typography } from '@mui/material'` was linked to the project's own `Typography` and every lit `@property()` decorator to an unrelated class's `property` field, and `codegraph callers`, impact and `codegraph affected` listed code that never used them. An import the alias does map to a file of your project, like a `.d.ts` you keep for an untyped package or `components/Button` through `"*": ["src/*"]`, links as before. Re-index affected projects after upgrading.
- Kotlin `fun interface` declarations are indexed, and no longer hide the declaration that follows them.
- Kotlin calls through a class property, a primary-constructor property, or a variable set from a function call now resolve on the declared type, and a call on a library type (such as `Regex` or a JDK class) no longer links to an unrelated project method with the same name. Chained receivers such as `engine.pump.drain()`, `this.engine.drain()` and `Mode.ON.next()` resolve the same way, as do properties inherited from a project base class and variables of the enclosing function used inside an anonymous `object : …`. Re-index Kotlin projects to pick this up.

## [1.6.2] - 2026-10-03

Expand Down
17 changes: 17 additions & 0 deletions __tests__/fixtures/kernel-parity/torture.kt
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,20 @@ class SiblingAccessorK {
register(fromInit)
}
}

class ReceiverChainK(private val engine: EngineK) {
fun chains() {
engine.pump.drain()
this.engine.drain()
engine?.pump?.drain()
engine
.pump
.drain()
engine.a.b.c.drain()
engine.a.b.c.d.drain()
engine!!.pump.drain()
(engine).pump.drain()
engine.pump().drain()
super.toString().length.toString()
}
}
19 changes: 11 additions & 8 deletions __tests__/kernel-kotlin-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,19 @@ describe.skipIf(!kernelBuilt)('kernel Kotlin extraction parity', () => {
});
}

it('fun-interface files defer to the wasm extractor (grammar-inherent error)', () => {
const src = 'package p\n\nfun interface Transformer {\n fun transform(x: Int): Int\n}\n\nfun after() { work() }\n';
it('fun-interface files parse on both paths once `fun` is blanked (preParse)', () => {
// tree-sitter-kotlin has no `fun interface`; the extractor's preParse
// blanks the `fun` (offset-preserving), so the kernel no longer defers
// and the declaration after it — here behind a doc comment, the shape
// whose error recovery used to swallow it — is extracted too.
const src = 'package p\n\nfun interface Transformer {\n fun transform(x: Int): Int\n}\n\n/** Next. */\ninterface Sink {\n fun put(x: Int)\n}\n\nfun after() { work() }\n';
assertParity('src/FunIface.kt', src, 4);
process.env.CODEGRAPH_KERNEL_LANGS = 'all';
delete process.env.CODEGRAPH_KERNEL;
expect(tryKernelExtract('src/FunIface.kt', src, 'kotlin')).toBeNull();
process.env.CODEGRAPH_KERNEL = '0';
const viaWasm = extractFromSource('src/FunIface.kt', src, 'kotlin');
delete process.env.CODEGRAPH_KERNEL;
// The wasm arm's misparse-recovery hook still mints the interface node.
expect(viaWasm.nodes.some((n) => n.kind === 'interface' && n.name === 'Transformer')).toBe(true);
const result = tryKernelExtract('src/FunIface.kt', src, 'kotlin')!;
expect(result.nodes.some((n) => n.kind === 'interface' && n.name === 'Transformer')).toBe(true);
expect(result.nodes.some((n) => n.kind === 'interface' && n.name === 'Sink')).toBe(true);
expect(result.nodes.some((n) => n.kind === 'method' && n.qualifiedName.endsWith('Sink::put'))).toBe(true);
});

it('PHANTOM errors defer too — hasError with a complete, ERROR-node-free CST', () => {
Expand Down
Loading