diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +22 diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..68eec44 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +# Required: tree-sitter grammar packages declare peer deps on older tree-sitter versions +# (^0.21.x / ^0.22.x) while we use ^0.25.0. All packages use NAPI so this is ABI-safe. +# Remove when grammar packages release versions declaring tree-sitter ^0.25 as peer. +legacy-peer-deps=true diff --git a/CHANGELOG.md b/CHANGELOG.md index 54543fa..efa6f42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to AiDex will be documented in this file. ## [Unreleased] +### Changed +- **tree-sitter upgrade**: Bumped `tree-sitter` from 0.21 to 0.25 and all grammar packages to latest — enables support for newer grammar packages requiring tree-sitter ^0.25.0 + ## [1.17.0] - 2026-04-07 ### Added diff --git a/package-lock.json b/package-lock.json index b5fa084..ea61169 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { - "name": "aidex", - "version": "1.14.1", + "name": "aidex-mcp", + "version": "1.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "aidex", - "version": "1.14.1", + "name": "aidex-mcp", + "version": "1.17.0", + "hasInstallScript": true, "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.0.0", @@ -17,19 +18,23 @@ "highlight.js": "^11.11.0", "minimatch": "^10.1.1", "simple-git": "^3.27.0", - "tree-sitter": "^0.21.0", - "tree-sitter-c": "^0.21.0", - "tree-sitter-c-sharp": "^0.21.0", - "tree-sitter-cpp": "^0.22.0", - "tree-sitter-go": "^0.21.0", - "tree-sitter-java": "^0.21.0", - "tree-sitter-php": "^0.22.0", - "tree-sitter-python": "^0.21.0", - "tree-sitter-ruby": "^0.21.0", - "tree-sitter-rust": "^0.21.0", - "tree-sitter-typescript": "^0.21.0", + "tree-sitter": "^0.25.0", + "tree-sitter-c": "^0.24.1", + "tree-sitter-c-sharp": "^0.23.1", + "tree-sitter-cpp": "^0.23.4", + "tree-sitter-go": "^0.25.0", + "tree-sitter-java": "^0.23.5", + "tree-sitter-php": "^0.24.2", + "tree-sitter-python": "^0.25.0", + "tree-sitter-ruby": "^0.23.1", + "tree-sitter-rust": "^0.24.0", + "tree-sitter-typescript": "^0.23.2", "ws": "^8.19.0" }, + "bin": { + "aidex": "build/index.js", + "aidex-mcp": "build/index.js" + }, "devDependencies": { "@types/better-sqlite3": "^7.6.0", "@types/express": "^4.17.25", @@ -3222,18 +3227,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -3318,16 +3311,6 @@ "node": ">=12.0.0" } }, - "node_modules/hono": { - "version": "4.11.5", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.5.tgz", - "integrity": "sha512-WemPi9/WfyMwZs+ZUXdiwcCh9Y+m7L+8vki9MzDw3jJ+W9Lc+12HGsd368Qc1vZi1xwW8BWMMsnK5efYKPdt4g==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -6004,215 +5987,242 @@ } }, "node_modules/tree-sitter": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.21.1.tgz", - "integrity": "sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.25.0.tgz", + "integrity": "sha512-PGZZzFW63eElZJDe/b/R/LbsjDDYJa5UEjLZJB59RQsMX+fo0j54fqBPn1MGKav/QNa0JR0zBiVaikYDWCj5KQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0" + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" } }, "node_modules/tree-sitter-c": { - "version": "0.21.4", - "resolved": "https://registry.npmmirror.com/tree-sitter-c/-/tree-sitter-c-0.21.4.tgz", - "integrity": "sha512-IahxFIhXiY15SUlrt2upBiKSBGdOaE1fjKLK1Ik5zxqGHf6T1rvr3IJrovbsE5sXhypx7Hnmf50gshsppaIihA==", + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/tree-sitter-c/-/tree-sitter-c-0.24.1.tgz", + "integrity": "sha512-lkYwWN3SRecpvaeqmFKkuPNR3ZbtnvHU+4XAEEkJdrp3JfSp2pBrhXOtvfsENUneye76g889Y0ddF2DM0gEDpA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.3.1", + "node-gyp-build": "^4.8.4" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.22.4" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, "node_modules/tree-sitter-c-sharp": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/tree-sitter-c-sharp/-/tree-sitter-c-sharp-0.21.3.tgz", - "integrity": "sha512-TVsl5EhmqetO/mhzDPVnMK6TPFnpNMKP0OTNuAQIprshk5Hx672ODRxoIoG5WqvUUlsnBu8J0zmn35hmJqelsA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-c-sharp/-/tree-sitter-c-sharp-0.23.1.tgz", + "integrity": "sha512-9zZ4FlcTRWWfRf6f4PgGhG8saPls6qOOt75tDfX7un9vQZJmARjPrAC6yBNCX2T/VKcCjIDbgq0evFaB3iGhQw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, "node_modules/tree-sitter-cpp": { - "version": "0.22.3", - "resolved": "https://registry.npmmirror.com/tree-sitter-cpp/-/tree-sitter-cpp-0.22.3.tgz", - "integrity": "sha512-p7w5903L/koqTQFVDwyyX0vjioxoZu2G4zT2ZHVG8DvLQbWN6OjNAqfMsCi+WdVkfMgU+7j06hS8i3j6Q0sPNQ==", + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/tree-sitter-cpp/-/tree-sitter-cpp-0.23.4.tgz", + "integrity": "sha512-qR5qUDyhZ5jJ6V8/umiBxokRbe89bCGmcq/dk94wI4kN86qfdV8k0GHIUEKaqWgcu42wKal5E97LKpLeVW8sKw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.2.1", + "node-gyp-build": "^4.8.2", + "tree-sitter-c": "^0.23.1" }, "peerDependencies": { "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { + "optional": true + } + } + }, + "node_modules/tree-sitter-cpp/node_modules/tree-sitter-c": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/tree-sitter-c/-/tree-sitter-c-0.23.6.tgz", + "integrity": "sha512-0dxXKznVyUA0s6PjNolJNs2yF87O5aL538A/eR6njA5oqX3C3vH4vnx3QdOKwuUdpKEcFdHuiDpRKLLCA/tjvQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.22.1" + }, + "peerDependenciesMeta": { + "tree-sitter": { "optional": true } } }, "node_modules/tree-sitter-go": { - "version": "0.21.2", - "resolved": "https://registry.npmmirror.com/tree-sitter-go/-/tree-sitter-go-0.21.2.tgz", - "integrity": "sha512-aMFwjsB948nWhURiIxExK8QX29JYKs96P/IfXVvluVMRJZpL04SREHsdOZHYqJr1whkb7zr3/gWHqqvlkczmvw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter-go/-/tree-sitter-go-0.25.0.tgz", + "integrity": "sha512-APBc/Dq3xz/e35Xpkhb1blu5UgW+2E3RyGWawZSCNcbGwa7jhSQPS8KsUupuzBla8PCo8+lz9W/JDJjmfRa2tw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.1.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.3.1", + "node-gyp-build": "^4.8.4" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.25.0" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, "node_modules/tree-sitter-java": { - "version": "0.21.0", - "resolved": "https://registry.npmmirror.com/tree-sitter-java/-/tree-sitter-java-0.21.0.tgz", - "integrity": "sha512-CKJiTo1uc3SUsgEcaZgufGx8my6dzihy8JR/JsJH40Tj3uSe2/eFLk+0q+fpbosGAyY4YiXJtEoFB2O4bS2yOw==", + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/tree-sitter-java/-/tree-sitter-java-0.23.5.tgz", + "integrity": "sha512-Yju7oQ0Xx7GcUT01mUglPP+bYfvqjNCGdxqigTnew9nLGoII42PNVP3bHrYeMxswiCRM0yubWmN5qk+zsg0zMA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.0" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, - "node_modules/tree-sitter-php": { - "version": "0.22.8", - "resolved": "https://registry.npmmirror.com/tree-sitter-php/-/tree-sitter-php-0.22.8.tgz", - "integrity": "sha512-X3VeTwgofcRaR1+GQBBkA0dGdS8MntAPjkgmsqmYtx2Jh/+bYzvc8/nM+D5S6HQW7npvAIf6DzP1DADP5xooSw==", + "node_modules/tree-sitter-javascript": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-javascript/-/tree-sitter-javascript-0.23.1.tgz", + "integrity": "sha512-/bnhbrTD9frUYHQTiYnPcxyHORIw157ERBa6dqzaKxvR/x3PC4Yzd+D1pZIMS6zNg2v3a8BZ0oK7jHqsQo9fWA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "globals": "^15.4.0", - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" }, "peerDependencies": { "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, - "node_modules/tree-sitter-python": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.21.0.tgz", - "integrity": "sha512-IUKx7JcTVbByUx1iHGFS/QsIjx7pqwTMHL9bl/NGyhyyydbfNrpruo2C7W6V4KZrbkkCOlX8QVrCoGOFW5qecg==", + "node_modules/tree-sitter-php": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/tree-sitter-php/-/tree-sitter-php-0.24.2.tgz", + "integrity": "sha512-zwgAePc/HozNaWOOfwRAA+3p8yhuehRw8Fb7vn5qd2XjiIc93uJPryDTMYTSjBRjVIUg/KY6pM3rRzs8dSwKfw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^7.1.0", - "node-gyp-build": "^4.8.0" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.22.4" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, - "node_modules/tree-sitter-python/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" + "node_modules/tree-sitter-python": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/tree-sitter-python/-/tree-sitter-python-0.25.0.tgz", + "integrity": "sha512-eCmJx6zQa35GxaCtQD+wXHOhYqBxEL+bp71W/s3fcDMu06MrtzkVXR437dRrCrbrDbyLuUDJpAgycs7ncngLXw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.5.0", + "node-gyp-build": "^4.8.4" + }, + "peerDependencies": { + "tree-sitter": "^0.25.0" + }, + "peerDependenciesMeta": { + "tree-sitter": { + "optional": true + } + } }, "node_modules/tree-sitter-ruby": { - "version": "0.21.0", - "resolved": "https://registry.npmmirror.com/tree-sitter-ruby/-/tree-sitter-ruby-0.21.0.tgz", - "integrity": "sha512-UrMpF9CZxKbZ5UFuPdXDuraaaYSMMlAiuzTpQXwNm7y0D48ibc9stWU5D6vDyJD0qf5/R+3yKTYHdHkqibmLSQ==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/tree-sitter-ruby/-/tree-sitter-ruby-0.23.1.tgz", + "integrity": "sha512-d9/RXgWjR6HanN7wTYhS5bpBQLz1VkH048Vm3CodPGyJVnamXMGb8oEhDypVCBq4QnHui9sTXuJBBP3WtCw5RA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2" }, "peerDependencies": { - "tree-sitter": "^0.21.0" + "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, "node_modules/tree-sitter-rust": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/tree-sitter-rust/-/tree-sitter-rust-0.21.0.tgz", - "integrity": "sha512-unVr73YLn3VC4Qa/GF0Nk+Wom6UtI526p5kz9Rn2iZSqwIFedyCZ3e0fKCEmUJLIPGrTb/cIEdu3ZUNGzfZx7A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/tree-sitter-rust/-/tree-sitter-rust-0.24.0.tgz", + "integrity": "sha512-NWemUDf629Tfc90Y0Z55zuwPCAHkLxWnMf2RznYu4iBkkrQl2o/CHGB7Cr52TyN5F1DAx8FmUnDtCy9iUkXZEQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^7.1.0", - "node-gyp-build": "^4.8.0" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.4" }, "peerDependencies": { - "tree-sitter": "^0.21.1" + "tree-sitter": "^0.22.1" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } }, - "node_modules/tree-sitter-rust/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" - }, "node_modules/tree-sitter-typescript": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/tree-sitter-typescript/-/tree-sitter-typescript-0.21.2.tgz", - "integrity": "sha512-/RyNK41ZpkA8PuPZimR6pGLvNR1p0ibRUJwwQn4qAjyyLEIQD/BNlwS3NSxWtGsAWZe9gZ44VK1mWx2+eQVldg==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/tree-sitter-typescript/-/tree-sitter-typescript-0.23.2.tgz", + "integrity": "sha512-e04JUUKxTT53/x3Uq1zIL45DoYKVfHH4CZqwgZhPg5qYROl5nQjV+85ruFzFGZxu+QeFVbRTPDRnqL9UbU4VeA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "node-addon-api": "^8.0.0", - "node-gyp-build": "^4.8.1" + "node-addon-api": "^8.2.2", + "node-gyp-build": "^4.8.2", + "tree-sitter-javascript": "^0.23.1" }, "peerDependencies": { "tree-sitter": "^0.21.0" }, "peerDependenciesMeta": { - "tree_sitter": { + "tree-sitter": { "optional": true } } diff --git a/package.json b/package.json index 0c89d5e..60e247d 100644 --- a/package.json +++ b/package.json @@ -69,17 +69,17 @@ "highlight.js": "^11.11.0", "minimatch": "^10.1.1", "simple-git": "^3.27.0", - "tree-sitter": "^0.21.0", - "tree-sitter-c": "^0.21.0", - "tree-sitter-c-sharp": "^0.21.0", - "tree-sitter-cpp": "^0.22.0", - "tree-sitter-go": "^0.21.0", - "tree-sitter-java": "^0.21.0", - "tree-sitter-php": "^0.22.0", - "tree-sitter-python": "^0.21.0", - "tree-sitter-ruby": "^0.21.0", - "tree-sitter-rust": "^0.21.0", - "tree-sitter-typescript": "^0.21.0", + "tree-sitter": "^0.25.0", + "tree-sitter-c": "^0.24.1", + "tree-sitter-c-sharp": "^0.23.1", + "tree-sitter-cpp": "^0.23.4", + "tree-sitter-go": "^0.25.0", + "tree-sitter-java": "^0.23.5", + "tree-sitter-php": "^0.24.2", + "tree-sitter-python": "^0.25.0", + "tree-sitter-ruby": "^0.23.1", + "tree-sitter-rust": "^0.24.0", + "tree-sitter-typescript": "^0.23.2", "ws": "^8.19.0" }, "devDependencies": { diff --git a/src/parser/tree-sitter.ts b/src/parser/tree-sitter.ts index a60301d..4dc278c 100644 --- a/src/parser/tree-sitter.ts +++ b/src/parser/tree-sitter.ts @@ -20,6 +20,27 @@ export type SupportedLanguage = | 'csharp' | 'typescript' | 'javascript' | 'rust' | 'python' | 'c' | 'cpp' | 'java' | 'go' | 'php' | 'ruby'; +// Grammar packages export types incompatible with tree-sitter 0.25's Parser.Language interface. +// All grammars work at runtime via NAPI — this is a type declaration mismatch only. +const asLang = (grammar: unknown): Parser.Language => grammar as Parser.Language; + +// Maps each supported language (+ tsx/jsx virtual keys) to its tree-sitter grammar +const GRAMMAR_MAP: Record = { + csharp: asLang(CSharp), + typescript: asLang(TypeScript.typescript), + javascript: asLang(TypeScript.typescript), // TS parser handles JS too + rust: asLang(Rust), + python: asLang(Python), + c: asLang(C), + cpp: asLang(Cpp), + java: asLang(Java), + go: asLang(Go), + php: asLang(Php.php), + ruby: asLang(Ruby), + tsx: asLang(TypeScript.tsx), + jsx: asLang(TypeScript.tsx), // tsx grammar handles JSX too +}; + // File extension to language mapping const EXTENSION_MAP: Record = { '.cs': 'csharp', @@ -59,44 +80,7 @@ export function getParser(language: SupportedLanguage): Parser { } parser = new Parser(); - - switch (language) { - case 'csharp': - parser.setLanguage(CSharp); - break; - case 'typescript': - parser.setLanguage(TypeScript.typescript); - break; - case 'javascript': - parser.setLanguage(TypeScript.typescript); // TS parser handles JS too - break; - case 'rust': - parser.setLanguage(Rust); - break; - case 'python': - parser.setLanguage(Python); - break; - case 'c': - parser.setLanguage(C); - break; - case 'cpp': - parser.setLanguage(Cpp); - break; - case 'java': - parser.setLanguage(Java); - break; - case 'go': - parser.setLanguage(Go); - break; - case 'php': - parser.setLanguage(Php.php); - break; - case 'ruby': - parser.setLanguage(Ruby); - break; - default: - throw new Error(`Unsupported language: ${language}`); - } + parser.setLanguage(GRAMMAR_MAP[language]); parsers.set(language, parser); return parser; @@ -155,18 +139,13 @@ function getParserForGrammar(grammarKey: string): Parser { let parser = parsers.get(grammarKey); if (parser) return parser; - parser = new Parser(); - switch (grammarKey) { - case 'tsx': - parser.setLanguage(TypeScript.tsx); - break; - case 'jsx': - parser.setLanguage(TypeScript.tsx); // tsx grammar handles JSX too - break; - default: - return getParser(grammarKey as SupportedLanguage); + const grammar = GRAMMAR_MAP[grammarKey]; + if (!grammar) { + throw new Error(`Unsupported grammar: ${grammarKey}`); } + parser = new Parser(); + parser.setLanguage(grammar); parsers.set(grammarKey, parser); return parser; }