This commit is contained in:
Colby McHenry
2026-01-18 16:25:00 -06:00
parent 08ccabb5a9
commit cc6e7a5c89
57 changed files with 23315 additions and 1 deletions
+172
View File
@@ -0,0 +1,172 @@
/**
* Grammar Loading and Caching
*
* Manages tree-sitter language grammars.
*/
import Parser from 'tree-sitter';
import { Language } from '../types';
// Grammar module imports
// eslint-disable-next-line @typescript-eslint/no-require-imports
const TypeScript = require('tree-sitter-typescript').typescript;
// eslint-disable-next-line @typescript-eslint/no-require-imports
const TSX = require('tree-sitter-typescript').tsx;
// eslint-disable-next-line @typescript-eslint/no-require-imports
const JavaScript = require('tree-sitter-javascript');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Python = require('tree-sitter-python');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Go = require('tree-sitter-go');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Rust = require('tree-sitter-rust');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Java = require('tree-sitter-java');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const C = require('tree-sitter-c');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Cpp = require('tree-sitter-cpp');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const CSharp = require('tree-sitter-c-sharp');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const PHP = require('tree-sitter-php').php;
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Ruby = require('tree-sitter-ruby');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Swift = require('tree-sitter-swift');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const Kotlin = require('tree-sitter-kotlin');
/**
* Mapping of Language to tree-sitter grammar
*/
const GRAMMAR_MAP: Record<string, unknown> = {
typescript: TypeScript,
tsx: TSX,
javascript: JavaScript,
jsx: JavaScript, // JSX uses the JavaScript grammar
python: Python,
go: Go,
rust: Rust,
java: Java,
c: C,
cpp: Cpp,
csharp: CSharp,
php: PHP,
ruby: Ruby,
swift: Swift,
kotlin: Kotlin,
};
/**
* File extension to Language mapping
*/
export const EXTENSION_MAP: Record<string, Language> = {
'.ts': 'typescript',
'.tsx': 'tsx',
'.js': 'javascript',
'.mjs': 'javascript',
'.cjs': 'javascript',
'.jsx': 'jsx',
'.py': 'python',
'.pyw': 'python',
'.go': 'go',
'.rs': 'rust',
'.java': 'java',
'.c': 'c',
'.h': 'c', // Could also be C++, defaulting to C
'.cpp': 'cpp',
'.cc': 'cpp',
'.cxx': 'cpp',
'.hpp': 'cpp',
'.hxx': 'cpp',
'.cs': 'csharp',
'.php': 'php',
'.rb': 'ruby',
'.rake': 'ruby',
'.swift': 'swift',
'.kt': 'kotlin',
'.kts': 'kotlin',
};
/**
* Cache for initialized parsers
*/
const parserCache = new Map<Language, Parser>();
/**
* Get a parser for the specified language
*/
export function getParser(language: Language): Parser | null {
// Check cache first
if (parserCache.has(language)) {
return parserCache.get(language)!;
}
// Get grammar for language
const grammar = GRAMMAR_MAP[language];
if (!grammar) {
return null;
}
// Create and cache parser
const parser = new Parser();
parser.setLanguage(grammar as Parameters<typeof parser.setLanguage>[0]);
parserCache.set(language, parser);
return parser;
}
/**
* Detect language from file extension
*/
export function detectLanguage(filePath: string): Language {
const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
return EXTENSION_MAP[ext] || 'unknown';
}
/**
* Check if a language is supported
*/
export function isLanguageSupported(language: Language): boolean {
return language !== 'unknown' && language in GRAMMAR_MAP;
}
/**
* Get all supported languages
*/
export function getSupportedLanguages(): Language[] {
return Object.keys(GRAMMAR_MAP) as Language[];
}
/**
* Clear the parser cache (useful for testing)
*/
export function clearParserCache(): void {
parserCache.clear();
}
/**
* Get language display name
*/
export function getLanguageDisplayName(language: Language): string {
const names: Record<Language, string> = {
typescript: 'TypeScript',
javascript: 'JavaScript',
tsx: 'TypeScript (TSX)',
jsx: 'JavaScript (JSX)',
python: 'Python',
go: 'Go',
rust: 'Rust',
java: 'Java',
c: 'C',
cpp: 'C++',
csharp: 'C#',
php: 'PHP',
ruby: 'Ruby',
swift: 'Swift',
kotlin: 'Kotlin',
unknown: 'Unknown',
};
return names[language] || language;
}