diff --git a/lib/analyze-action.js.map b/lib/analyze-action.js.map index 5170853244..72604e6bbc 100644 --- a/lib/analyze-action.js.map +++ b/lib/analyze-action.js.map @@ -1 +1 @@ -{"version":3,"file":"analyze-action.js","sourceRoot":"","sources":["../src/analyze-action.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"analyze-action.js","sourceRoot":"","sources":["../src/analyze-action.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/analyze.js b/lib/analyze.js index 98e04d31ba..d849c025ff 100644 --- a/lib/analyze.js +++ b/lib/analyze.js @@ -12,6 +12,7 @@ const path = __importStar(require("path")); const toolrunner = __importStar(require("@actions/exec/lib/toolrunner")); const analysisPaths = __importStar(require("./analysis-paths")); const codeql_1 = require("./codeql"); +const count_loc_1 = require("./count-loc"); const languages_1 = require("./languages"); const sharedEnv = __importStar(require("./shared-environment")); const upload_lib_1 = require("./upload-lib"); @@ -77,6 +78,12 @@ async function finalizeDatabaseCreation(config, threadsFlag, logger) { // Runs queries and creates sarif files in the given folder async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, config, logger) { const statusReport = {}; + // count the number of lines in the background + const locPromise = count_loc_1.countLoc(path.resolve(), + // config.paths specifies external directories. the current + // directory is included in the analysis by default. Replicate + // that here. + ["**"].concat(config.paths || []), config.pathsIgnore, config.languages, logger); for (const language of config.languages) { logger.startGroup(`Analyzing ${language}`); const queries = config.queries[language]; @@ -86,7 +93,8 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, try { if (queries["builtin"].length > 0) { const startTimeBuliltIn = new Date().getTime(); - await runQueryGroup(language, "builtin", queries["builtin"], sarifFolder, undefined); + const sarifFile = await runQueryGroup(language, "builtin", queries["builtin"], sarifFolder, undefined); + await injectLinesOfCode(sarifFile, language, locPromise); statusReport[`analyze_builtin_queries_${language}_duration_ms`] = new Date().getTime() - startTimeBuliltIn; } @@ -95,12 +103,14 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, const temporarySarifFiles = []; for (let i = 0; i < queries["custom"].length; ++i) { if (queries["custom"][i].queries.length > 0) { - await runQueryGroup(language, `custom-${i}`, queries["custom"][i].queries, temporarySarifDir, queries["custom"][i].searchPath); - temporarySarifFiles.push(path.join(temporarySarifDir, `${language}-custom-${i}.sarif`)); + const sarifFile = await runQueryGroup(language, `custom-${i}`, queries["custom"][i].queries, temporarySarifDir, queries["custom"][i].searchPath); + temporarySarifFiles.push(sarifFile); } } if (temporarySarifFiles.length > 0) { - fs.writeFileSync(path.join(sarifFolder, `${language}-custom.sarif`), upload_lib_1.combineSarifFiles(temporarySarifFiles)); + const sarifFile = path.join(sarifFolder, `${language}-custom.sarif`); + fs.writeFileSync(sarifFile, upload_lib_1.combineSarifFiles(temporarySarifFiles)); + await injectLinesOfCode(sarifFile, language, locPromise); statusReport[`analyze_custom_queries_${language}_duration_ms`] = new Date().getTime() - startTimeCustom; } @@ -127,6 +137,7 @@ async function runQueries(sarifFolder, memoryFlag, addSnippetsFlag, threadsFlag, await codeql.databaseAnalyze(databasePath, sarifFile, searchPath, querySuitePath, memoryFlag, addSnippetsFlag, threadsFlag); logger.debug(`SARIF results for database ${language} created at "${sarifFile}"`); logger.endGroup(); + return sarifFile; } } exports.runQueries = runQueries; @@ -141,4 +152,25 @@ async function runAnalyze(outputDir, memoryFlag, addSnippetsFlag, threadsFlag, c return { ...queriesStats }; } exports.runAnalyze = runAnalyze; +async function injectLinesOfCode(sarifFile, language, locPromise) { + const lineCounts = await locPromise; + if (language in lineCounts) { + const sarif = JSON.parse(fs.readFileSync(sarifFile, "utf8")); + if (Array.isArray(sarif.runs)) { + for (const run of sarif.runs) { + const metricId = `${language}/summary/lines-of-code`; + run.properties = run.properties || {}; + run.properties.metricResults = run.properties.metricResults || []; + const metric = run.properties.metricResults.find( + // the metric id can be in either of two places + (m) => { var _a; return m.metricId === metricId || ((_a = m.metric) === null || _a === void 0 ? void 0 : _a.id) === metricId; }); + // only add the baseline value if the metric already exists + if (metric) { + metric.baseline = lineCounts[language]; + } + } + } + fs.writeFileSync(sarifFile, JSON.stringify(sarif)); + } +} //# sourceMappingURL=analyze.js.map \ No newline at end of file diff --git a/lib/analyze.js.map b/lib/analyze.js.map index eb368aacc7..c9e55b4c24 100644 --- a/lib/analyze.js.map +++ b/lib/analyze.js.map @@ -1 +1 @@ -{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/analyze.test.js b/lib/analyze.test.js index c249a4b4ca..08ced2299f 100644 --- a/lib/analyze.test.js +++ b/lib/analyze.test.js @@ -11,9 +11,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); +const path = __importStar(require("path")); const ava_1 = __importDefault(require("ava")); +const sinon_1 = __importDefault(require("sinon")); const analyze_1 = require("./analyze"); const codeql_1 = require("./codeql"); +const count = __importStar(require("./count-loc")); const languages_1 = require("./languages"); const logging_1 = require("./logging"); const testing_utils_1 = require("./testing-utils"); @@ -23,21 +26,53 @@ testing_utils_1.setupTests(ava_1.default); // and correct case of builtin or custom. Also checks the correct search // paths are set in the database analyze invocation. ava_1.default("status report fields and search path setting", async (t) => { + const mockLinesOfCode = Object.entries(languages_1.Language).reduce((obj, [lang], i) => { + // use a different line count for each languaged + obj[lang] = i + 1; + return obj; + }, {}); + sinon_1.default.stub(count, "countLoc").resolves(mockLinesOfCode); let searchPathsUsed = []; return await util.withTmpDir(async (tmpDir) => { testing_utils_1.setupActionsVars(tmpDir, tmpDir); - codeql_1.setCodeQL({ - databaseAnalyze: async (_, sarifFile, searchPath) => { - fs.writeFileSync(sarifFile, JSON.stringify({ - runs: [], - })); - searchPathsUsed.push(searchPath); - }, - }); const memoryFlag = ""; const addSnippetsFlag = ""; const threadsFlag = ""; for (const language of Object.values(languages_1.Language)) { + codeql_1.setCodeQL({ + databaseAnalyze: async (_, sarifFile, searchPath) => { + fs.writeFileSync(sarifFile, JSON.stringify({ + runs: [ + // variant 1 uses metricId + { + properties: { + metricResults: [ + { + metricId: `${language}/summary/lines-of-code`, + value: 123, + }, + ], + }, + }, + // variant 2 uses metric.id + { + properties: { + metricResults: [ + { + metric: { + id: `${language}/summary/lines-of-code`, + }, + value: 123, + }, + ], + }, + }, + {}, + ], + })); + searchPathsUsed.push(searchPath); + }, + }); searchPathsUsed = []; const config = { languages: [language], @@ -80,6 +115,35 @@ ava_1.default("status report fields and search path setting", async (t) => { t.true(`analyze_custom_queries_${language}_duration_ms` in customStatusReport); t.deepEqual(searchPathsUsed, [undefined, "/1", "/2"]); } + verifyLineCounts(tmpDir); }); + function verifyLineCounts(tmpDir) { + // eslint-disable-next-line github/array-foreach + Object.keys(languages_1.Language).forEach((lang, i) => { + verifyLineCountForFile(lang, path.join(tmpDir, `${lang}-builtin.sarif`), i + 1); + verifyLineCountForFile(lang, path.join(tmpDir, `${lang}-custom.sarif`), i + 1); + }); + } + function verifyLineCountForFile(lang, filePath, lineCount) { + const sarif = JSON.parse(fs.readFileSync(filePath, "utf8")); + t.deepEqual(sarif.runs[0].properties.metricResults, [ + { + metricId: `${lang}/summary/lines-of-code`, + value: 123, + baseline: lineCount, + }, + ]); + t.deepEqual(sarif.runs[1].properties.metricResults, [ + { + metric: { + id: `${lang}/summary/lines-of-code`, + }, + value: 123, + baseline: lineCount, + }, + ]); + // when the metric doesn't exists, it should not be added + t.deepEqual(sarif.runs[2].properties.metricResults, []); + } }); //# sourceMappingURL=analyze.test.js.map \ No newline at end of file diff --git a/lib/analyze.test.js.map b/lib/analyze.test.js.map index 3cb0e3ed55..20abc479d2 100644 --- a/lib/analyze.test.js.map +++ b/lib/analyze.test.js.map @@ -1 +1 @@ -{"version":3,"file":"analyze.test.js","sourceRoot":"","sources":["../src/analyze.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"analyze.test.js","sourceRoot":"","sources":["../src/analyze.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/count-loc.js b/lib/count-loc.js new file mode 100644 index 0000000000..ad51fa0a31 --- /dev/null +++ b/lib/count-loc.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const github_linguist_1 = require("github-linguist"); +// 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", +}; +/** + * Count the lines of code of the specified language using the include + * and exclude glob paths. + * + * @param cwd the root directory to start the count from + * @param include glob patterns to include in the search for relevant files + * @param exclude glob patterns to exclude in the search for relevant files + * @param dbLanguages list of languages to include in the results + * @param logger object to log results + */ +async function countLoc(cwd, include, exclude, dbLanguages, logger) { + const result = await new github_linguist_1.LocDir({ + cwd, + include, + exclude, + }).loadInfo(); + // The analysis counts LoC in all languages. We need to + // extract the languages we care about. Also, note that + // 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); + } + return obj; + }, {}); + if (Object.keys(lineCounts).length) { + logger.debug("Lines of code count:"); + for (const [language, count] of Object.entries(lineCounts)) { + logger.debug(` ${language}: ${count}`); + } + } + else { + logger.warning("Did not find any lines of code in database."); + } + return lineCounts; +} +exports.countLoc = countLoc; +//# sourceMappingURL=count-loc.js.map \ No newline at end of file diff --git a/lib/count-loc.js.map b/lib/count-loc.js.map new file mode 100644 index 0000000000..0bb658ae4a --- /dev/null +++ b/lib/count-loc.js.map @@ -0,0 +1 @@ +{"version":3,"file":"count-loc.js","sourceRoot":"","sources":["../src/count-loc.ts"],"names":[],"mappings":";;AAAA,qDAAyC;AAIzC,4EAA4E;AAC5E,MAAM,kBAAkB,GAAG;IACzB,CAAC,EAAE,KAAK;IACR,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,IAAI;IACV,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF;;;;;;;;;GASG;AACI,KAAK,UAAU,QAAQ,CAC5B,GAAW,EACX,OAAiB,EACjB,OAAiB,EACjB,WAAqB,EACrB,MAAc;IAEd,MAAM,MAAM,GAAG,MAAM,IAAI,wBAAM,CAAC;QAC9B,GAAG;QACH,OAAO;QACP,OAAO;KACR,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEd,uDAAuD;IACvD,uDAAuD;IACvD,2DAA2D;IAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CACxD,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,UAAU,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;YAClD,GAAG,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;SACjD;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAA4B,CAC7B,CAAC;IAEF,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE;QAClC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACrC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAC1D,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;SACzC;KACF;SAAM;QACL,MAAM,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;KAC/D;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AArCD,4BAqCC"} \ No newline at end of file diff --git a/src/analyze-action.ts b/src/analyze-action.ts index e29c8ca7e7..7d3591d814 100644 --- a/src/analyze-action.ts +++ b/src/analyze-action.ts @@ -69,6 +69,7 @@ async function run() { "Config file could not be found at expected location. Has the 'init' action been called?" ); } + const apiDetails = { auth: actionsUtil.getRequiredInput("token"), url: actionsUtil.getRequiredEnvParam("GITHUB_SERVER_URL"), diff --git a/src/analyze.test.ts b/src/analyze.test.ts index 7f6ca09129..c1ced4ba16 100644 --- a/src/analyze.test.ts +++ b/src/analyze.test.ts @@ -1,10 +1,13 @@ import * as fs from "fs"; +import * as path from "path"; import test from "ava"; +import sinon from "sinon"; import { runQueries } from "./analyze"; import { setCodeQL } from "./codeql"; import { Config } from "./config-utils"; +import * as count from "./count-loc"; import { Language } from "./languages"; import { getRunnerLogger } from "./logging"; import { setupTests, setupActionsVars } from "./testing-utils"; @@ -16,31 +19,63 @@ setupTests(test); // and correct case of builtin or custom. Also checks the correct search // paths are set in the database analyze invocation. test("status report fields and search path setting", async (t) => { + const mockLinesOfCode = Object.entries(Language).reduce((obj, [lang], i) => { + // use a different line count for each languaged + obj[lang] = i + 1; + return obj; + }, {}); + sinon.stub(count, "countLoc").resolves(mockLinesOfCode); let searchPathsUsed: string[] = []; return await util.withTmpDir(async (tmpDir) => { setupActionsVars(tmpDir, tmpDir); - setCodeQL({ - databaseAnalyze: async ( - _, - sarifFile: string, - searchPath: string | undefined - ) => { - fs.writeFileSync( - sarifFile, - JSON.stringify({ - runs: [], - }) - ); - searchPathsUsed.push(searchPath!); - }, - }); - const memoryFlag = ""; const addSnippetsFlag = ""; const threadsFlag = ""; for (const language of Object.values(Language)) { + setCodeQL({ + databaseAnalyze: async ( + _, + sarifFile: string, + searchPath: string | undefined + ) => { + fs.writeFileSync( + sarifFile, + JSON.stringify({ + runs: [ + // variant 1 uses metricId + { + properties: { + metricResults: [ + { + metricId: `${language}/summary/lines-of-code`, + value: 123, + }, + ], + }, + }, + // variant 2 uses metric.id + { + properties: { + metricResults: [ + { + metric: { + id: `${language}/summary/lines-of-code`, + }, + value: 123, + }, + ], + }, + }, + {}, + ], + }) + ); + searchPathsUsed.push(searchPath!); + }, + }); + searchPathsUsed = []; const config: Config = { languages: [language], @@ -103,5 +138,49 @@ test("status report fields and search path setting", async (t) => { ); t.deepEqual(searchPathsUsed, [undefined, "/1", "/2"]); } + + verifyLineCounts(tmpDir); }); + + function verifyLineCounts(tmpDir: string) { + // eslint-disable-next-line github/array-foreach + Object.keys(Language).forEach((lang, i) => { + verifyLineCountForFile( + lang, + path.join(tmpDir, `${lang}-builtin.sarif`), + i + 1 + ); + verifyLineCountForFile( + lang, + path.join(tmpDir, `${lang}-custom.sarif`), + i + 1 + ); + }); + } + + function verifyLineCountForFile( + lang: string, + filePath: string, + lineCount: number + ) { + const sarif = JSON.parse(fs.readFileSync(filePath, "utf8")); + t.deepEqual(sarif.runs[0].properties.metricResults, [ + { + metricId: `${lang}/summary/lines-of-code`, + value: 123, + baseline: lineCount, + }, + ]); + t.deepEqual(sarif.runs[1].properties.metricResults, [ + { + metric: { + id: `${lang}/summary/lines-of-code`, + }, + value: 123, + baseline: lineCount, + }, + ]); + // when the metric doesn't exists, it should not be added + t.deepEqual(sarif.runs[2].properties.metricResults, []); + } }); diff --git a/src/analyze.ts b/src/analyze.ts index eef84810c6..ce796cde30 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -6,6 +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 { isScannedLanguage, Language } from "./languages"; import { Logger } from "./logging"; import * as sharedEnv from "./shared-environment"; @@ -144,6 +145,18 @@ export async function runQueries( ): Promise { const statusReport: QueriesStatusReport = {}; + // count the number of lines in the background + const locPromise = countLoc( + path.resolve(), + // config.paths specifies external directories. the current + // directory is included in the analysis by default. Replicate + // that here. + ["**"].concat(config.paths || []), + config.pathsIgnore, + config.languages, + logger + ); + for (const language of config.languages) { logger.startGroup(`Analyzing ${language}`); @@ -157,13 +170,15 @@ export async function runQueries( try { if (queries["builtin"].length > 0) { const startTimeBuliltIn = new Date().getTime(); - await runQueryGroup( + const sarifFile = await runQueryGroup( language, "builtin", queries["builtin"], sarifFolder, undefined ); + await injectLinesOfCode(sarifFile, language, locPromise); + statusReport[`analyze_builtin_queries_${language}_duration_ms`] = new Date().getTime() - startTimeBuliltIn; } @@ -172,23 +187,21 @@ export async function runQueries( const temporarySarifFiles: string[] = []; for (let i = 0; i < queries["custom"].length; ++i) { if (queries["custom"][i].queries.length > 0) { - await runQueryGroup( + const sarifFile = await runQueryGroup( language, `custom-${i}`, queries["custom"][i].queries, temporarySarifDir, queries["custom"][i].searchPath ); - temporarySarifFiles.push( - path.join(temporarySarifDir, `${language}-custom-${i}.sarif`) - ); + temporarySarifFiles.push(sarifFile); } } if (temporarySarifFiles.length > 0) { - fs.writeFileSync( - path.join(sarifFolder, `${language}-custom.sarif`), - combineSarifFiles(temporarySarifFiles) - ); + const sarifFile = path.join(sarifFolder, `${language}-custom.sarif`); + fs.writeFileSync(sarifFile, combineSarifFiles(temporarySarifFiles)); + await injectLinesOfCode(sarifFile, language, locPromise); + statusReport[`analyze_custom_queries_${language}_duration_ms`] = new Date().getTime() - startTimeCustom; } @@ -210,7 +223,7 @@ export async function runQueries( queries: string[], destinationFolder: string, searchPath: string | undefined - ): Promise { + ): Promise { const databasePath = util.getCodeQLDatabasePath(config.tempDir, language); // Pass the queries to codeql using a file instead of using the command // line to avoid command line length restrictions, particularly on windows. @@ -238,6 +251,8 @@ export async function runQueries( `SARIF results for database ${language} created at "${sarifFile}"` ); logger.endGroup(); + + return sarifFile; } } @@ -269,3 +284,30 @@ export async function runAnalyze( return { ...queriesStats }; } + +async function injectLinesOfCode( + sarifFile: string, + language: string, + locPromise: Promise> +) { + const lineCounts = await locPromise; + if (language in lineCounts) { + const sarif = JSON.parse(fs.readFileSync(sarifFile, "utf8")); + if (Array.isArray(sarif.runs)) { + for (const run of sarif.runs) { + const metricId = `${language}/summary/lines-of-code`; + run.properties = run.properties || {}; + run.properties.metricResults = run.properties.metricResults || []; + const metric = run.properties.metricResults.find( + // the metric id can be in either of two places + (m) => m.metricId === metricId || m.metric?.id === metricId + ); + // only add the baseline value if the metric already exists + if (metric) { + metric.baseline = lineCounts[language]; + } + } + } + fs.writeFileSync(sarifFile, JSON.stringify(sarif)); + } +} diff --git a/src/count-loc.ts b/src/count-loc.ts new file mode 100644 index 0000000000..ecb8ab368b --- /dev/null +++ b/src/count-loc.ts @@ -0,0 +1,65 @@ +import { LocDir } from "github-linguist"; + +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", +}; + +/** + * Count the lines of code of the specified language using the include + * and exclude glob paths. + * + * @param cwd the root directory to start the count from + * @param include glob patterns to include in the search for relevant files + * @param exclude glob patterns to exclude in the search for relevant files + * @param dbLanguages list of languages to include in the results + * @param logger object to log results + */ +export async function countLoc( + cwd: string, + include: string[], + exclude: string[], + dbLanguages: string[], + logger: Logger +): Promise> { + const result = await new LocDir({ + cwd, + include, + exclude, + }).loadInfo(); + + // The analysis counts LoC in all languages. We need to + // extract the languages we care about. Also, note that + // 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); + } + return obj; + }, + {} as Record + ); + + if (Object.keys(lineCounts).length) { + logger.debug("Lines of code count:"); + for (const [language, count] of Object.entries(lineCounts)) { + logger.debug(` ${language}: ${count}`); + } + } else { + logger.warning("Did not find any lines of code in database."); + } + + return lineCounts; +}