GitNexus/gitnexus/test/unit/preprocess-source-parity.test.ts
gitnexus-release-bot[bot] 47d63a0601
chore(vendor): update tree-sitter-dart to 1.0.0-g0038280 (#3633)
* chore(vendor): update tree-sitter-dart to 1.0.0-g0038280

* chore(vendor): rebuild native prebuilds (tree-sitter-dart)

Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39212887661

* fix(dart): use native extension type parsing

The upgraded grammar parses extension types directly. The compatibility
rewrite loses generic extension bodies and implements clauses, so capture
the native nodes and register their member ownership instead.

Refresh the Dart capture fingerprint after comparing the old grammar and
emitter over the same fixture corpus. Keep the scaling budget unchanged.

Refs #3633

* chore(vendor): rebuild native prebuilds (tree-sitter-dart)

Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39239767139

* fix: repair Dart parity and checkpoint regressions

Remove Dart from the preprocessing fixture inventory after retiring its
hook. Use the parsed body boundary when reading extension-type heritage
so named-record representations retain their implements clauses.

Seed the WAL recovery fixture with the normal checkpoint threshold, then
force one-byte checkpoints only for the deliberately blocked write.
Require an actual error exit instead of accepting a subprocess timeout.

Refs #3633

* chore(vendor): rebuild native prebuilds (tree-sitter-dart)

Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39248441688

---------

Co-authored-by: gitnexus-release-bot[bot] <gitnexus-release-bot[bot]@users.noreply.github.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-19 15:41:34 +01:00

112 lines
3.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { SupportedLanguages } from 'gitnexus-shared';
import { providers, getProvider } from '../../src/core/ingestion/languages/index.js';
import { extractParsedFile } from '../../src/core/ingestion/scope-extractor-bridge.js';
import { isLanguageAvailable } from '../../src/core/tree-sitter/parser-loader.js';
import { ensureAndParse } from '../../src/core/embeddings/ast-utils.js';
import type { LanguageProvider } from '../../src/core/ingestion/language-provider.js';
/**
* Every provider that defines `preprocessSource` must produce the same
* `ParsedFile` whether it is handed raw source or already-preprocessed source.
*
* The parse worker applies the hook, but `emitScopeCaptures` re-parses on a
* parse-cache miss and the embedding pipeline parses independently — so unless
* those paths see the same transform the halves of the pipeline analyze
* different programs and the graph depends on whether the run was warm (#2771).
*
* Fixtures are keyed by language and cross-checked against the registry, so a
* new provider adopting the hook fails here until it adds one.
*/
const FIXTURES: Partial<Record<SupportedLanguages, { filePath: string; source: string }>> = {
[SupportedLanguages.Swift]: {
filePath: 'Fixture.swift',
source: [
'class Outer {',
' enum A { case x }',
' #if os(iOS)',
' enum B { case y }',
' #endif',
'}',
'',
].join('\n'),
},
[SupportedLanguages.CPlusPlus]: {
filePath: 'Actor.cpp',
source: [
'UCLASS()',
'class MYGAME_API AGameActor : public AActor {',
' GENERATED_BODY()',
'public:',
' UPROPERTY(EditAnywhere) int Health;',
' UFUNCTION(BlueprintCallable) void Tick(float DeltaTime) { Health = 1; }',
'};',
'',
].join('\n'),
},
[SupportedLanguages.ObjectiveC]: {
filePath: 'Marker.m',
source: [
'RCT_EXTERN_C_BEGIN',
'typedef struct {',
' int value;',
'} GNMarker;',
'RCT_EXTERN_C_END',
'@protocol GNMarkerProtocol',
'- (void)run;',
'@end',
'',
].join('\n'),
},
};
const languagesWithHook = Object.entries(providers)
.filter(([, provider]) => provider.preprocessSource !== undefined)
.map(([language]) => language)
.sort();
describe('LanguageProvider.preprocessSource parity', () => {
it('does not propagate an exception thrown by the warning callback', () => {
const provider = {
emitScopeCaptures: () => {
throw new Error('provider failed');
},
} as unknown as LanguageProvider;
expect(() =>
extractParsedFile(provider, 'const value = 1;', 'broken.ts', () => {
throw new Error('warning transport closed');
}),
).not.toThrow();
});
it('has a fixture for every provider defining the hook', () => {
expect(Object.keys(FIXTURES).sort()).toEqual(languagesWithHook);
});
describe.each(languagesWithHook)('%s', (language) => {
const provider = getProvider(language as SupportedLanguages);
const { filePath, source } = FIXTURES[language as SupportedLanguages]!;
describe.skipIf(!isLanguageAvailable(language as SupportedLanguages))(
'with the grammar',
() => {
it('extracts the same ParsedFile from raw and preprocessed source', () => {
const preprocessed = provider.preprocessSource!(source, filePath);
expect(preprocessed).not.toBe(source);
expect(preprocessed).toHaveLength(source.length);
expect(extractParsedFile(provider, source, filePath, () => {})).toEqual(
extractParsedFile(provider, preprocessed, filePath, () => {}),
);
});
it('parses the preprocessed text on the embedding path too', async () => {
const tree = await ensureAndParse(source, filePath);
expect(tree.rootNode.hasError).toBe(false);
});
},
);
});
});