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 @@ -14,6 +14,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Fixes

- 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.
- In TypeScript, an awaited call with type arguments like `await fetchApi<User>("/me")` or `await api.get<T>(url)` now links to the function it calls. Before, the call was dropped, so typed fetch wrappers looked like they had no callers. (#2586)
- In JavaScript and TypeScript, a call or `new` in a parameter's default value, like `function renderWithNote(note = buildNote())`, a destructured `{ size = defaultSize() }` or `constructor(private svc = new Service())`, now counts as the function's own call. Before, it was dropped, so `buildNote` was missing that caller and impact on it came back incomplete. Re-index JavaScript and TypeScript projects after upgrading. Thanks @inth3shadows for the report and the pull request. (#2588)
- In React, a component rendered at module scope, in a top-level constant or inside a test's `it(…)` callback, like `createRoot(el).render(<App />)` or `render(<Card />)`, now counts as rendered there, so an app's entry reaches its root component and a component's tests show among its callers. (#2587)
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 @@ -291,3 +291,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