Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions extensions/ql-vscode/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,12 @@ export class CodeQLCliServer implements Disposable {
}
}

async packResolveDependencies(dir: string, mode: 'use-lock'): Promise<{ [pack: string]: string }> {
Comment thread
adityasharad marked this conversation as resolved.
Outdated
const args = ['--mode', mode, dir];
const results: { [pack: string]: string } = await this.runJsonCodeQlCliCommand(['pack', 'resolve-dependencies'], args, 'Resolving pack dependencies');
return results;
}

async generateDil(qloFile: string, outFile: string): Promise<void> {
const extraArgs = await this.cliConstraints.supportsDecompileDil()
? ['--kind', 'dil', '-o', outFile, qloFile]
Expand Down
71 changes: 61 additions & 10 deletions extensions/ql-vscode/src/contextual/templateProvider.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import {
CancellationToken,
DefinitionProvider,
Expand All @@ -14,6 +16,7 @@ import {
import { decodeSourceArchiveUri, encodeArchiveBasePath, zipArchiveScheme } from '../archive-filesystem-provider';
import { CodeQLCliServer } from '../cli';
import { DatabaseManager } from '../databases';
import { logger } from '../logging';
import { CachedOperation } from '../helpers';
import { ProgressCallback, withProgress } from '../commandRunner';
import AstBuilder from './astBuilder';
Expand All @@ -27,12 +30,11 @@ import { createInitialQueryInfo, QueryWithResults } from '../run-queries-shared'
import { QueryRunner } from '../queryRunner';

/**
* Run templated CodeQL queries to find definitions and references in
* Runs templated CodeQL queries to find definitions in
* source-language files. We may eventually want to find a way to
* generalize this to other custom queries, e.g. showing dataflow to
* or from a selected identifier.
*/

export class TemplateQueryDefinitionProvider implements DefinitionProvider {
private cache: CachedOperation<LocationLink[]>;

Expand Down Expand Up @@ -77,6 +79,12 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
}
}

/**
* Runs templated CodeQL queries to find references in
* source-language files. We may eventually want to find a way to
* generalize this to other custom queries, e.g. showing dataflow to
* or from a selected identifier.
*/
export class TemplateQueryReferenceProvider implements ReferenceProvider {
private cache: CachedOperation<FullLocationLink[]>;

Expand Down Expand Up @@ -131,6 +139,10 @@ type QueryWithDb = {
dbUri: Uri
};

/**
* Run templated CodeQL queries to produce AST information for
* source-language files.
*/
export class TemplatePrintAstProvider {
private cache: CachedOperation<QueryWithDb>;

Expand Down Expand Up @@ -199,6 +211,31 @@ export class TemplatePrintAstProvider {
zippedArchive.pathWithinSourceArchive
};

// The AST viewer queries now live within the standard library packs.
// This simplifies distribution (you don't need the standard query pack to use the AST viewer),
// but if the library pack doesn't have a lockfile, we won't be able to find
// other pack dependencies of the library pack.

// Work out the enclosing pack.
const packContents = await this.cli.packPacklist(query, false);
const packFilePath = packContents.find((p) => ['codeql-pack.yml', 'qlpack.yml'].includes(path.basename(p)));
if (packFilePath === undefined) {
// Should not happen; we already resolved this query.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this always true? What happens if you try to run a query in a directory that's outside of a qlpack?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not generally true, but I hope it is always true for our own contextual queries.

throw new Error(`Could not find a CodeQL pack file for the pack enclosing the query ${query}`);
}
const packPath = path.dirname(packFilePath);
const lockFilePath = packContents.find((p) => ['codeql-pack.lock.yml', 'qlpack.lock.yml'].includes(path.basename(p)));
if (!lockFilePath) {
// No lock file, likely because this library pack is in the package cache.
// Create a lock file so that we can resolve dependencies and library path
// for the AST query.
void logger.log(`Library pack ${packPath} is missing a lock file; creating a temporary lock file`);
await this.cli.packResolveDependencies(packPath, 'use-lock');
Comment thread
adityasharad marked this conversation as resolved.
Outdated
// Install dependencies.
void logger.log(`Installing package dependencies for library pack ${packPath}`);
await this.cli.packInstall(packPath);
Comment thread
adityasharad marked this conversation as resolved.
Outdated
}

const initialInfo = await createInitialQueryInfo(
Uri.file(query),
{
Expand All @@ -208,20 +245,34 @@ export class TemplatePrintAstProvider {
false
);

void logger.log(`Running AST query ${query}; results will be stored in ${this.queryStorageDir}`);
const queryResult = await this.qs.compileAndRunQueryAgainstDatabase(
db,
initialInfo,
this.queryStorageDir,
progress,
token,
templates
);

if (!lockFilePath) {
// Clean up the temporary lock file we created.
const tempLockFilePath = path.resolve(packPath, 'codeql-pack.lock.yml');
void logger.log(`Deleting temporary package lock file at ${tempLockFilePath}`);
// It's fine if the file doesn't exist.
fs.rmSync(path.resolve(packPath, 'codeql-pack.lock.yml'), { force: true });
Comment thread
adityasharad marked this conversation as resolved.
Outdated
}
return {
query: await this.qs.compileAndRunQueryAgainstDatabase(
db,
initialInfo,
this.queryStorageDir,
progress,
token,
templates
),
query: queryResult,
dbUri: db.databaseUri
};
}
}

/**
* Run templated CodeQL queries to produce CFG information for
* source-language files.
*/
export class TemplatePrintCfgProvider {
private cache: CachedOperation<[Uri, Record<string, string>] | undefined>;

Expand Down