Skip to content

Commit 1003d8b

Browse files
committed
test: add coverage for perf optimizations — fastStripNullable, skipGraphPhases, AST pruning
- 6 new unit tests for fastStripNullable branches (simple id, nullable union, bare keyword) - 4 new integration tests for skipGraphPhases pipeline option - Tests for SKIP_SUBTREE_TYPES and interestingNodeTypes code paths
1 parent 74b9701 commit 1003d8b

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

gitnexus/test/integration/resolvers/javascript.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,39 @@ import {
88
runPipelineFromRepo, type PipelineResult,
99
} from './helpers.js';
1010

11+
// ---------------------------------------------------------------------------
12+
// skipGraphPhases: verify pipeline works correctly when graph phases are skipped
13+
// ---------------------------------------------------------------------------
14+
15+
describe('Pipeline skipGraphPhases option', () => {
16+
let result: PipelineResult;
17+
18+
beforeAll(async () => {
19+
result = await runPipelineFromRepo(
20+
path.join(FIXTURES, 'javascript-self-this-resolution'),
21+
() => {},
22+
{ skipGraphPhases: true },
23+
);
24+
}, 60000);
25+
26+
it('produces graph nodes without community/process phases', () => {
27+
expect(getNodesByLabel(result, 'Class').length).toBeGreaterThan(0);
28+
});
29+
30+
it('still resolves CALLS edges correctly', () => {
31+
const calls = getRelationships(result, 'CALLS');
32+
expect(calls.length).toBeGreaterThan(0);
33+
});
34+
35+
it('omits communityResult when skipGraphPhases is true', () => {
36+
expect(result.communityResult).toBeUndefined();
37+
});
38+
39+
it('omits processResult when skipGraphPhases is true', () => {
40+
expect(result.processResult).toBeUndefined();
41+
});
42+
});
43+
1144
// ---------------------------------------------------------------------------
1245
// this.save() resolves to enclosing class's own save method
1346
// ---------------------------------------------------------------------------

gitnexus/test/unit/type-env.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3526,4 +3526,65 @@ fn process(opt: Option<User>) {
35263526
});
35273527
});
35283528

3529+
describe('performance optimizations — coverage for new code paths', () => {
3530+
it('fastStripNullable: passes through simple identifier without stripping', () => {
3531+
const tree = parse('function f(user: User) { user.save(); }', TypeScript.typescript);
3532+
const typeEnv = buildTypeEnv(tree, 'typescript');
3533+
// lookup exercises fastStripNullable — "User" has no | or ? markers
3534+
const callNode = tree.rootNode.descendantForIndex(tree.rootNode.text.indexOf('save'));
3535+
expect(typeEnv.lookup('user', callNode)).toBe('User');
3536+
});
3537+
3538+
it('fastStripNullable: strips nullable union type via full stripNullable', () => {
3539+
const tree = parse('function f(user: User | null) { user.save(); }', TypeScript.typescript);
3540+
const typeEnv = buildTypeEnv(tree, 'typescript');
3541+
const callNode = tree.rootNode.descendantForIndex(tree.rootNode.text.indexOf('save'));
3542+
expect(typeEnv.lookup('user', callNode)).toBe('User');
3543+
});
3544+
3545+
it('fastStripNullable: rejects bare nullable keyword', () => {
3546+
const tree = parse('function f(x: null) { x.save(); }', TypeScript.typescript);
3547+
const typeEnv = buildTypeEnv(tree, 'typescript');
3548+
const callNode = tree.rootNode.descendantForIndex(tree.rootNode.text.indexOf('save'));
3549+
expect(typeEnv.lookup('x', callNode)).toBeUndefined();
3550+
});
3551+
3552+
it('fastStripNullable: strips optional type suffix', () => {
3553+
const tree = parse(`
3554+
class Foo {
3555+
process(user: User) {
3556+
user.save();
3557+
}
3558+
}
3559+
`, TypeScript.typescript);
3560+
const typeEnv = buildTypeEnv(tree, 'typescript');
3561+
const callNode = tree.rootNode.descendantForIndex(tree.rootNode.text.indexOf('save'));
3562+
expect(typeEnv.lookup('user', callNode)).toBe('User');
3563+
});
3564+
3565+
it('SKIP_SUBTREE_TYPES: string literal subtrees do not affect type extraction', () => {
3566+
const tree = parse(`
3567+
function f(user: User) {
3568+
const msg = "hello world this is a long string";
3569+
user.save();
3570+
}
3571+
`, TypeScript.typescript);
3572+
const { env } = buildTypeEnv(tree, 'typescript');
3573+
expect(flatGet(env, 'user')).toBe('User');
3574+
});
3575+
3576+
it('interestingNodeTypes: non-declaration nodes skip extractTypeBinding', () => {
3577+
// Large code with many non-interesting nodes (binary expressions, calls, etc.)
3578+
const tree = parse(`
3579+
function calculate(service: Service) {
3580+
const a = 1 + 2 + 3;
3581+
const b = true && false;
3582+
if (a > b) { service.run(); }
3583+
}
3584+
`, TypeScript.typescript);
3585+
const { env } = buildTypeEnv(tree, 'typescript');
3586+
expect(flatGet(env, 'service')).toBe('Service');
3587+
});
3588+
});
3589+
35293590
});

0 commit comments

Comments
 (0)