diff --git a/understand-anything-plugin/packages/core/src/__tests__/language-registry.test.ts b/understand-anything-plugin/packages/core/src/__tests__/language-registry.test.ts index 7a3c77495..577dedacf 100644 --- a/understand-anything-plugin/packages/core/src/__tests__/language-registry.test.ts +++ b/understand-anything-plugin/packages/core/src/__tests__/language-registry.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest"; import { LanguageRegistry } from "../languages/language-registry.js"; import { StrictLanguageConfigSchema } from "../languages/types.js"; import { typescriptConfig } from "../languages/configs/typescript.js"; +import { javascriptConfig } from "../languages/configs/javascript.js"; import { pythonConfig } from "../languages/configs/python.js"; describe("LanguageRegistry", () => { @@ -72,6 +73,9 @@ describe("LanguageRegistry", () => { expect(registry.getByExtension(".h")?.id).toBe("c"); expect(registry.getByExtension(".lua")?.id).toBe("lua"); expect(registry.getByExtension(".js")?.id).toBe("javascript"); + expect(registry.getByExtension(".mts")?.id).toBe("typescript"); + expect(registry.getByExtension(".cts")?.id).toBe("typescript"); + expect(registry.getForFile("src/server.mts")?.id).toBe("typescript"); }); it("has no duplicate extension mappings across configs", () => { @@ -93,6 +97,20 @@ describe("LanguageRegistry", () => { }); }); + describe("typescript config test patterns", () => { + it("recognizes both .test.tsx and .spec.tsx test files", () => { + expect(typescriptConfig.filePatterns.tests).toContain("*.test.tsx"); + expect(typescriptConfig.filePatterns.tests).toContain("*.spec.tsx"); + }); + }); + + describe("javascript config test patterns", () => { + it("recognizes .jsx test files for parity with the .tsx patterns", () => { + expect(javascriptConfig.filePatterns.tests).toContain("*.test.jsx"); + expect(javascriptConfig.filePatterns.tests).toContain("*.spec.jsx"); + }); + }); + describe("Non-code language configs", () => { it("detects all non-code file types via extension", () => { const registry = LanguageRegistry.createDefault(); diff --git a/understand-anything-plugin/packages/core/src/languages/configs/javascript.ts b/understand-anything-plugin/packages/core/src/languages/configs/javascript.ts index d89cf4997..851253df8 100644 --- a/understand-anything-plugin/packages/core/src/languages/configs/javascript.ts +++ b/understand-anything-plugin/packages/core/src/languages/configs/javascript.ts @@ -23,7 +23,7 @@ export const javascriptConfig = { filePatterns: { entryPoints: ["index.js", "src/index.js", "main.js"], barrels: ["index.js"], - tests: ["*.test.js", "*.spec.js"], + tests: ["*.test.js", "*.spec.js", "*.test.jsx", "*.spec.jsx"], config: ["package.json", "jsconfig.json"], }, } satisfies LanguageConfig; diff --git a/understand-anything-plugin/packages/core/src/languages/configs/typescript.ts b/understand-anything-plugin/packages/core/src/languages/configs/typescript.ts index 04a884d74..f94246079 100644 --- a/understand-anything-plugin/packages/core/src/languages/configs/typescript.ts +++ b/understand-anything-plugin/packages/core/src/languages/configs/typescript.ts @@ -3,7 +3,12 @@ import type { LanguageConfig } from "../types.js"; export const typescriptConfig = { id: "typescript", displayName: "TypeScript", - extensions: [".ts", ".tsx"], + // Declaration files (.d.ts / .d.mts / .d.cts) are intentionally NOT listed + // separately: getForFile() resolves by the final extension, so they fall + // through to .ts / .mts / .cts and are parsed as ordinary (types-only) + // TypeScript. They carry no runtime exports or call edges, so the extractor + // simply yields an empty call graph for them — no special gating is applied. + extensions: [".ts", ".tsx", ".mts", ".cts"], treeSitter: { wasmPackage: "tree-sitter-typescript", wasmFile: "tree-sitter-typescript.wasm", @@ -24,7 +29,7 @@ export const typescriptConfig = { filePatterns: { entryPoints: ["src/index.ts", "src/main.ts", "src/App.tsx", "index.ts"], barrels: ["index.ts"], - tests: ["*.test.ts", "*.spec.ts", "*.test.tsx"], + tests: ["*.test.ts", "*.spec.ts", "*.test.tsx", "*.spec.tsx"], config: ["tsconfig.json"], }, } satisfies LanguageConfig; diff --git a/understand-anything-plugin/packages/core/src/plugins/tree-sitter-plugin.ts b/understand-anything-plugin/packages/core/src/plugins/tree-sitter-plugin.ts index 65203d255..9c0bc1010 100644 --- a/understand-anything-plugin/packages/core/src/plugins/tree-sitter-plugin.ts +++ b/understand-anything-plugin/packages/core/src/plugins/tree-sitter-plugin.ts @@ -111,7 +111,10 @@ export class TreeSitterPlugin implements AnalyzerPlugin { private languageKeyFromPath(filePath: string): string | null { const ext = extname(filePath).toLowerCase(); - // Special case: .tsx needs its own grammar + // Special case: only .tsx needs the dedicated TSX grammar (it carries JSX). + // .mts / .cts deliberately fall through to the plain TypeScript grammar via + // _extensionToLang — they cannot contain JSX, so do NOT add them to this + // branch by analogy with the .mjs-treated-as-JS pattern. if (ext === ".tsx") return "tsx"; return this._extensionToLang.get(ext) ?? null;