fix(reference-source): recognize Kotlin files in imported inventories

Classify .kt and .kts at the source owner so imported entries and historical language summaries preserve Kotlin identity.

Validation: production inventory projection covers Kotlin, Gradle script, Java and backup-suffix controls.

Based on #3224.

Co-authored-by: Aurantium <280805072+Aurantium-47@users.noreply.github.com>
This commit is contained in:
morluto
2026-10-14 13:58:15 +08:00
parent 576b58cefe
commit 03ffb2c13d
2 changed files with 64 additions and 0 deletions
@@ -0,0 +1,60 @@
import { createHash } from "node:crypto";
import { expect, it } from "vitest";
import { parseReferenceSourceEntries } from "./ReferenceSourceImportEntries.js";
import { historicalSourceLanguages } from "../domain/referenceSourceGraph.js";
import type { ReferenceSourceRead } from "../reference/ReferenceSourceReaderTypes.js";
it("retains Kotlin source identity and language across the inventory projection", () => {
const files = [
[
"MainActivity.kt",
"import android.app.Activity\nclass MainActivity : Activity()\n",
["source"],
"Kotlin",
],
["task.kts", 'println("hello")\n', ["source"], "Kotlin"],
[
"build.gradle.kts",
'plugins { kotlin("jvm") version "2.3.0" }\n',
["manifest", "source"],
"Kotlin",
],
["MainActivity.kt.backup", "backup\n", ["unknown"], null],
["Legacy.java", "class Legacy {}\n", ["source"], "Java"],
] as const;
const read: ReferenceSourceRead = {
root: "/selected/source",
entries: files.map(([path, content]) => ({
status: "read",
kind: "file",
path,
bytes: Buffer.from(content),
size: Buffer.byteLength(content),
})),
bytesRead: files.reduce(
(sum, [, content]) => sum + Buffer.byteLength(content),
0,
),
limitations: [],
};
const parsed = parseReferenceSourceEntries(
read,
new Set(files.map(([path]) => path)),
);
for (const [path, content, classifications, language] of files)
expect(parsed.entries).toContainEqual({
path,
kind: "file",
language,
classifications,
size: Buffer.byteLength(content),
sha256: createHash("sha256").update(content).digest("hex"),
content_state: "hashed",
limitations: [],
});
expect(historicalSourceLanguages(parsed.entries)).toEqual(["Java", "Kotlin"]);
expect(parsed.parseFailures).toEqual([]);
expect(parsed.relationships).toEqual([]);
});
@@ -27,6 +27,8 @@ const CODE_EXTENSIONS = new Set([
"rs",
"go",
"java",
"kt",
"kts",
"c",
"h",
"cpp",
@@ -54,6 +56,8 @@ const LANGUAGE_BY_EXTENSION = new Map<string, string>([
["rs", "Rust"],
["go", "Go"],
["java", "Java"],
["kt", "Kotlin"],
["kts", "Kotlin"],
["c", "C"],
["h", "C"],
["cpp", "C++"],