grammars.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /**
  2. * Grammar Loading and Caching
  3. *
  4. * Manages tree-sitter language grammars.
  5. */
  6. import Parser from 'tree-sitter';
  7. import { Language } from '../types';
  8. // Grammar module imports
  9. // eslint-disable-next-line @typescript-eslint/no-require-imports
  10. const TypeScript = require('tree-sitter-typescript').typescript;
  11. // eslint-disable-next-line @typescript-eslint/no-require-imports
  12. const TSX = require('tree-sitter-typescript').tsx;
  13. // eslint-disable-next-line @typescript-eslint/no-require-imports
  14. const JavaScript = require('tree-sitter-javascript');
  15. // eslint-disable-next-line @typescript-eslint/no-require-imports
  16. const Python = require('tree-sitter-python');
  17. // eslint-disable-next-line @typescript-eslint/no-require-imports
  18. const Go = require('tree-sitter-go');
  19. // eslint-disable-next-line @typescript-eslint/no-require-imports
  20. const Rust = require('tree-sitter-rust');
  21. // eslint-disable-next-line @typescript-eslint/no-require-imports
  22. const Java = require('tree-sitter-java');
  23. // eslint-disable-next-line @typescript-eslint/no-require-imports
  24. const C = require('tree-sitter-c');
  25. // eslint-disable-next-line @typescript-eslint/no-require-imports
  26. const Cpp = require('tree-sitter-cpp');
  27. // eslint-disable-next-line @typescript-eslint/no-require-imports
  28. const CSharp = require('tree-sitter-c-sharp');
  29. // eslint-disable-next-line @typescript-eslint/no-require-imports
  30. const PHP = require('tree-sitter-php').php;
  31. // eslint-disable-next-line @typescript-eslint/no-require-imports
  32. const Ruby = require('tree-sitter-ruby');
  33. // eslint-disable-next-line @typescript-eslint/no-require-imports
  34. const Swift = require('tree-sitter-swift');
  35. // eslint-disable-next-line @typescript-eslint/no-require-imports
  36. const Kotlin = require('tree-sitter-kotlin');
  37. /**
  38. * Mapping of Language to tree-sitter grammar
  39. */
  40. const GRAMMAR_MAP: Record<string, unknown> = {
  41. typescript: TypeScript,
  42. tsx: TSX,
  43. javascript: JavaScript,
  44. jsx: JavaScript, // JSX uses the JavaScript grammar
  45. python: Python,
  46. go: Go,
  47. rust: Rust,
  48. java: Java,
  49. c: C,
  50. cpp: Cpp,
  51. csharp: CSharp,
  52. php: PHP,
  53. ruby: Ruby,
  54. swift: Swift,
  55. kotlin: Kotlin,
  56. };
  57. /**
  58. * File extension to Language mapping
  59. */
  60. export const EXTENSION_MAP: Record<string, Language> = {
  61. '.ts': 'typescript',
  62. '.tsx': 'tsx',
  63. '.js': 'javascript',
  64. '.mjs': 'javascript',
  65. '.cjs': 'javascript',
  66. '.jsx': 'jsx',
  67. '.py': 'python',
  68. '.pyw': 'python',
  69. '.go': 'go',
  70. '.rs': 'rust',
  71. '.java': 'java',
  72. '.c': 'c',
  73. '.h': 'c', // Could also be C++, defaulting to C
  74. '.cpp': 'cpp',
  75. '.cc': 'cpp',
  76. '.cxx': 'cpp',
  77. '.hpp': 'cpp',
  78. '.hxx': 'cpp',
  79. '.cs': 'csharp',
  80. '.php': 'php',
  81. '.rb': 'ruby',
  82. '.rake': 'ruby',
  83. '.swift': 'swift',
  84. '.kt': 'kotlin',
  85. '.kts': 'kotlin',
  86. };
  87. /**
  88. * Cache for initialized parsers
  89. */
  90. const parserCache = new Map<Language, Parser>();
  91. /**
  92. * Get a parser for the specified language
  93. */
  94. export function getParser(language: Language): Parser | null {
  95. // Check cache first
  96. if (parserCache.has(language)) {
  97. return parserCache.get(language)!;
  98. }
  99. // Get grammar for language
  100. const grammar = GRAMMAR_MAP[language];
  101. if (!grammar) {
  102. return null;
  103. }
  104. // Create and cache parser
  105. const parser = new Parser();
  106. parser.setLanguage(grammar as Parameters<typeof parser.setLanguage>[0]);
  107. parserCache.set(language, parser);
  108. return parser;
  109. }
  110. /**
  111. * Detect language from file extension
  112. */
  113. export function detectLanguage(filePath: string): Language {
  114. const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
  115. return EXTENSION_MAP[ext] || 'unknown';
  116. }
  117. /**
  118. * Check if a language is supported
  119. */
  120. export function isLanguageSupported(language: Language): boolean {
  121. return language !== 'unknown' && language in GRAMMAR_MAP;
  122. }
  123. /**
  124. * Get all supported languages
  125. */
  126. export function getSupportedLanguages(): Language[] {
  127. return Object.keys(GRAMMAR_MAP) as Language[];
  128. }
  129. /**
  130. * Clear the parser cache (useful for testing)
  131. */
  132. export function clearParserCache(): void {
  133. parserCache.clear();
  134. }
  135. /**
  136. * Get language display name
  137. */
  138. export function getLanguageDisplayName(language: Language): string {
  139. const names: Record<Language, string> = {
  140. typescript: 'TypeScript',
  141. javascript: 'JavaScript',
  142. tsx: 'TypeScript (TSX)',
  143. jsx: 'JavaScript (JSX)',
  144. python: 'Python',
  145. go: 'Go',
  146. rust: 'Rust',
  147. java: 'Java',
  148. c: 'C',
  149. cpp: 'C++',
  150. csharp: 'C#',
  151. php: 'PHP',
  152. ruby: 'Ruby',
  153. swift: 'Swift',
  154. kotlin: 'Kotlin',
  155. unknown: 'Unknown',
  156. };
  157. return names[language] || language;
  158. }