Fix lines of code mapping

We were inadvertently using codeql language ids instead of the action's
language ids. There is now a 3-way mapping between the ids used by
the lines counter library, the action, and codeql.
This commit is contained in:
Andrew Eisenberg 2021-05-07 09:33:07 -07:00
parent 35a83b92ca
commit b6ae33fbe6
8 changed files with 116 additions and 62 deletions

View file

@ -6,7 +6,7 @@ import * as toolrunner from "@actions/exec/lib/toolrunner";
import * as analysisPaths from "./analysis-paths";
import { getCodeQL } from "./codeql";
import * as configUtils from "./config-utils";
import { countLoc } from "./count-loc";
import { IdPrefixes, countLoc } from "./count-loc";
import { isScannedLanguage, Language } from "./languages";
import { Logger } from "./logging";
import * as sharedEnv from "./shared-environment";
@ -288,7 +288,7 @@ export async function runAnalyze(
async function injectLinesOfCode(
sarifFile: string,
language: string,
locPromise: Promise<Record<string, number>>
locPromise: Promise<Partial<Record<IdPrefixes, number>>>
) {
const lineCounts = await locPromise;
if (language in lineCounts) {

View file

@ -3,6 +3,7 @@ import * as path from "path";
import test from "ava";
import { countLoc } from "./count-loc";
import { Language } from "./languages";
import { getRunnerLogger } from "./logging";
import { setupTests } from "./testing-utils";
@ -13,7 +14,7 @@ test("ensure lines of code works for cpp and js", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"),
[],
[],
["cpp", "js"],
[Language.cpp, Language.javascript],
getRunnerLogger(true)
);
@ -28,12 +29,12 @@ test("ensure lines of code can handle undefined language", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"),
[],
[],
["rb", "py", "hucairz"],
[Language.javascript, Language.python, "hucairz" as Language],
getRunnerLogger(true)
);
t.deepEqual(results, {
rb: 6,
js: 3,
py: 5,
});
});
@ -57,7 +58,7 @@ test("ensure lines of code can handle includes", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"),
["../../src/testdata"],
[],
["js"],
[Language.javascript],
getRunnerLogger(true)
);
@ -71,11 +72,11 @@ test("ensure lines of code can handle exclude", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"),
[],
["**/*.py"],
["rb", "py"],
[Language.javascript, Language.python],
getRunnerLogger(true)
);
t.deepEqual(results, {
rb: 6,
js: 3,
});
});

View file

@ -1,29 +1,59 @@
import { LocDir } from "github-linguist";
import { Language } from "./languages";
import { Logger } from "./logging";
// Map from linguist language names to language prefixes used in our metrics
const supportedLanguages = {
c: "cpp",
"c++": "cpp",
"c#": "cs",
go: "go",
java: "java",
javascript: "js",
python: "py",
ruby: "rb",
typescript: "js",
// Language IDs used by codeql when specifying its metrics.
export type IdPrefixes = "cpp" | "cs" | "go" | "java" | "js" | "py" | "rb";
// Map from linguist language names to language prefixes used in the action and codeql
const linguistToMetrics: Record<
string,
{ name: Language; prefix: IdPrefixes }
> = {
c: {
name: Language.cpp,
prefix: "cpp",
},
"c++": {
name: Language.cpp,
prefix: "cpp",
},
"c#": {
name: Language.csharp,
prefix: "cs",
},
go: {
name: Language.go,
prefix: "go",
},
java: {
name: Language.java,
prefix: "java",
},
javascript: {
name: Language.javascript,
prefix: "js",
},
python: {
name: Language.python,
prefix: "py",
},
typescript: {
name: Language.javascript,
prefix: "js",
},
};
const supportedLanguagesReversed = Object.entries(supportedLanguages).reduce(
(obj, [key, value]) => {
if (!obj[value]) {
obj[value] = [];
const nameToLinguist = Object.entries(linguistToMetrics).reduce(
(obj, [key, { name: action }]) => {
if (!obj[action]) {
obj[action] = [];
}
obj[value].push(key);
obj[action].push(key);
return obj;
},
{}
{} as Record<Language, string[]>
);
/**
@ -40,16 +70,14 @@ export async function countLoc(
cwd: string,
include: string[],
exclude: string[],
dbLanguages: string[],
dbLanguages: Language[],
logger: Logger
): Promise<Record<string, number>> {
): Promise<Partial<Record<IdPrefixes, number>>> {
const result = await new LocDir({
cwd,
include: ["**"].concat(include || []),
exclude,
analysisLanguages: dbLanguages.flatMap(
(lang) => supportedLanguagesReversed[lang]
),
analysisLanguages: dbLanguages.flatMap((lang) => nameToLinguist[lang]),
}).loadInfo();
// The analysis counts LoC in all languages. We need to
@ -57,13 +85,13 @@ export async function countLoc(
// the analysis uses slightly different names for language.
const lineCounts = Object.entries(result.languages).reduce(
(obj, [language, { code }]) => {
const dbLanguage = supportedLanguages[language];
if (dbLanguage && dbLanguages.includes(dbLanguage)) {
obj[dbLanguage] = code + (obj[dbLanguage] || 0);
const metricsLanguage = linguistToMetrics[language];
if (metricsLanguage && dbLanguages.includes(metricsLanguage.name)) {
obj[metricsLanguage.prefix] = code + (obj[metricsLanguage.prefix] || 0);
}
return obj;
},
{} as Record<string, number>
{} as Record<IdPrefixes, number>
);
if (Object.keys(lineCounts).length) {