-
Notifications
You must be signed in to change notification settings - Fork 229
Fix AST viewer for refactored language packs #939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
912b227
6c73170
7b7849a
f3136a0
1fc2592
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,8 +11,9 @@ import { | |
| } from './keyType'; | ||
| import { CodeQLCliServer } from '../cli'; | ||
| import { DatabaseItem } from '../databases'; | ||
| import { QlPacksForLanguage } from '../helpers'; | ||
|
|
||
| export async function qlpackOfDatabase(cli: CodeQLCliServer, db: DatabaseItem): Promise<string> { | ||
| export async function qlpackOfDatabase(cli: CodeQLCliServer, db: DatabaseItem): Promise<QlPacksForLanguage> { | ||
| if (db.contents === undefined) { | ||
| throw new Error('Database is invalid and cannot infer QLPack.'); | ||
| } | ||
|
|
@@ -21,28 +22,87 @@ export async function qlpackOfDatabase(cli: CodeQLCliServer, db: DatabaseItem): | |
| return await helpers.getQlPackForDbscheme(cli, dbscheme); | ||
| } | ||
|
|
||
| /** | ||
| * Finds the contextual queries with the specified key in a list of CodeQL packs. | ||
| * | ||
| * @param cli The CLI instance to use. | ||
| * @param qlpacks The list of packs to search. | ||
| * @param keyType The contextual query key of the query to search for. | ||
| * @returns The found queries from the first pack in which any matching queries were found. | ||
| */ | ||
| async function resolveQueriesFromPacks(cli: CodeQLCliServer, qlpacks: string[], keyType: KeyType): Promise<string[]> { | ||
| for (const qlpack of qlpacks) { | ||
| const suiteFile = (await tmp.file({ | ||
| postfix: '.qls' | ||
| })).path; | ||
| const suiteYaml = { | ||
| qlpack, | ||
| include: { | ||
| kind: kindOfKeyType(keyType), | ||
| 'tags contain': tagOfKeyType(keyType) | ||
| } | ||
| }; | ||
| await fs.writeFile(suiteFile, yaml.safeDump(suiteYaml), 'utf8'); | ||
|
|
||
| export async function resolveQueries(cli: CodeQLCliServer, qlpack: string, keyType: KeyType): Promise<string[]> { | ||
| const suiteFile = (await tmp.file({ | ||
| postfix: '.qls' | ||
| })).path; | ||
| const suiteYaml = { | ||
| qlpack, | ||
| include: { | ||
| kind: kindOfKeyType(keyType), | ||
| 'tags contain': tagOfKeyType(keyType) | ||
| const queries = await cli.resolveQueriesInSuite(suiteFile, helpers.getOnDiskWorkspaceFolders()); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned about calling the CLI in a loop. Each call is a few seconds since it needs to restart the vm. If it's only going to be called 2 or 3 times for each AST Viewer call, maybe that's fine. Alternatively, could you combine all the qlpacks into one suite? It would look like this: const allPacks = [
{
qlpack: 'codeql/cpp-queries',
include: { ... }
},
{
qlpack: 'codeql/cpp-all',
include: { ... }
}
];And then you can just send this suite directly to the CLI. I think it would work.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could use the CodeQL CLI server (
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, did a little bit of digging here and we are using the cli server for all calls to the cli. The queries are handled by the query server and other commands by the cli server. This means that it is less important to combine these pack references into a single suite.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once the packs are all properly refactored, we'll always find the queries in the dbscheme library pack, so we'll never search the query pack. The only situation where we'll search both packs is with a >=2.6.1 CLI and packs that were released at the same time as 2.6.1. By the next dist upgrade, the contextual queries will already be in the library pack. |
||
| if (queries.length > 0) { | ||
| return queries; | ||
| } | ||
| }; | ||
| await fs.writeFile(suiteFile, yaml.safeDump(suiteYaml), 'utf8'); | ||
|
|
||
| const queries = await cli.resolveQueriesInSuite(suiteFile, helpers.getOnDiskWorkspaceFolders()); | ||
| if (queries.length === 0) { | ||
| void helpers.showAndLogErrorMessage( | ||
| `No ${nameOfKeyType(keyType)} queries (tagged "${tagOfKeyType(keyType)}") could be found in the current library path. \ | ||
| Try upgrading the CodeQL libraries. If that doesn't work, then ${nameOfKeyType(keyType)} queries are not yet available \ | ||
| for this language.` | ||
| ); | ||
| throw new Error(`Couldn't find any queries tagged ${tagOfKeyType(keyType)} for qlpack ${qlpack}`); | ||
| } | ||
| return queries; | ||
|
|
||
| return []; | ||
| } | ||
|
|
||
| export async function resolveQueries(cli: CodeQLCliServer, qlpacks: QlPacksForLanguage, keyType: KeyType): Promise<string[]> { | ||
| const cliCanHandleLibraryPack = await cli.cliConstraints.supportsAllowLibraryPacksInResolveQueries(); | ||
| const packsToSearch: string[] = []; | ||
| let blameCli: boolean; | ||
|
|
||
| if (cliCanHandleLibraryPack) { | ||
| // The CLI can handle both library packs and query packs, so search both packs in order. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah...so it's only ever 2 calls to the CLI for resolve queries. Still might make sense to combine them into a single suite.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above. Even the two-call case is only for a specific combination of CLI/pack versions. |
||
| packsToSearch.push(qlpacks.dbschemePack); | ||
| if (qlpacks.queryPack !== undefined) { | ||
| packsToSearch.push(qlpacks.queryPack); | ||
| } | ||
| // If we don't find the query, it's because it's not there, not because the CLI was unable to | ||
| // search the pack. | ||
| blameCli = false; | ||
| } else { | ||
| // Older CLIs can't handle `codeql resolve queries` with a suite that references a library pack. | ||
| if (qlpacks.dbschemePackIsLibraryPack) { | ||
| if (qlpacks.queryPack !== undefined) { | ||
| // Just search the query pack, because some older library/query releases still had the | ||
| // contextual queries in the query pack. | ||
| packsToSearch.push(qlpacks.queryPack); | ||
| } | ||
| // If we don't find it, it's because the CLI was unable to search the library pack that | ||
| // actually contains the query. Blame any failure on the CLI, not the packs. | ||
| blameCli = true; | ||
| } else { | ||
| // We have an old CLI, but the dbscheme pack is old enough that it's still a unified pack with | ||
| // both libraries and queries. Just search that pack. | ||
| packsToSearch.push(qlpacks.dbschemePack); | ||
| // Any CLI should be able to search the single query pack, so if we don't find it, it's | ||
| // because the language doesn't support it. | ||
| blameCli = false; | ||
| } | ||
| } | ||
|
|
||
| const queries = await resolveQueriesFromPacks(cli, packsToSearch, keyType); | ||
| if (queries.length > 0) { | ||
| return queries; | ||
| } | ||
|
|
||
| // No queries found. Determine the correct error message for the various scenarios. | ||
| const errorMessage = blameCli ? | ||
| `Your current version of the CodeQL CLI, '${(await cli.getVersion()).version}', \ | ||
| is unable to use contextual queries from recent versions of the standard CodeQL libraries. \ | ||
| Please upgrade to the latest version of the CodeQL CLI.` | ||
| : | ||
| `No ${nameOfKeyType(keyType)} queries (tagged "${tagOfKeyType(keyType)}") could be found in the current library path. \ | ||
| Try upgrading the CodeQL libraries. If that doesn't work, then ${nameOfKeyType(keyType)} queries are not yet available \ | ||
| for this language.`; | ||
|
|
||
| void helpers.showAndLogErrorMessage(errorMessage); | ||
| throw new Error(`Couldn't find any queries tagged ${tagOfKeyType(keyType)} in any of the following packs: ${packsToSearch.join(', ')}.`); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why wasn't this
asyncbefore?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, its only
returnstatement was returning an appropriately-typed promise from a function call, so there was no need to useawaitinside the implementation.