diff --git a/src/analyze.test.ts b/src/analyze.test.ts index c73159d1fe..0d0a48d18e 100644 --- a/src/analyze.test.ts +++ b/src/analyze.test.ts @@ -10,7 +10,7 @@ import { runQueries } from "./analyze"; import { setCodeQL } from "./codeql"; import { Config } from "./config-utils"; import * as count from "./count-loc"; -import { Language } from "./languages"; +import { KnownLanguage } from "./languages"; import { getRunnerLogger } from "./logging"; import { setupTests, setupActionsVars } from "./testing-utils"; import * as util from "./util"; @@ -21,8 +21,8 @@ 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.values(Language).reduce((obj, lang, i) => { - // use a different line count for each language + const mockLinesOfCode = Object.values(KnownLanguage).reduce((obj, lang, i) => { + // use a different line count for each KnownLanguage obj[lang] = i + 1; return obj; }, {}); @@ -35,13 +35,13 @@ test("status report fields and search path setting", async (t) => { const addSnippetsFlag = ""; const threadsFlag = ""; const packs = { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: clean("1.0.0")!, }, ], - [Language.java]: [ + [KnownLanguage.java]: [ { packName: "c/d", version: clean("2.0.0")!, @@ -49,7 +49,7 @@ test("status report fields and search path setting", async (t) => { ], }; - for (const language of Object.values(Language)) { + for (const language of Object.values(KnownLanguage)) { setCodeQL({ packDownload: async () => ({ packs: [] }), databaseRunQueries: async ( @@ -203,7 +203,7 @@ test("status report fields and search path setting", async (t) => { function verifyLineCounts(tmpDir: string) { // eslint-disable-next-line github/array-foreach - Object.keys(Language).forEach((lang, i) => { + Object.keys(KnownLanguage).forEach((lang, i) => { verifyLineCountForFile(path.join(tmpDir, `${lang}.sarif`), i + 1); }); } @@ -249,14 +249,14 @@ test("status report fields and search path setting", async (t) => { version: "2.0.0", }, ]; - for (const lang of Object.values(Language)) { + for (const lang of Object.values(KnownLanguage)) { t.deepEqual(readContents(`${lang}-queries-builtin.qls`), qlsContent); t.deepEqual(readContents(`${lang}-queries-custom-0.qls`), qlsContent); t.deepEqual(readContents(`${lang}-queries-custom-1.qls`), qlsContent2); const packSuiteName = `${lang}-queries-packs.qls`; - if (lang === Language.cpp) { + if (lang === KnownLanguage.cpp) { t.deepEqual(readContents(packSuiteName), qlsPackContentCpp); - } else if (lang === Language.java) { + } else if (lang === KnownLanguage.java) { t.deepEqual(readContents(packSuiteName), qlsPackContentJava); } else { t.false( diff --git a/src/analyze.ts b/src/analyze.ts index 422df5eea9..5df4b7b85f 100644 --- a/src/analyze.ts +++ b/src/analyze.ts @@ -8,7 +8,7 @@ import * as analysisPaths from "./analysis-paths"; import { CODEQL_VERSION_COUNTS_LINES, getCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; import { countLoc } from "./count-loc"; -import { isScannedLanguage, Language } from "./languages"; +import { isScannedLanguage, KnownLanguage, Language } from "./languages"; import { Logger } from "./logging"; import * as sharedEnv from "./shared-environment"; import * as util from "./util"; @@ -124,7 +124,7 @@ async function createdDBForScannedLanguages( ) { logger.startGroup(`Extracting ${language}`); - if (language === Language.python) { + if (language === KnownLanguage.python) { await setupPythonExtractor(logger); } diff --git a/src/config-utils.test.ts b/src/config-utils.test.ts index 6a6ae6d300..1e82249f61 100644 --- a/src/config-utils.test.ts +++ b/src/config-utils.test.ts @@ -9,7 +9,7 @@ import * as sinon from "sinon"; import * as api from "./api-client"; import { getCachedCodeQL, setCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; -import { Language } from "./languages"; +import { KnownLanguage, Language } from "./languages"; import { getRunnerLogger } from "./logging"; import { setupTests } from "./testing-utils"; import * as util from "./util"; @@ -299,7 +299,7 @@ test("load non-empty input", async (t) => { // And the config we expect it to parse to const expectedConfig: configUtils.Config = { - languages: [Language.javascript], + languages: [KnownLanguage.javascript], queries: { javascript: { builtin: [], @@ -974,7 +974,7 @@ test("No detected languages", async (t) => { }); }); -test("Unknown languages", async (t) => { +test("Unknown, unsupported languages", async (t) => { return await util.withTmpDir(async (tmpDir) => { const languages = "rubbish,english"; @@ -998,7 +998,77 @@ test("Unknown languages", async (t) => { } catch (err) { t.deepEqual( err, - new Error(configUtils.getUnknownLanguagesError(["rubbish", "english"])) + new Error( + configUtils.getUnsupportedLanguagesError(["rubbish", "english"]) + ) + ); + } + }); +}); + +test("Unknown, supported languages", async (t) => { + return await util.withTmpDir(async (tmpDir) => { + const languages = "ql"; + + const codeQL = setCodeQL({ + async resolveLanguages() { + return { + ql: ["/tmp/ql-for-ql-pack"], + }; + }, + }); + + let config: configUtils.Config = await configUtils.initConfig( + languages, + undefined, + undefined, + undefined, + undefined, + { owner: "github", repo: "example " }, + tmpDir, + tmpDir, + codeQL, + tmpDir, + gitHubVersion, + sampleApiDetails, + getRunnerLogger(true) + ); + t.deepEqual(config.languages, ["ql"]); + }); +}); + +test("Partially supported languages", async (t) => { + return await util.withTmpDir(async (tmpDir) => { + const languages = "rubbish,ql"; + + const codeQL = setCodeQL({ + async resolveLanguages() { + return { + ql: ["/tmp/ql-for-ql-pack"], + }; + }, + }); + try { + await configUtils.initConfig( + languages, + undefined, + undefined, + undefined, + undefined, + { owner: "github", repo: "example " }, + tmpDir, + tmpDir, + codeQL, + tmpDir, + gitHubVersion, + sampleApiDetails, + getRunnerLogger(true) + ); + throw new Error("initConfig did not throw error"); + } catch (err) { + t.deepEqual( + err, + new Error(configUtils.getUnsupportedLanguagesError(["rubbish"])) ); } }); @@ -1044,7 +1114,7 @@ test("Config specifies packages", async (t) => { getRunnerLogger(true) ); t.deepEqual(packs as unknown, { - [Language.javascript]: [ + [KnownLanguage.javascript]: [ { packName: "a/b", version: clean("1.2.3"), @@ -1102,13 +1172,13 @@ test("Config specifies packages for multiple languages", async (t) => { getRunnerLogger(true) ); t.deepEqual(packs as unknown, { - [Language.javascript]: [ + [KnownLanguage.javascript]: [ { packName: "a/b", version: clean("1.2.3"), }, ], - [Language.python]: [ + [KnownLanguage.python]: [ { packName: "c/d", version: clean("1.2.3"), @@ -1377,8 +1447,8 @@ parsePacksErrorMacro.title = (providedTitle: string) => function invalidPackNameMacro(t: ExecutionContext, name: string) { parsePacksErrorMacro( t, - { [Language.cpp]: [name] }, - [Language.cpp], + { [KnownLanguage.cpp]: [name] }, + [KnownLanguage.cpp], new RegExp( `The configuration file "/a/b" is invalid: property "packs" "${name}" is not a valid pack` ) @@ -1388,8 +1458,8 @@ invalidPackNameMacro.title = (_: string, arg: string) => `Invalid pack string: ${arg}`; test("no packs", parsePacksMacro, {}, [], {}); -test("two packs", parsePacksMacro, ["a/b", "c/d@1.2.3"], [Language.cpp], { - [Language.cpp]: [ +test("two packs", parsePacksMacro, ["a/b", "c/d@1.2.3"], [KnownLanguage.cpp], { + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: clean("1.2.3") }, ], @@ -1398,9 +1468,9 @@ test( "two packs with spaces", parsePacksMacro, [" a/b ", " c/d@1.2.3 "], - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: clean("1.2.3") }, ], @@ -1410,16 +1480,16 @@ test( "two packs with language", parsePacksMacro, { - [Language.cpp]: ["a/b", "c/d@1.2.3"], - [Language.java]: ["d/e", "f/g@1.2.3"], + [KnownLanguage.cpp]: ["a/b", "c/d@1.2.3"], + [KnownLanguage.java]: ["d/e", "f/g@1.2.3"], }, - [Language.cpp, Language.java, Language.csharp], + [KnownLanguage.cpp, KnownLanguage.java, KnownLanguage.csharp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: clean("1.2.3") }, ], - [Language.java]: [ + [KnownLanguage.java]: [ { packName: "d/e", version: undefined }, { packName: "f/g", version: clean("1.2.3") }, ], @@ -1430,21 +1500,21 @@ test( "no language", parsePacksErrorMacro, ["a/b@1.2.3"], - [Language.java, Language.python], + [KnownLanguage.java, KnownLanguage.python], /The configuration file "\/a\/b" is invalid: property "packs" must split packages by language/ ); test( "invalid language", parsePacksErrorMacro, - { [Language.java]: ["c/d"] }, - [Language.cpp], + { [KnownLanguage.java]: ["c/d"] }, + [KnownLanguage.cpp], /The configuration file "\/a\/b" is invalid: property "packs" has "java", but it is not one of the languages to analyze/ ); test( "not an array", parsePacksErrorMacro, - { [Language.cpp]: "c/d" }, - [Language.cpp], + { [KnownLanguage.cpp]: "c/d" }, + [KnownLanguage.cpp], /The configuration file "\/a\/b" is invalid: property "packs" must be an array of non-empty strings/ ); @@ -1496,8 +1566,8 @@ function parseInputAndConfigErrorMacro( parseInputAndConfigErrorMacro.title = (providedTitle: string) => `Parse Packs input and config Error: ${providedTitle}`; -test("input only", parseInputAndConfigMacro, {}, " c/d ", [Language.cpp], { - [Language.cpp]: [{ packName: "c/d", version: undefined }], +test("input only", parseInputAndConfigMacro, {}, " c/d ", [KnownLanguage.cpp], { + [KnownLanguage.cpp]: [{ packName: "c/d", version: undefined }], }); test( @@ -1505,9 +1575,9 @@ test( parseInputAndConfigMacro, {}, "a/b , c/d@1.2.3", - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: "1.2.3" }, ], @@ -1519,9 +1589,9 @@ test( parseInputAndConfigMacro, {}, " + a/b , c/d@1.2.3 ", - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: "1.2.3" }, ], @@ -1533,9 +1603,9 @@ test( parseInputAndConfigMacro, ["a/b", "c/d"], " ", - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "a/b", version: undefined }, { packName: "c/d", version: undefined }, ], @@ -1547,9 +1617,9 @@ test( parseInputAndConfigMacro, ["a/b", "c/d"], " e/f, g/h@1.2.3 ", - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "e/f", version: undefined }, { packName: "g/h", version: "1.2.3" }, ], @@ -1561,9 +1631,9 @@ test( parseInputAndConfigMacro, ["a/b", "c/d"], " +e/f, g/h@1.2.3 ", - [Language.cpp], + [KnownLanguage.cpp], { - [Language.cpp]: [ + [KnownLanguage.cpp]: [ { packName: "e/f", version: undefined }, { packName: "g/h", version: "1.2.3" }, { packName: "a/b", version: undefined }, @@ -1586,7 +1656,7 @@ test( parseInputAndConfigErrorMacro, {}, "c/d", - [Language.cpp, Language.csharp], + [KnownLanguage.cpp, KnownLanguage.csharp], /multi-language analysis/ ); @@ -1595,7 +1665,7 @@ test( parseInputAndConfigErrorMacro, {}, " + ", - [Language.cpp], + [KnownLanguage.cpp], /remove the '\+'/ ); @@ -1604,7 +1674,7 @@ test( parseInputAndConfigErrorMacro, {}, " xxx", - [Language.cpp], + [KnownLanguage.cpp], /"xxx" is not a valid pack/ ); diff --git a/src/config-utils.ts b/src/config-utils.ts index c0881314f1..909946a5f7 100644 --- a/src/config-utils.ts +++ b/src/config-utils.ts @@ -673,8 +673,8 @@ export function getNoLanguagesError(): string { ); } -export function getUnknownLanguagesError(languages: string[]): string { - return `Did not recognise the following languages: ${languages.join(", ")}`; +export function getUnsupportedLanguagesError(languages: string[]): string { + return `Does not support the following languages: ${languages.join(", ")}`; } /** @@ -714,8 +714,10 @@ async function getLanguagesInRepo( * has been set, otherwise it is deduced as all languages in the repo that * can be analysed. * - * If no languages could be detected from either the workflow or the repository + * If no supported languages could be detected from either the workflow or the repository * then throw an error. + * + * The set of supported languages is defined by the `codeql resolve languages` command. */ async function getLanguages( codeQL: CodeQL, @@ -731,11 +733,11 @@ async function getLanguages( .filter((x) => x.length > 0); logger.info(`Languages from configuration: ${JSON.stringify(languages)}`); + const allSupportedLanguages = new Set(Object.keys(await codeQL.resolveLanguages())); if (languages.length === 0) { // Obtain languages as all languages in the repo that can be analysed languages = await getLanguagesInRepo(repository, apiDetails, logger); - const availableLanguages = await codeQL.resolveLanguages(); - languages = languages.filter((value) => value in availableLanguages); + languages = languages.filter((value) => allSupportedLanguages.has(value)); logger.info( `Automatically detected languages: ${JSON.stringify(languages)}` ); @@ -748,21 +750,21 @@ async function getLanguages( } // Make sure they are supported - const parsedLanguages: Language[] = []; - const unknownLanguages: string[] = []; + const supportedLanguages: Language[] = []; + const unsupportedLanguages: Language[] = []; for (const language of languages) { const parsedLanguage = parseLanguage(language); - if (parsedLanguage === undefined) { - unknownLanguages.push(language); - } else if (parsedLanguages.indexOf(parsedLanguage) === -1) { - parsedLanguages.push(parsedLanguage); + if (!allSupportedLanguages.has(parsedLanguage)) { + unsupportedLanguages.push(language); + } else if (supportedLanguages.indexOf(parsedLanguage) === -1) { + supportedLanguages.push(parsedLanguage); } } - if (unknownLanguages.length > 0) { - throw new Error(getUnknownLanguagesError(unknownLanguages)); + if (unsupportedLanguages.length > 0) { + throw new Error(getUnsupportedLanguagesError(unsupportedLanguages)); } - return parsedLanguages; + return supportedLanguages; } async function addQueriesFromWorkflow( @@ -1071,7 +1073,7 @@ export function parsePacksFromConfig( if (!Array.isArray(packsArr)) { throw new Error(getPacksInvalid(configFile)); } - if (!languages.includes(lang as Language)) { + if (!languages.includes(lang)) { throw new Error(getPacksRequireLanguage(lang, configFile)); } packs[lang] = []; @@ -1172,7 +1174,7 @@ function shouldCombinePacks(packsInput?: string): boolean { function combinePacks(packs1: Packs, packs2: Packs): Packs { const packs = {}; for (const lang of Object.keys(packs1)) { - packs[lang] = packs1[lang].concat(packs2[lang] || []); + packs[lang] = packs1[lang]?.concat(packs2[lang] || []); } for (const lang of Object.keys(packs2)) { if (!packs[lang]) { diff --git a/src/count-loc.test.ts b/src/count-loc.test.ts index 3a32ab6e1a..eb2cb69cef 100644 --- a/src/count-loc.test.ts +++ b/src/count-loc.test.ts @@ -3,7 +3,7 @@ import * as path from "path"; import test from "ava"; import { countLoc } from "./count-loc"; -import { Language } from "./languages"; +import { KnownLanguage } from "./languages"; import { getRunnerLogger } from "./logging"; import { setupTests } from "./testing-utils"; @@ -14,7 +14,7 @@ test("ensure lines of code works for cpp and js", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), [], [], - [Language.cpp, Language.javascript], + [KnownLanguage.cpp, KnownLanguage.javascript], getRunnerLogger(true) ); @@ -29,7 +29,7 @@ test("ensure lines of code works for csharp", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), [], [], - [Language.csharp], + [KnownLanguage.csharp], getRunnerLogger(true) ); @@ -43,7 +43,7 @@ test("ensure lines of code can handle undefined language", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), [], [], - [Language.javascript, Language.python, "hucairz" as Language], + [KnownLanguage.javascript, KnownLanguage.python, "hucairz" as KnownLanguage], getRunnerLogger(true) ); @@ -72,7 +72,7 @@ test("ensure lines of code can handle includes", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), ["../../src/testdata"], [], - [Language.javascript], + [KnownLanguage.javascript], getRunnerLogger(true) ); @@ -88,7 +88,7 @@ test("ensure lines of code can handle empty includes", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), ["idontexist"], [], - [Language.javascript], + [KnownLanguage.javascript], getRunnerLogger(true) ); @@ -102,7 +102,7 @@ test("ensure lines of code can handle exclude", async (t) => { path.join(__dirname, "../tests/multi-language-repo"), [], ["**/*.py"], - [Language.javascript, Language.python], + [KnownLanguage.javascript, KnownLanguage.python], getRunnerLogger(true) ); diff --git a/src/count-loc.ts b/src/count-loc.ts index 549f07d703..6d0c6ee9be 100644 --- a/src/count-loc.ts +++ b/src/count-loc.ts @@ -1,19 +1,19 @@ import { LocDir } from "github-linguist"; -import { Language } from "./languages"; +import { KnownLanguage, Language } from "./languages"; import { Logger } from "./logging"; // Map from linguist language names to language prefixes used in the action and codeql -const linguistToMetrics: Record = { - c: Language.cpp, - "c++": Language.cpp, - "c#": Language.csharp, - go: Language.go, - java: Language.java, - javascript: Language.javascript, - python: Language.python, - ruby: Language.ruby, - typescript: Language.javascript, +const linguistToMetrics: Record = { + c: KnownLanguage.cpp, + "c++": KnownLanguage.cpp, + "c#": KnownLanguage.csharp, + go: KnownLanguage.go, + java: KnownLanguage.java, + javascript: KnownLanguage.javascript, + python: KnownLanguage.python, + ruby: KnownLanguage.ruby, + typescript: KnownLanguage.javascript, }; const nameToLinguist = Object.entries(linguistToMetrics).reduce( @@ -24,7 +24,7 @@ const nameToLinguist = Object.entries(linguistToMetrics).reduce( obj[name].push(key); return obj; }, - {} as Record + {} as Record ); /** diff --git a/src/database-upload.test.ts b/src/database-upload.test.ts index de55a0245f..8c61eba2f4 100644 --- a/src/database-upload.test.ts +++ b/src/database-upload.test.ts @@ -10,7 +10,7 @@ import * as apiClient from "./api-client"; import { setCodeQL } from "./codeql"; import { Config } from "./config-utils"; import { uploadDatabases } from "./database-upload"; -import { Language } from "./languages"; +import { KnownLanguage } from "./languages"; import { Logger } from "./logging"; import { RepositoryNwo } from "./repository"; import { setupActionsVars, setupTests } from "./testing-utils"; @@ -36,7 +36,7 @@ const testApiDetails: GitHubApiDetails = { function getTestConfig(tmpDir: string): Config { return { - languages: [Language.javascript], + languages: [KnownLanguage.javascript], queries: {}, pathsIgnore: [], paths: [], diff --git a/src/init-action.ts b/src/init-action.ts index 44402a688a..5faaa35705 100644 --- a/src/init-action.ts +++ b/src/init-action.ts @@ -21,7 +21,7 @@ import { installPythonDeps, runInit, } from "./init"; -import { Language } from "./languages"; +import { KnownLanguage } from "./languages"; import { getActionsLogger } from "./logging"; import { parseRepositoryNwo } from "./repository"; import { @@ -172,7 +172,7 @@ async function run() { ); if ( - config.languages.includes(Language.python) && + config.languages.includes(KnownLanguage.python) && getRequiredInput("setup-python-dependencies") === "true" ) { try { diff --git a/src/languages.test.ts b/src/languages.test.ts index 5837c91f8d..cdb9bac66f 100644 --- a/src/languages.test.ts +++ b/src/languages.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import { - Language, + KnownLanguage, isScannedLanguage, isTracedLanguage, parseLanguage, @@ -12,18 +12,18 @@ setupTests(test); test("parseLanguage", async (t) => { // Exact matches - t.deepEqual(parseLanguage("csharp"), Language.csharp); - t.deepEqual(parseLanguage("cpp"), Language.cpp); - t.deepEqual(parseLanguage("go"), Language.go); - t.deepEqual(parseLanguage("java"), Language.java); - t.deepEqual(parseLanguage("javascript"), Language.javascript); - t.deepEqual(parseLanguage("python"), Language.python); + t.deepEqual(parseLanguage("csharp"), KnownLanguage.csharp); + t.deepEqual(parseLanguage("cpp"), KnownLanguage.cpp); + t.deepEqual(parseLanguage("go"), KnownLanguage.go); + t.deepEqual(parseLanguage("java"), KnownLanguage.java); + t.deepEqual(parseLanguage("javascript"), KnownLanguage.javascript); + t.deepEqual(parseLanguage("python"), KnownLanguage.python); // Aliases - t.deepEqual(parseLanguage("c"), Language.cpp); - t.deepEqual(parseLanguage("c++"), Language.cpp); - t.deepEqual(parseLanguage("c#"), Language.csharp); - t.deepEqual(parseLanguage("typescript"), Language.javascript); + t.deepEqual(parseLanguage("c"), KnownLanguage.cpp); + t.deepEqual(parseLanguage("c++"), KnownLanguage.cpp); + t.deepEqual(parseLanguage("c#"), KnownLanguage.csharp); + t.deepEqual(parseLanguage("typescript"), KnownLanguage.javascript); // Not matches t.deepEqual(parseLanguage("foo"), undefined); @@ -32,21 +32,21 @@ test("parseLanguage", async (t) => { }); test("isTracedLanguage", async (t) => { - t.true(isTracedLanguage(Language.cpp)); - t.true(isTracedLanguage(Language.java)); - t.true(isTracedLanguage(Language.csharp)); + t.true(isTracedLanguage(KnownLanguage.cpp)); + t.true(isTracedLanguage(KnownLanguage.java)); + t.true(isTracedLanguage(KnownLanguage.csharp)); - t.false(isTracedLanguage(Language.go)); - t.false(isTracedLanguage(Language.javascript)); - t.false(isTracedLanguage(Language.python)); + t.false(isTracedLanguage(KnownLanguage.go)); + t.false(isTracedLanguage(KnownLanguage.javascript)); + t.false(isTracedLanguage(KnownLanguage.python)); }); test("isScannedLanguage", async (t) => { - t.false(isScannedLanguage(Language.cpp)); - t.false(isScannedLanguage(Language.java)); - t.false(isScannedLanguage(Language.csharp)); + t.false(isScannedLanguage(KnownLanguage.cpp)); + t.false(isScannedLanguage(KnownLanguage.java)); + t.false(isScannedLanguage(KnownLanguage.csharp)); - t.true(isScannedLanguage(Language.go)); - t.true(isScannedLanguage(Language.javascript)); - t.true(isScannedLanguage(Language.python)); + t.true(isScannedLanguage(KnownLanguage.go)); + t.true(isScannedLanguage(KnownLanguage.javascript)); + t.true(isScannedLanguage(KnownLanguage.python)); }); diff --git a/src/languages.ts b/src/languages.ts index a696908c7f..b4190e907b 100644 --- a/src/languages.ts +++ b/src/languages.ts @@ -1,5 +1,12 @@ -// All the languages supported by CodeQL -export enum Language { +/** + * A lowercase string representing a language. + */ +export type Language = Lowercase; + +/** + * All the languages known to be supported by CodeQL + */ +export enum KnownLanguage { csharp = "csharp", cpp = "cpp", go = "go", @@ -11,20 +18,20 @@ export enum Language { // Additional names for languages const LANGUAGE_ALIASES: { [lang: string]: Language } = { - c: Language.cpp, - "c++": Language.cpp, - "c#": Language.csharp, - typescript: Language.javascript, + c: KnownLanguage.cpp, + "c++": KnownLanguage.cpp, + "c#": KnownLanguage.csharp, + typescript: KnownLanguage.javascript, }; // Translate from user input or GitHub's API names for languages to CodeQL's names for languages -export function parseLanguage(language: string): Language | undefined { +export function parseLanguage(language: string): Language { // Normalise to lower case language = language.toLowerCase(); // See if it's an exact match - if (language in Language) { - return language as Language; + if (language in KnownLanguage) { + return language; } // Check language aliases @@ -32,14 +39,14 @@ export function parseLanguage(language: string): Language | undefined { return LANGUAGE_ALIASES[language]; } - return undefined; + return language; } export function isTracedLanguage(language: Language): boolean { return ( - ["cpp", "java", "csharp"].includes(language) || + [KnownLanguage.cpp, KnownLanguage.java, KnownLanguage.csharp].includes(language as any) || (process.env["CODEQL_EXTRACTOR_GO_BUILD_TRACING"] === "on" && - language === Language.go) + language === KnownLanguage.go) ); } diff --git a/src/tracer-config.test.ts b/src/tracer-config.test.ts index eae544844a..c62814a256 100644 --- a/src/tracer-config.test.ts +++ b/src/tracer-config.test.ts @@ -5,7 +5,7 @@ import test from "ava"; import { setCodeQL } from "./codeql"; import * as configUtils from "./config-utils"; -import { Language } from "./languages"; +import { KnownLanguage } from "./languages"; import { setupTests } from "./testing-utils"; import { concatTracerConfigs, @@ -18,7 +18,7 @@ setupTests(test); function getTestConfig(tmpDir: string): configUtils.Config { return { - languages: [Language.java], + languages: [KnownLanguage.java], queries: {}, pathsIgnore: [], paths: [], @@ -49,7 +49,7 @@ test("getTracerConfigForLanguage - minimal setup", async (t) => { const result = await getTracerConfigForLanguage( codeQL, config, - Language.javascript + KnownLanguage.javascript ); t.deepEqual(result, { spec: "abc", env: { foo: "bar" } }); }); @@ -89,7 +89,7 @@ test("getTracerConfigForLanguage - existing / critical vars", async (t) => { const result = await getTracerConfigForLanguage( codeQL, config, - Language.javascript + KnownLanguage.javascript ); t.deepEqual(result, { spec: "abc", @@ -309,7 +309,7 @@ test("getCombinedTracerConfig - return undefined when no languages are traced la await util.withTmpDir(async (tmpDir) => { const config = getTestConfig(tmpDir); // No traced languages - config.languages = [Language.javascript, Language.python]; + config.languages = [KnownLanguage.javascript, KnownLanguage.python]; const codeQL = setCodeQL({ async getTracerEnv() { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy