mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-01 02:01:24 +00:00
* docs: add Objective-C fork provider notes * feat(objective-c): add deterministic provider and grammar * feat(objective-c): finalize provider MVP * fix(objective-c): harden provider integration * fix(objective-c): normalize bare macro markers * docs(objective-c): integrate provider documentation * fix(objective-c): harden resolution and header classification * fix(objective-c): complete provider follow-ups * fix: address Objective-C review follow-ups * chore: format Objective-C grammar sources * fix(objective-c): harden review follow-ups * Address PR review feedback (#3179) Keep Objective-C chunking and macro recovery aligned with the grammar, and stop Community MEMBER_OF edges from leaking into symbol context. Co-authored-by: Cursor <cursoragent@cursor.com> * Address follow-up review on ObjC chunking and language fallback. Keep preprocessor directive text from changing file-scope brace depth, group real ivar nodes, skip header modifiers, and restore Rakefile/Gemfile detection through getLanguageFromFilename. Co-authored-by: Cursor <cursoragent@cursor.com> * Parse Objective-C headers with the objc grammar in embeddings. ensureAndParse and structural extraction now use the same content classifier as ingest, including method snippets from .h files, so Protocol/Category/Class chunks are not re-parsed as C++. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Keep file-scope macro elision off C line splices and @interface/@protocol/@implementation bodies, and attach ivar attributes to the following instance variable when chunking. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(bench): rebaseline Objective-C CSV emit * feat(objective-c): add workspace resolution and linear emit benches Plain .h files are classified as C++, so the ObjC pass could not resolve #import of those headers. Load a C/C#-style workspace once per pass, and keep protocol-candidate USES linear. Refs #3179 Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) - Compare LadybugDB labels() as a scalar when excluding Community MEMBER_OF edges. - Walk superclass members, skip file-static C sibling defs, and ignore comments in ObjC header/macro scans. Note: pre-existing failure in objective-c-provider integration (worker-pool ready timeout) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Emit Objective-C declaration captures so compilation-unit siblings can share header/implementation bindings, and keep class vs protocol visibility groups distinct. Note: pre-existing failure in worker-pool startup (GITNEXUS_WORKER_READY_TIMEOUT_MS) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Emit every comma-separated property/ivar declarator, and count @interface after a multiline block comment closes so in-declaration macros stay intact. Note: pre-existing failure in worker-pool startup (GITNEXUS_WORKER_READY_TIMEOUT_MS) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: ximengkai <ximengkai@soyoung.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
4 KiB
TypeScript
116 lines
4 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.Dart]: {
|
|
filePath: 'meters.dart',
|
|
source: ['extension type Meters(int value) {', ' int get raw => value;', '}', ''].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);
|
|
});
|
|
},
|
|
);
|
|
});
|
|
});
|