diff --git a/gitnexus/src/core/ingestion/call-processor.ts b/gitnexus/src/core/ingestion/call-processor.ts index 9b6dfc3f4..98f8a8b11 100644 --- a/gitnexus/src/core/ingestion/call-processor.ts +++ b/gitnexus/src/core/ingestion/call-processor.ts @@ -3,7 +3,7 @@ import { ASTCache } from './ast-cache.js'; import { SymbolTable } from './symbol-table.js'; import { ImportMap } from './import-processor.js'; import Parser from 'tree-sitter'; -import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; +import { isLanguageAvailable, loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; import { LANGUAGE_QUERIES } from './tree-sitter-queries.js'; import { generateId } from '../../lib/utils.js'; import { getLanguageFromFilename, yieldToEventLoop } from './utils.js'; @@ -159,6 +159,7 @@ export const processCalls = async ( // 1. Check language support first const language = getLanguageFromFilename(file.path); if (!language) continue; + if (!isLanguageAvailable(language)) continue; const queryStr = LANGUAGE_QUERIES[language]; if (!queryStr) continue; diff --git a/gitnexus/src/core/ingestion/heritage-processor.ts b/gitnexus/src/core/ingestion/heritage-processor.ts index dbb7bac8c..2bd092f0a 100644 --- a/gitnexus/src/core/ingestion/heritage-processor.ts +++ b/gitnexus/src/core/ingestion/heritage-processor.ts @@ -10,7 +10,7 @@ import { KnowledgeGraph } from '../graph/types.js'; import { ASTCache } from './ast-cache.js'; import { SymbolTable } from './symbol-table.js'; import Parser from 'tree-sitter'; -import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; +import { isLanguageAvailable, loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; import { LANGUAGE_QUERIES } from './tree-sitter-queries.js'; import { generateId } from '../../lib/utils.js'; import { getLanguageFromFilename, yieldToEventLoop } from './utils.js'; @@ -33,6 +33,7 @@ export const processHeritage = async ( // 1. Check language support const language = getLanguageFromFilename(file.path); if (!language) continue; + if (!isLanguageAvailable(language)) continue; const queryStr = LANGUAGE_QUERIES[language]; if (!queryStr) continue; diff --git a/gitnexus/src/core/ingestion/import-processor.ts b/gitnexus/src/core/ingestion/import-processor.ts index 990f968af..494639540 100644 --- a/gitnexus/src/core/ingestion/import-processor.ts +++ b/gitnexus/src/core/ingestion/import-processor.ts @@ -3,7 +3,7 @@ import path from 'path'; import { KnowledgeGraph } from '../graph/types.js'; import { ASTCache } from './ast-cache.js'; import Parser from 'tree-sitter'; -import { loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; +import { isLanguageAvailable, loadParser, loadLanguage } from '../tree-sitter/parser-loader.js'; import { LANGUAGE_QUERIES } from './tree-sitter-queries.js'; import { generateId } from '../../lib/utils.js'; import { getLanguageFromFilename, yieldToEventLoop } from './utils.js'; @@ -781,6 +781,7 @@ export const processImports = async ( // 1. Check language support first const language = getLanguageFromFilename(file.path); if (!language) continue; + if (!isLanguageAvailable(language)) continue; const queryStr = LANGUAGE_QUERIES[language]; if (!queryStr) continue; diff --git a/gitnexus/test/unit/sequential-language-availability.test.ts b/gitnexus/test/unit/sequential-language-availability.test.ts new file mode 100644 index 000000000..265851400 --- /dev/null +++ b/gitnexus/test/unit/sequential-language-availability.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, it, vi, beforeEach } from 'vitest'; + +vi.mock('../../src/core/tree-sitter/parser-loader.js', () => ({ + loadParser: vi.fn(async () => ({ + parse: vi.fn(), + getLanguage: vi.fn(), + })), + loadLanguage: vi.fn(async () => undefined), + isLanguageAvailable: vi.fn(() => true), +})); + +import { createKnowledgeGraph } from '../../src/core/graph/graph.js'; +import { createASTCache } from '../../src/core/ingestion/ast-cache.js'; +import { createImportMap, processImports } from '../../src/core/ingestion/import-processor.js'; +import { processCalls } from '../../src/core/ingestion/call-processor.js'; +import { processHeritage } from '../../src/core/ingestion/heritage-processor.js'; +import { createSymbolTable } from '../../src/core/ingestion/symbol-table.js'; +import * as parserLoader from '../../src/core/tree-sitter/parser-loader.js'; + + +describe('sequential native parser availability', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('skips Swift files in processImports when the native parser is unavailable', async () => { + vi.mocked(parserLoader.isLanguageAvailable).mockReturnValue(false); + + await expect(processImports( + createKnowledgeGraph(), + [{ path: 'App.swift', content: 'import Foundation' }], + createASTCache(), + createImportMap(), + undefined, + '/tmp/repo', + ['App.swift'], + )).resolves.toBeUndefined(); + + expect(parserLoader.loadLanguage).not.toHaveBeenCalled(); + }); + + it('skips Swift files in processCalls when the native parser is unavailable', async () => { + vi.mocked(parserLoader.isLanguageAvailable).mockReturnValue(false); + + await expect(processCalls( + createKnowledgeGraph(), + [{ path: 'App.swift', content: 'func demo() {}' }], + createASTCache(), + createSymbolTable(), + createImportMap(), + )).resolves.toBeUndefined(); + + expect(parserLoader.loadLanguage).not.toHaveBeenCalled(); + }); + + it('skips Swift files in processHeritage when the native parser is unavailable', async () => { + vi.mocked(parserLoader.isLanguageAvailable).mockReturnValue(false); + + await expect(processHeritage( + createKnowledgeGraph(), + [{ path: 'App.swift', content: 'class AppViewController: UIViewController {}' }], + createASTCache(), + createSymbolTable(), + )).resolves.toBeUndefined(); + + expect(parserLoader.loadLanguage).not.toHaveBeenCalled(); + }); +});