1+ import * as fs from 'fs-extra' ;
2+ import * as path from 'path' ;
13import {
24 CancellationToken ,
35 DefinitionProvider ,
@@ -14,6 +16,7 @@ import {
1416import { decodeSourceArchiveUri , encodeArchiveBasePath , zipArchiveScheme } from '../archive-filesystem-provider' ;
1517import { CodeQLCliServer } from '../cli' ;
1618import { DatabaseManager } from '../databases' ;
19+ import { logger } from '../logging' ;
1720import { CachedOperation } from '../helpers' ;
1821import { ProgressCallback , withProgress } from '../commandRunner' ;
1922import AstBuilder from './astBuilder' ;
@@ -208,6 +211,31 @@ export class TemplatePrintAstProvider {
208211 zippedArchive . pathWithinSourceArchive
209212 } ;
210213
214+ // The AST viewer queries now live within the standard library packs.
215+ // This simplifies distribution (you don't need the standard query pack to use the AST viewer),
216+ // but if the library pack doesn't have a lockfile, we won't be able to find
217+ // other pack dependencies of the library pack.
218+
219+ // Work out the enclosing pack.
220+ const packContents = await this . cli . packPacklist ( query , false ) ;
221+ const packFilePath = packContents . find ( ( p ) => [ 'codeql-pack.yml' , 'qlpack.yml' ] . includes ( path . basename ( p ) ) ) ;
222+ if ( packFilePath === undefined ) {
223+ // Should not happen; we already resolved this query.
224+ throw new Error ( `Could not find a CodeQL pack file for the pack enclosing the query ${ query } ` ) ;
225+ }
226+ const packPath = path . dirname ( packFilePath ) ;
227+ const lockFilePath = packContents . find ( ( p ) => [ 'codeql-pack.lock.yml' , 'qlpack.lock.yml' ] . includes ( path . basename ( p ) ) ) ;
228+ if ( ! lockFilePath ) {
229+ // No lock file, likely because this library pack is in the package cache.
230+ // Create a lock file so that we can resolve dependencies and library path
231+ // for the AST query.
232+ void logger . log ( `Library pack ${ packPath } is missing a lock file; creating a temporary lock file` ) ;
233+ await this . cli . packResolveDependencies ( packPath , 'use-lock' ) ;
234+ // Install dependencies.
235+ void logger . log ( `Installing package dependencies for library pack ${ packPath } ` ) ;
236+ await this . cli . packInstall ( packPath ) ;
237+ }
238+
211239 const initialInfo = await createInitialQueryInfo (
212240 Uri . file ( query ) ,
213241 {
@@ -217,15 +245,25 @@ export class TemplatePrintAstProvider {
217245 false
218246 ) ;
219247
248+ void logger . log ( `Running AST query ${ query } ; results will be stored in ${ this . queryStorageDir } ` ) ;
249+ const queryResult = await this . qs . compileAndRunQueryAgainstDatabase (
250+ db ,
251+ initialInfo ,
252+ this . queryStorageDir ,
253+ progress ,
254+ token ,
255+ templates
256+ ) ;
257+
258+ if ( ! lockFilePath ) {
259+ // Clean up the temporary lock file we created.
260+ const tempLockFilePath = path . resolve ( packPath , 'codeql-pack.lock.yml' ) ;
261+ void logger . log ( `Deleting temporary package lock file at ${ tempLockFilePath } ` ) ;
262+ // It's fine if the file doesn't exist.
263+ fs . rmSync ( path . resolve ( packPath , 'codeql-pack.lock.yml' ) , { force : true } ) ;
264+ }
220265 return {
221- query : await this . qs . compileAndRunQueryAgainstDatabase (
222- db ,
223- initialInfo ,
224- this . queryStorageDir ,
225- progress ,
226- token ,
227- templates
228- ) ,
266+ query : queryResult ,
229267 dbUri : db . databaseUri
230268 } ;
231269 }
0 commit comments