Skip to content

Commit 327f41f

Browse files
committed
feat(intelligence): expand language detection coverage
1 parent 846d7fd commit 327f41f

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

src/intelligence/repository/profile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { RepositoryProfile, StackDetection } from "../../core/domain/repository-context.js";
22
import type { RepoSnapshot } from "../../core/domain/repository-snapshot.js";
33

4-
const LANGUAGE_EXTENSIONS = new Map([[".ts", "TypeScript"], [".tsx", "TypeScript"], [".js", "JavaScript"], [".jsx", "JavaScript"], [".py", "Python"], [".go", "Go"], [".rs", "Rust"]]);
4+
const LANGUAGE_EXTENSIONS = new Map([[".ts", "TypeScript"], [".tsx", "TypeScript"], [".js", "JavaScript"], [".jsx", "JavaScript"], [".py", "Python"], [".go", "Go"], [".rs", "Rust"], [".java", "Java"], [".rb", "Ruby"], [".php", "PHP"]]);
55
function extensionOf(path: string): string { return path.match(/\.[^.\/]+$/u)?.[0] ?? ""; }
66
function hasPath(repo: RepoSnapshot, predicate: (path: string) => boolean): boolean { return repo.files.some((file) => predicate(file.path.toLowerCase())); }
77

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, it } from "vitest";
2+
import { detectStack } from "../../src/intelligence/frameworks/detect-stack.js";
3+
import { buildRepositoryProfile } from "../../src/intelligence/repository/profile.js";
4+
import type { RepoSnapshot } from "../../src/core/domain/repository-snapshot.js";
5+
import { taintUntrusted } from "../../src/core/domain/trust.js";
6+
7+
function repoWith(paths: string[]): RepoSnapshot {
8+
return {
9+
ref: { name: "fixture", defaultBranch: "main" },
10+
capped: false,
11+
files: paths.map((path) => ({ path, content: taintUntrusted("") }))
12+
};
13+
}
14+
15+
function primaryLanguage(repo: RepoSnapshot): string {
16+
return buildRepositoryProfile(repo, detectStack(repo)).languages[0]?.name ?? "unknown";
17+
}
18+
19+
describe("language detection coverage", () => {
20+
it("detects Python from .py files", () => {
21+
expect(primaryLanguage(repoWith(["main.py", "src/utils/helpers.py"]))).toBe("Python");
22+
});
23+
24+
it("detects Go from .go files", () => {
25+
expect(primaryLanguage(repoWith(["main.go", "internal/server.go"]))).toBe("Go");
26+
});
27+
28+
it("detects Java from .java files", () => {
29+
expect(primaryLanguage(repoWith(["src/Main.java", "src/Service.java"]))).toBe("Java");
30+
});
31+
32+
it("detects Ruby from .rb files", () => {
33+
expect(primaryLanguage(repoWith(["app.rb", "lib/parser.rb"]))).toBe("Ruby");
34+
});
35+
36+
it("detects PHP from .php files", () => {
37+
expect(primaryLanguage(repoWith(["index.php", "src/Controller.php"]))).toBe("PHP");
38+
});
39+
40+
it("detects Rust from .rs files", () => {
41+
expect(primaryLanguage(repoWith(["src/main.rs", "src/lib.rs"]))).toBe("Rust");
42+
});
43+
44+
it("keeps existing TypeScript detection unchanged", () => {
45+
expect(primaryLanguage(repoWith(["src/index.ts", "src/app.tsx"]))).toBe("TypeScript");
46+
});
47+
48+
it("keeps existing JavaScript detection unchanged", () => {
49+
expect(primaryLanguage(repoWith(["index.js", "src/app.jsx"]))).toBe("JavaScript");
50+
});
51+
52+
it("returns unknown when no recognized source files exist", () => {
53+
expect(primaryLanguage(repoWith(["NOTES.txt", "data.csv"]))).toBe("unknown");
54+
});
55+
56+
it("ranks the dominant language first in a mixed repo", () => {
57+
const profile = buildRepositoryProfile(repoWith(["a.py", "b.py", "c.py", "x.rb"]), detectStack(repoWith(["a.py", "b.py", "c.py", "x.rb"])));
58+
expect(profile.languages[0]?.name).toBe("Python");
59+
expect(profile.languages.map((language) => language.name)).toContain("Ruby");
60+
});
61+
});

0 commit comments

Comments
 (0)