1- import { writeFile , promises } from "fs-extra" ;
2- import { dump } from "js-yaml" ;
3- import { file } from "tmp-promise" ;
4- import { basename , dirname , resolve } from "path" ;
5-
61import { getOnDiskWorkspaceFolders } from "../../common/vscode/workspace-folders" ;
7- import {
8- getPrimaryDbscheme ,
9- getQlPackForDbscheme ,
10- QlPacksForLanguage ,
11- } from "../../databases/qlpack" ;
2+ import { QlPacksForLanguage } from "../../databases/qlpack" ;
123import {
134 KeyType ,
145 kindOfKeyType ,
@@ -17,154 +8,22 @@ import {
178} from "./key-type" ;
189import { CodeQLCliServer } from "../../codeql-cli/cli" ;
1910import { DatabaseItem } from "../../databases/local-databases" ;
11+ import { resolveQueries as resolveLocalQueries } from "../../local-queries/query-resolver" ;
2012import { extLogger } from "../../common/logging/vscode" ;
21- import {
22- showAndLogExceptionWithTelemetry ,
23- TeeLogger ,
24- } from "../../common/logging" ;
13+ import { TeeLogger } from "../../common/logging" ;
2514import { CancellationToken } from "vscode" ;
2615import { ProgressCallback } from "../../common/vscode/progress" ;
2716import { CoreCompletedQuery , QueryRunner } from "../../query-server" ;
28- import { redactableError } from "../../common/errors" ;
29- import { QLPACK_FILENAMES } from "../../common/ql" ;
30- import { telemetryListener } from "../../common/vscode/telemetry" ;
31-
32- export async function qlpackOfDatabase (
33- cli : Pick < CodeQLCliServer , "resolveQlpacks" > ,
34- db : Pick < DatabaseItem , "contents" > ,
35- ) : Promise < QlPacksForLanguage > {
36- if ( db . contents === undefined ) {
37- throw new Error ( "Database is invalid and cannot infer QLPack." ) ;
38- }
39- const datasetPath = db . contents . datasetUri . fsPath ;
40- const dbscheme = await getPrimaryDbscheme ( datasetPath ) ;
41- return await getQlPackForDbscheme ( cli , dbscheme ) ;
42- }
43-
44- /**
45- * Finds the contextual queries with the specified key in a list of CodeQL packs.
46- *
47- * @param cli The CLI instance to use.
48- * @param qlpacks The list of packs to search.
49- * @param keyType The contextual query key of the query to search for.
50- * @returns The found queries from the first pack in which any matching queries were found.
51- */
52- async function resolveQueriesFromPacks (
53- cli : CodeQLCliServer ,
54- qlpacks : string [ ] ,
55- keyType : KeyType ,
56- ) : Promise < string [ ] > {
57- const suiteFile = (
58- await file ( {
59- postfix : ".qls" ,
60- } )
61- ) . path ;
62- const suiteYaml = [ ] ;
63- for ( const qlpack of qlpacks ) {
64- suiteYaml . push ( {
65- from : qlpack ,
66- queries : "." ,
67- include : {
68- kind : kindOfKeyType ( keyType ) ,
69- "tags contain" : tagOfKeyType ( keyType ) ,
70- } ,
71- } ) ;
72- }
73- await writeFile ( suiteFile , dump ( suiteYaml ) , "utf8" ) ;
74-
75- const queries = await cli . resolveQueriesInSuite (
76- suiteFile ,
77- getOnDiskWorkspaceFolders ( ) ,
78- ) ;
79- return queries ;
80- }
17+ import { createLockFileForStandardQuery } from "../../local-queries/standard-queries" ;
8118
8219export async function resolveQueries (
8320 cli : CodeQLCliServer ,
8421 qlpacks : QlPacksForLanguage ,
8522 keyType : KeyType ,
8623) : Promise < string [ ] > {
87- const packsToSearch : string [ ] = [ ] ;
88-
89- // The CLI can handle both library packs and query packs, so search both packs in order.
90- packsToSearch . push ( qlpacks . dbschemePack ) ;
91- if ( qlpacks . queryPack !== undefined ) {
92- packsToSearch . push ( qlpacks . queryPack ) ;
93- }
94-
95- const queries = await resolveQueriesFromPacks ( cli , packsToSearch , keyType ) ;
96- if ( queries . length > 0 ) {
97- return queries ;
98- }
99-
100- // No queries found. Determine the correct error message for the various scenarios.
101- const keyTypeName = nameOfKeyType ( keyType ) ;
102- const keyTypeTag = tagOfKeyType ( keyType ) ;
103- const joinedPacksToSearch = packsToSearch . join ( ", " ) ;
104- const error = redactableError `No ${ keyTypeName } queries (tagged "${ keyTypeTag } ") could be found in the \
105- current library path (tried searching the following packs: ${ joinedPacksToSearch } ). \
106- Try upgrading the CodeQL libraries. If that doesn't work, then ${ keyTypeName } queries are not yet available \
107- for this language.` ;
108-
109- void showAndLogExceptionWithTelemetry ( extLogger , telemetryListener , error ) ;
110- throw error ;
111- }
112-
113- async function resolveContextualQuery (
114- cli : CodeQLCliServer ,
115- query : string ,
116- ) : Promise < { packPath : string ; createdTempLockFile : boolean } > {
117- // Contextual queries now live within the standard library packs.
118- // This simplifies distribution (you don't need the standard query pack to use the AST viewer),
119- // but if the library pack doesn't have a lockfile, we won't be able to find
120- // other pack dependencies of the library pack.
121-
122- // Work out the enclosing pack.
123- const packContents = await cli . packPacklist ( query , false ) ;
124- const packFilePath = packContents . find ( ( p ) =>
125- QLPACK_FILENAMES . includes ( basename ( p ) ) ,
126- ) ;
127- if ( packFilePath === undefined ) {
128- // Should not happen; we already resolved this query.
129- throw new Error (
130- `Could not find a CodeQL pack file for the pack enclosing the contextual query ${ query } ` ,
131- ) ;
132- }
133- const packPath = dirname ( packFilePath ) ;
134- const lockFilePath = packContents . find ( ( p ) =>
135- [ "codeql-pack.lock.yml" , "qlpack.lock.yml" ] . includes ( basename ( p ) ) ,
136- ) ;
137- let createdTempLockFile = false ;
138- if ( ! lockFilePath ) {
139- // No lock file, likely because this library pack is in the package cache.
140- // Create a lock file so that we can resolve dependencies and library path
141- // for the contextual query.
142- void extLogger . log (
143- `Library pack ${ packPath } is missing a lock file; creating a temporary lock file` ,
144- ) ;
145- await cli . packResolveDependencies ( packPath ) ;
146- createdTempLockFile = true ;
147- // Clear CLI server pack cache before installing dependencies,
148- // so that it picks up the new lock file, not the previously cached pack.
149- void extLogger . log ( "Clearing the CodeQL CLI server's pack cache" ) ;
150- await cli . clearCache ( ) ;
151- // Install dependencies.
152- void extLogger . log (
153- `Installing package dependencies for library pack ${ packPath } ` ,
154- ) ;
155- await cli . packInstall ( packPath ) ;
156- }
157- return { packPath, createdTempLockFile } ;
158- }
159-
160- async function removeTemporaryLockFile ( packPath : string ) {
161- const tempLockFilePath = resolve ( packPath , "codeql-pack.lock.yml" ) ;
162- void extLogger . log (
163- `Deleting temporary package lock file at ${ tempLockFilePath } ` ,
164- ) ;
165- // It's fine if the file doesn't exist.
166- await promises . rm ( resolve ( packPath , "codeql-pack.lock.yml" ) , {
167- force : true ,
24+ return resolveLocalQueries ( cli , qlpacks , nameOfKeyType ( keyType ) , {
25+ kind : kindOfKeyType ( keyType ) ,
26+ "tags contain" : [ tagOfKeyType ( keyType ) ] ,
16827 } ) ;
16928}
17029
@@ -178,10 +37,7 @@ export async function runContextualQuery(
17837 token : CancellationToken ,
17938 templates : Record < string , string > ,
18039) : Promise < CoreCompletedQuery > {
181- const { packPath, createdTempLockFile } = await resolveContextualQuery (
182- cli ,
183- query ,
184- ) ;
40+ const { cleanup } = await createLockFileForStandardQuery ( cli , query ) ;
18541 const queryRun = qs . createQueryRun (
18642 db . databaseUri . fsPath ,
18743 { queryPath : query , quickEvalPosition : undefined } ,
@@ -200,8 +56,6 @@ export async function runContextualQuery(
20056 token ,
20157 new TeeLogger ( qs . logger , queryRun . outputDir . logPath ) ,
20258 ) ;
203- if ( createdTempLockFile ) {
204- await removeTemporaryLockFile ( packPath ) ;
205- }
59+ await cleanup ?.( ) ;
20660 return results ;
20761}
0 commit comments