Compare commits

...

3 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
91e3c857ab add test 2021-10-28 14:43:00 +02:00
Esben Sparre Andreasen
3847055a30 fix TypeScript NPE type warning 2021-10-25 21:22:43 +02:00
Esben Sparre Andreasen
2a8725d4a8 let the codeql env decide the supported languages 2021-10-25 21:22:43 +02:00
11 changed files with 208 additions and 129 deletions

View File

@@ -10,7 +10,7 @@ import { runQueries } from "./analyze";
import { setCodeQL } from "./codeql"; import { setCodeQL } from "./codeql";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import * as count from "./count-loc"; import * as count from "./count-loc";
import { Language } from "./languages"; import { KnownLanguage } from "./languages";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { setupTests, setupActionsVars } from "./testing-utils"; import { setupTests, setupActionsVars } from "./testing-utils";
import * as util from "./util"; import * as util from "./util";
@@ -21,8 +21,8 @@ setupTests(test);
// and correct case of builtin or custom. Also checks the correct search // and correct case of builtin or custom. Also checks the correct search
// paths are set in the database analyze invocation. // paths are set in the database analyze invocation.
test("status report fields and search path setting", async (t) => { test("status report fields and search path setting", async (t) => {
const mockLinesOfCode = Object.values(Language).reduce((obj, lang, i) => { const mockLinesOfCode = Object.values(KnownLanguage).reduce((obj, lang, i) => {
// use a different line count for each language // use a different line count for each KnownLanguage
obj[lang] = i + 1; obj[lang] = i + 1;
return obj; return obj;
}, {}); }, {});
@@ -35,13 +35,13 @@ test("status report fields and search path setting", async (t) => {
const addSnippetsFlag = ""; const addSnippetsFlag = "";
const threadsFlag = ""; const threadsFlag = "";
const packs = { const packs = {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ {
packName: "a/b", packName: "a/b",
version: clean("1.0.0")!, version: clean("1.0.0")!,
}, },
], ],
[Language.java]: [ [KnownLanguage.java]: [
{ {
packName: "c/d", packName: "c/d",
version: clean("2.0.0")!, 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({ setCodeQL({
packDownload: async () => ({ packs: [] }), packDownload: async () => ({ packs: [] }),
databaseRunQueries: async ( databaseRunQueries: async (
@@ -203,7 +203,7 @@ test("status report fields and search path setting", async (t) => {
function verifyLineCounts(tmpDir: string) { function verifyLineCounts(tmpDir: string) {
// eslint-disable-next-line github/array-foreach // 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); 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", 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-builtin.qls`), qlsContent);
t.deepEqual(readContents(`${lang}-queries-custom-0.qls`), qlsContent); t.deepEqual(readContents(`${lang}-queries-custom-0.qls`), qlsContent);
t.deepEqual(readContents(`${lang}-queries-custom-1.qls`), qlsContent2); t.deepEqual(readContents(`${lang}-queries-custom-1.qls`), qlsContent2);
const packSuiteName = `${lang}-queries-packs.qls`; const packSuiteName = `${lang}-queries-packs.qls`;
if (lang === Language.cpp) { if (lang === KnownLanguage.cpp) {
t.deepEqual(readContents(packSuiteName), qlsPackContentCpp); t.deepEqual(readContents(packSuiteName), qlsPackContentCpp);
} else if (lang === Language.java) { } else if (lang === KnownLanguage.java) {
t.deepEqual(readContents(packSuiteName), qlsPackContentJava); t.deepEqual(readContents(packSuiteName), qlsPackContentJava);
} else { } else {
t.false( t.false(

View File

@@ -8,7 +8,7 @@ import * as analysisPaths from "./analysis-paths";
import { CODEQL_VERSION_COUNTS_LINES, getCodeQL } from "./codeql"; import { CODEQL_VERSION_COUNTS_LINES, getCodeQL } from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { countLoc } from "./count-loc"; import { countLoc } from "./count-loc";
import { isScannedLanguage, Language } from "./languages"; import { isScannedLanguage, KnownLanguage, Language } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
import * as sharedEnv from "./shared-environment"; import * as sharedEnv from "./shared-environment";
import * as util from "./util"; import * as util from "./util";
@@ -124,7 +124,7 @@ async function createdDBForScannedLanguages(
) { ) {
logger.startGroup(`Extracting ${language}`); logger.startGroup(`Extracting ${language}`);
if (language === Language.python) { if (language === KnownLanguage.python) {
await setupPythonExtractor(logger); await setupPythonExtractor(logger);
} }

View File

@@ -9,7 +9,7 @@ import * as sinon from "sinon";
import * as api from "./api-client"; import * as api from "./api-client";
import { getCachedCodeQL, setCodeQL } from "./codeql"; import { getCachedCodeQL, setCodeQL } from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { Language } from "./languages"; import { KnownLanguage, Language } from "./languages";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { setupTests } from "./testing-utils"; import { setupTests } from "./testing-utils";
import * as util from "./util"; 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 // And the config we expect it to parse to
const expectedConfig: configUtils.Config = { const expectedConfig: configUtils.Config = {
languages: [Language.javascript], languages: [KnownLanguage.javascript],
queries: { queries: {
javascript: { javascript: {
builtin: [], 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) => { return await util.withTmpDir(async (tmpDir) => {
const languages = "rubbish,english"; const languages = "rubbish,english";
@@ -998,7 +998,77 @@ test("Unknown languages", async (t) => {
} catch (err) { } catch (err) {
t.deepEqual( t.deepEqual(
err, 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) getRunnerLogger(true)
); );
t.deepEqual(packs as unknown, { t.deepEqual(packs as unknown, {
[Language.javascript]: [ [KnownLanguage.javascript]: [
{ {
packName: "a/b", packName: "a/b",
version: clean("1.2.3"), version: clean("1.2.3"),
@@ -1102,13 +1172,13 @@ test("Config specifies packages for multiple languages", async (t) => {
getRunnerLogger(true) getRunnerLogger(true)
); );
t.deepEqual(packs as unknown, { t.deepEqual(packs as unknown, {
[Language.javascript]: [ [KnownLanguage.javascript]: [
{ {
packName: "a/b", packName: "a/b",
version: clean("1.2.3"), version: clean("1.2.3"),
}, },
], ],
[Language.python]: [ [KnownLanguage.python]: [
{ {
packName: "c/d", packName: "c/d",
version: clean("1.2.3"), version: clean("1.2.3"),
@@ -1377,8 +1447,8 @@ parsePacksErrorMacro.title = (providedTitle: string) =>
function invalidPackNameMacro(t: ExecutionContext<unknown>, name: string) { function invalidPackNameMacro(t: ExecutionContext<unknown>, name: string) {
parsePacksErrorMacro( parsePacksErrorMacro(
t, t,
{ [Language.cpp]: [name] }, { [KnownLanguage.cpp]: [name] },
[Language.cpp], [KnownLanguage.cpp],
new RegExp( new RegExp(
`The configuration file "/a/b" is invalid: property "packs" "${name}" is not a valid pack` `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}`; `Invalid pack string: ${arg}`;
test("no packs", parsePacksMacro, {}, [], {}); test("no packs", parsePacksMacro, {}, [], {});
test("two packs", parsePacksMacro, ["a/b", "c/d@1.2.3"], [Language.cpp], { test("two packs", parsePacksMacro, ["a/b", "c/d@1.2.3"], [KnownLanguage.cpp], {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
{ packName: "c/d", version: clean("1.2.3") }, { packName: "c/d", version: clean("1.2.3") },
], ],
@@ -1398,9 +1468,9 @@ test(
"two packs with spaces", "two packs with spaces",
parsePacksMacro, parsePacksMacro,
[" a/b ", " c/d@1.2.3 "], [" a/b ", " c/d@1.2.3 "],
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
{ packName: "c/d", version: clean("1.2.3") }, { packName: "c/d", version: clean("1.2.3") },
], ],
@@ -1410,16 +1480,16 @@ test(
"two packs with language", "two packs with language",
parsePacksMacro, parsePacksMacro,
{ {
[Language.cpp]: ["a/b", "c/d@1.2.3"], [KnownLanguage.cpp]: ["a/b", "c/d@1.2.3"],
[Language.java]: ["d/e", "f/g@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: "a/b", version: undefined },
{ packName: "c/d", version: clean("1.2.3") }, { packName: "c/d", version: clean("1.2.3") },
], ],
[Language.java]: [ [KnownLanguage.java]: [
{ packName: "d/e", version: undefined }, { packName: "d/e", version: undefined },
{ packName: "f/g", version: clean("1.2.3") }, { packName: "f/g", version: clean("1.2.3") },
], ],
@@ -1430,21 +1500,21 @@ test(
"no language", "no language",
parsePacksErrorMacro, parsePacksErrorMacro,
["a/b@1.2.3"], ["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/ /The configuration file "\/a\/b" is invalid: property "packs" must split packages by language/
); );
test( test(
"invalid language", "invalid language",
parsePacksErrorMacro, parsePacksErrorMacro,
{ [Language.java]: ["c/d"] }, { [KnownLanguage.java]: ["c/d"] },
[Language.cpp], [KnownLanguage.cpp],
/The configuration file "\/a\/b" is invalid: property "packs" has "java", but it is not one of the languages to analyze/ /The configuration file "\/a\/b" is invalid: property "packs" has "java", but it is not one of the languages to analyze/
); );
test( test(
"not an array", "not an array",
parsePacksErrorMacro, parsePacksErrorMacro,
{ [Language.cpp]: "c/d" }, { [KnownLanguage.cpp]: "c/d" },
[Language.cpp], [KnownLanguage.cpp],
/The configuration file "\/a\/b" is invalid: property "packs" must be an array of non-empty strings/ /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) => parseInputAndConfigErrorMacro.title = (providedTitle: string) =>
`Parse Packs input and config Error: ${providedTitle}`; `Parse Packs input and config Error: ${providedTitle}`;
test("input only", parseInputAndConfigMacro, {}, " c/d ", [Language.cpp], { test("input only", parseInputAndConfigMacro, {}, " c/d ", [KnownLanguage.cpp], {
[Language.cpp]: [{ packName: "c/d", version: undefined }], [KnownLanguage.cpp]: [{ packName: "c/d", version: undefined }],
}); });
test( test(
@@ -1505,9 +1575,9 @@ test(
parseInputAndConfigMacro, parseInputAndConfigMacro,
{}, {},
"a/b , c/d@1.2.3", "a/b , c/d@1.2.3",
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
{ packName: "c/d", version: "1.2.3" }, { packName: "c/d", version: "1.2.3" },
], ],
@@ -1519,9 +1589,9 @@ test(
parseInputAndConfigMacro, parseInputAndConfigMacro,
{}, {},
" + a/b , c/d@1.2.3 ", " + a/b , c/d@1.2.3 ",
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
{ packName: "c/d", version: "1.2.3" }, { packName: "c/d", version: "1.2.3" },
], ],
@@ -1533,9 +1603,9 @@ test(
parseInputAndConfigMacro, parseInputAndConfigMacro,
["a/b", "c/d"], ["a/b", "c/d"],
" ", " ",
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
{ packName: "c/d", version: undefined }, { packName: "c/d", version: undefined },
], ],
@@ -1547,9 +1617,9 @@ test(
parseInputAndConfigMacro, parseInputAndConfigMacro,
["a/b", "c/d"], ["a/b", "c/d"],
" e/f, g/h@1.2.3 ", " e/f, g/h@1.2.3 ",
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "e/f", version: undefined }, { packName: "e/f", version: undefined },
{ packName: "g/h", version: "1.2.3" }, { packName: "g/h", version: "1.2.3" },
], ],
@@ -1561,9 +1631,9 @@ test(
parseInputAndConfigMacro, parseInputAndConfigMacro,
["a/b", "c/d"], ["a/b", "c/d"],
" +e/f, g/h@1.2.3 ", " +e/f, g/h@1.2.3 ",
[Language.cpp], [KnownLanguage.cpp],
{ {
[Language.cpp]: [ [KnownLanguage.cpp]: [
{ packName: "e/f", version: undefined }, { packName: "e/f", version: undefined },
{ packName: "g/h", version: "1.2.3" }, { packName: "g/h", version: "1.2.3" },
{ packName: "a/b", version: undefined }, { packName: "a/b", version: undefined },
@@ -1586,7 +1656,7 @@ test(
parseInputAndConfigErrorMacro, parseInputAndConfigErrorMacro,
{}, {},
"c/d", "c/d",
[Language.cpp, Language.csharp], [KnownLanguage.cpp, KnownLanguage.csharp],
/multi-language analysis/ /multi-language analysis/
); );
@@ -1595,7 +1665,7 @@ test(
parseInputAndConfigErrorMacro, parseInputAndConfigErrorMacro,
{}, {},
" + ", " + ",
[Language.cpp], [KnownLanguage.cpp],
/remove the '\+'/ /remove the '\+'/
); );
@@ -1604,7 +1674,7 @@ test(
parseInputAndConfigErrorMacro, parseInputAndConfigErrorMacro,
{}, {},
" xxx", " xxx",
[Language.cpp], [KnownLanguage.cpp],
/"xxx" is not a valid pack/ /"xxx" is not a valid pack/
); );

View File

@@ -673,8 +673,8 @@ export function getNoLanguagesError(): string {
); );
} }
export function getUnknownLanguagesError(languages: string[]): string { export function getUnsupportedLanguagesError(languages: string[]): string {
return `Did not recognise the following languages: ${languages.join(", ")}`; 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 * has been set, otherwise it is deduced as all languages in the repo that
* can be analysed. * 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. * then throw an error.
*
* The set of supported languages is defined by the `codeql resolve languages` command.
*/ */
async function getLanguages( async function getLanguages(
codeQL: CodeQL, codeQL: CodeQL,
@@ -731,11 +733,11 @@ async function getLanguages(
.filter((x) => x.length > 0); .filter((x) => x.length > 0);
logger.info(`Languages from configuration: ${JSON.stringify(languages)}`); logger.info(`Languages from configuration: ${JSON.stringify(languages)}`);
const allSupportedLanguages = new Set(Object.keys(await codeQL.resolveLanguages()));
if (languages.length === 0) { if (languages.length === 0) {
// Obtain languages as all languages in the repo that can be analysed // Obtain languages as all languages in the repo that can be analysed
languages = await getLanguagesInRepo(repository, apiDetails, logger); languages = await getLanguagesInRepo(repository, apiDetails, logger);
const availableLanguages = await codeQL.resolveLanguages(); languages = languages.filter((value) => allSupportedLanguages.has(value));
languages = languages.filter((value) => value in availableLanguages);
logger.info( logger.info(
`Automatically detected languages: ${JSON.stringify(languages)}` `Automatically detected languages: ${JSON.stringify(languages)}`
); );
@@ -748,21 +750,21 @@ async function getLanguages(
} }
// Make sure they are supported // Make sure they are supported
const parsedLanguages: Language[] = []; const supportedLanguages: Language[] = [];
const unknownLanguages: string[] = []; const unsupportedLanguages: Language[] = [];
for (const language of languages) { for (const language of languages) {
const parsedLanguage = parseLanguage(language); const parsedLanguage = parseLanguage(language);
if (parsedLanguage === undefined) { if (!allSupportedLanguages.has(parsedLanguage)) {
unknownLanguages.push(language); unsupportedLanguages.push(language);
} else if (parsedLanguages.indexOf(parsedLanguage) === -1) { } else if (supportedLanguages.indexOf(parsedLanguage) === -1) {
parsedLanguages.push(parsedLanguage); supportedLanguages.push(parsedLanguage);
} }
} }
if (unknownLanguages.length > 0) { if (unsupportedLanguages.length > 0) {
throw new Error(getUnknownLanguagesError(unknownLanguages)); throw new Error(getUnsupportedLanguagesError(unsupportedLanguages));
} }
return parsedLanguages; return supportedLanguages;
} }
async function addQueriesFromWorkflow( async function addQueriesFromWorkflow(
@@ -1071,7 +1073,7 @@ export function parsePacksFromConfig(
if (!Array.isArray(packsArr)) { if (!Array.isArray(packsArr)) {
throw new Error(getPacksInvalid(configFile)); throw new Error(getPacksInvalid(configFile));
} }
if (!languages.includes(lang as Language)) { if (!languages.includes(lang)) {
throw new Error(getPacksRequireLanguage(lang, configFile)); throw new Error(getPacksRequireLanguage(lang, configFile));
} }
packs[lang] = []; packs[lang] = [];
@@ -1172,7 +1174,7 @@ function shouldCombinePacks(packsInput?: string): boolean {
function combinePacks(packs1: Packs, packs2: Packs): Packs { function combinePacks(packs1: Packs, packs2: Packs): Packs {
const packs = {}; const packs = {};
for (const lang of Object.keys(packs1)) { 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)) { for (const lang of Object.keys(packs2)) {
if (!packs[lang]) { if (!packs[lang]) {

View File

@@ -3,7 +3,7 @@ import * as path from "path";
import test from "ava"; import test from "ava";
import { countLoc } from "./count-loc"; import { countLoc } from "./count-loc";
import { Language } from "./languages"; import { KnownLanguage } from "./languages";
import { getRunnerLogger } from "./logging"; import { getRunnerLogger } from "./logging";
import { setupTests } from "./testing-utils"; 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"), path.join(__dirname, "../tests/multi-language-repo"),
[], [],
[], [],
[Language.cpp, Language.javascript], [KnownLanguage.cpp, KnownLanguage.javascript],
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -29,7 +29,7 @@ test("ensure lines of code works for csharp", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"), path.join(__dirname, "../tests/multi-language-repo"),
[], [],
[], [],
[Language.csharp], [KnownLanguage.csharp],
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -43,7 +43,7 @@ test("ensure lines of code can handle undefined language", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"), path.join(__dirname, "../tests/multi-language-repo"),
[], [],
[], [],
[Language.javascript, Language.python, "hucairz" as Language], [KnownLanguage.javascript, KnownLanguage.python, "hucairz" as KnownLanguage],
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -72,7 +72,7 @@ test("ensure lines of code can handle includes", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"), path.join(__dirname, "../tests/multi-language-repo"),
["../../src/testdata"], ["../../src/testdata"],
[], [],
[Language.javascript], [KnownLanguage.javascript],
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -88,7 +88,7 @@ test("ensure lines of code can handle empty includes", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"), path.join(__dirname, "../tests/multi-language-repo"),
["idontexist"], ["idontexist"],
[], [],
[Language.javascript], [KnownLanguage.javascript],
getRunnerLogger(true) getRunnerLogger(true)
); );
@@ -102,7 +102,7 @@ test("ensure lines of code can handle exclude", async (t) => {
path.join(__dirname, "../tests/multi-language-repo"), path.join(__dirname, "../tests/multi-language-repo"),
[], [],
["**/*.py"], ["**/*.py"],
[Language.javascript, Language.python], [KnownLanguage.javascript, KnownLanguage.python],
getRunnerLogger(true) getRunnerLogger(true)
); );

View File

@@ -1,19 +1,19 @@
import { LocDir } from "github-linguist"; import { LocDir } from "github-linguist";
import { Language } from "./languages"; import { KnownLanguage, Language } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
// Map from linguist language names to language prefixes used in the action and codeql // Map from linguist language names to language prefixes used in the action and codeql
const linguistToMetrics: Record<string, Language> = { const linguistToMetrics: Record<string, KnownLanguage> = {
c: Language.cpp, c: KnownLanguage.cpp,
"c++": Language.cpp, "c++": KnownLanguage.cpp,
"c#": Language.csharp, "c#": KnownLanguage.csharp,
go: Language.go, go: KnownLanguage.go,
java: Language.java, java: KnownLanguage.java,
javascript: Language.javascript, javascript: KnownLanguage.javascript,
python: Language.python, python: KnownLanguage.python,
ruby: Language.ruby, ruby: KnownLanguage.ruby,
typescript: Language.javascript, typescript: KnownLanguage.javascript,
}; };
const nameToLinguist = Object.entries(linguistToMetrics).reduce( const nameToLinguist = Object.entries(linguistToMetrics).reduce(
@@ -24,7 +24,7 @@ const nameToLinguist = Object.entries(linguistToMetrics).reduce(
obj[name].push(key); obj[name].push(key);
return obj; return obj;
}, },
{} as Record<Language, string[]> {} as Record<KnownLanguage, string[]>
); );
/** /**

View File

@@ -10,7 +10,7 @@ import * as apiClient from "./api-client";
import { setCodeQL } from "./codeql"; import { setCodeQL } from "./codeql";
import { Config } from "./config-utils"; import { Config } from "./config-utils";
import { uploadDatabases } from "./database-upload"; import { uploadDatabases } from "./database-upload";
import { Language } from "./languages"; import { KnownLanguage } from "./languages";
import { Logger } from "./logging"; import { Logger } from "./logging";
import { RepositoryNwo } from "./repository"; import { RepositoryNwo } from "./repository";
import { setupActionsVars, setupTests } from "./testing-utils"; import { setupActionsVars, setupTests } from "./testing-utils";
@@ -36,7 +36,7 @@ const testApiDetails: GitHubApiDetails = {
function getTestConfig(tmpDir: string): Config { function getTestConfig(tmpDir: string): Config {
return { return {
languages: [Language.javascript], languages: [KnownLanguage.javascript],
queries: {}, queries: {},
pathsIgnore: [], pathsIgnore: [],
paths: [], paths: [],

View File

@@ -21,7 +21,7 @@ import {
installPythonDeps, installPythonDeps,
runInit, runInit,
} from "./init"; } from "./init";
import { Language } from "./languages"; import { KnownLanguage } from "./languages";
import { getActionsLogger } from "./logging"; import { getActionsLogger } from "./logging";
import { parseRepositoryNwo } from "./repository"; import { parseRepositoryNwo } from "./repository";
import { import {
@@ -172,7 +172,7 @@ async function run() {
); );
if ( if (
config.languages.includes(Language.python) && config.languages.includes(KnownLanguage.python) &&
getRequiredInput("setup-python-dependencies") === "true" getRequiredInput("setup-python-dependencies") === "true"
) { ) {
try { try {

View File

@@ -1,7 +1,7 @@
import test from "ava"; import test from "ava";
import { import {
Language, KnownLanguage,
isScannedLanguage, isScannedLanguage,
isTracedLanguage, isTracedLanguage,
parseLanguage, parseLanguage,
@@ -12,18 +12,18 @@ setupTests(test);
test("parseLanguage", async (t) => { test("parseLanguage", async (t) => {
// Exact matches // Exact matches
t.deepEqual(parseLanguage("csharp"), Language.csharp); t.deepEqual(parseLanguage("csharp"), KnownLanguage.csharp);
t.deepEqual(parseLanguage("cpp"), Language.cpp); t.deepEqual(parseLanguage("cpp"), KnownLanguage.cpp);
t.deepEqual(parseLanguage("go"), Language.go); t.deepEqual(parseLanguage("go"), KnownLanguage.go);
t.deepEqual(parseLanguage("java"), Language.java); t.deepEqual(parseLanguage("java"), KnownLanguage.java);
t.deepEqual(parseLanguage("javascript"), Language.javascript); t.deepEqual(parseLanguage("javascript"), KnownLanguage.javascript);
t.deepEqual(parseLanguage("python"), Language.python); t.deepEqual(parseLanguage("python"), KnownLanguage.python);
// Aliases // Aliases
t.deepEqual(parseLanguage("c"), Language.cpp); t.deepEqual(parseLanguage("c"), KnownLanguage.cpp);
t.deepEqual(parseLanguage("c++"), Language.cpp); t.deepEqual(parseLanguage("c++"), KnownLanguage.cpp);
t.deepEqual(parseLanguage("c#"), Language.csharp); t.deepEqual(parseLanguage("c#"), KnownLanguage.csharp);
t.deepEqual(parseLanguage("typescript"), Language.javascript); t.deepEqual(parseLanguage("typescript"), KnownLanguage.javascript);
// Not matches // Not matches
t.deepEqual(parseLanguage("foo"), undefined); t.deepEqual(parseLanguage("foo"), undefined);
@@ -32,21 +32,21 @@ test("parseLanguage", async (t) => {
}); });
test("isTracedLanguage", async (t) => { test("isTracedLanguage", async (t) => {
t.true(isTracedLanguage(Language.cpp)); t.true(isTracedLanguage(KnownLanguage.cpp));
t.true(isTracedLanguage(Language.java)); t.true(isTracedLanguage(KnownLanguage.java));
t.true(isTracedLanguage(Language.csharp)); t.true(isTracedLanguage(KnownLanguage.csharp));
t.false(isTracedLanguage(Language.go)); t.false(isTracedLanguage(KnownLanguage.go));
t.false(isTracedLanguage(Language.javascript)); t.false(isTracedLanguage(KnownLanguage.javascript));
t.false(isTracedLanguage(Language.python)); t.false(isTracedLanguage(KnownLanguage.python));
}); });
test("isScannedLanguage", async (t) => { test("isScannedLanguage", async (t) => {
t.false(isScannedLanguage(Language.cpp)); t.false(isScannedLanguage(KnownLanguage.cpp));
t.false(isScannedLanguage(Language.java)); t.false(isScannedLanguage(KnownLanguage.java));
t.false(isScannedLanguage(Language.csharp)); t.false(isScannedLanguage(KnownLanguage.csharp));
t.true(isScannedLanguage(Language.go)); t.true(isScannedLanguage(KnownLanguage.go));
t.true(isScannedLanguage(Language.javascript)); t.true(isScannedLanguage(KnownLanguage.javascript));
t.true(isScannedLanguage(Language.python)); t.true(isScannedLanguage(KnownLanguage.python));
}); });

View File

@@ -1,5 +1,12 @@
// All the languages supported by CodeQL /**
export enum Language { * A lowercase string representing a language.
*/
export type Language = Lowercase<string>;
/**
* All the languages known to be supported by CodeQL
*/
export enum KnownLanguage {
csharp = "csharp", csharp = "csharp",
cpp = "cpp", cpp = "cpp",
go = "go", go = "go",
@@ -11,20 +18,20 @@ export enum Language {
// Additional names for languages // Additional names for languages
const LANGUAGE_ALIASES: { [lang: string]: Language } = { const LANGUAGE_ALIASES: { [lang: string]: Language } = {
c: Language.cpp, c: KnownLanguage.cpp,
"c++": Language.cpp, "c++": KnownLanguage.cpp,
"c#": Language.csharp, "c#": KnownLanguage.csharp,
typescript: Language.javascript, typescript: KnownLanguage.javascript,
}; };
// Translate from user input or GitHub's API names for languages to CodeQL's names for languages // 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 // Normalise to lower case
language = language.toLowerCase(); language = language.toLowerCase();
// See if it's an exact match // See if it's an exact match
if (language in Language) { if (language in KnownLanguage) {
return language as Language; return language;
} }
// Check language aliases // Check language aliases
@@ -32,14 +39,14 @@ export function parseLanguage(language: string): Language | undefined {
return LANGUAGE_ALIASES[language]; return LANGUAGE_ALIASES[language];
} }
return undefined; return language;
} }
export function isTracedLanguage(language: Language): boolean { export function isTracedLanguage(language: Language): boolean {
return ( return (
["cpp", "java", "csharp"].includes(language) || [KnownLanguage.cpp, KnownLanguage.java, KnownLanguage.csharp].includes(language as any) ||
(process.env["CODEQL_EXTRACTOR_GO_BUILD_TRACING"] === "on" && (process.env["CODEQL_EXTRACTOR_GO_BUILD_TRACING"] === "on" &&
language === Language.go) language === KnownLanguage.go)
); );
} }

View File

@@ -5,7 +5,7 @@ import test from "ava";
import { setCodeQL } from "./codeql"; import { setCodeQL } from "./codeql";
import * as configUtils from "./config-utils"; import * as configUtils from "./config-utils";
import { Language } from "./languages"; import { KnownLanguage } from "./languages";
import { setupTests } from "./testing-utils"; import { setupTests } from "./testing-utils";
import { import {
concatTracerConfigs, concatTracerConfigs,
@@ -18,7 +18,7 @@ setupTests(test);
function getTestConfig(tmpDir: string): configUtils.Config { function getTestConfig(tmpDir: string): configUtils.Config {
return { return {
languages: [Language.java], languages: [KnownLanguage.java],
queries: {}, queries: {},
pathsIgnore: [], pathsIgnore: [],
paths: [], paths: [],
@@ -49,7 +49,7 @@ test("getTracerConfigForLanguage - minimal setup", async (t) => {
const result = await getTracerConfigForLanguage( const result = await getTracerConfigForLanguage(
codeQL, codeQL,
config, config,
Language.javascript KnownLanguage.javascript
); );
t.deepEqual(result, { spec: "abc", env: { foo: "bar" } }); t.deepEqual(result, { spec: "abc", env: { foo: "bar" } });
}); });
@@ -89,7 +89,7 @@ test("getTracerConfigForLanguage - existing / critical vars", async (t) => {
const result = await getTracerConfigForLanguage( const result = await getTracerConfigForLanguage(
codeQL, codeQL,
config, config,
Language.javascript KnownLanguage.javascript
); );
t.deepEqual(result, { t.deepEqual(result, {
spec: "abc", spec: "abc",
@@ -309,7 +309,7 @@ test("getCombinedTracerConfig - return undefined when no languages are traced la
await util.withTmpDir(async (tmpDir) => { await util.withTmpDir(async (tmpDir) => {
const config = getTestConfig(tmpDir); const config = getTestConfig(tmpDir);
// No traced languages // No traced languages
config.languages = [Language.javascript, Language.python]; config.languages = [KnownLanguage.javascript, KnownLanguage.python];
const codeQL = setCodeQL({ const codeQL = setCodeQL({
async getTracerEnv() { async getTracerEnv() {