Refactor version constraints

A simple refactoring that simplifies and unifies how we check if a
feature is supported by a specific cli version.
This commit is contained in:
Andrew Eisenberg
2021-04-09 15:32:10 -07:00
parent 5b08fd0df1
commit bdb2feb559
7 changed files with 74 additions and 59 deletions

View File

@@ -132,26 +132,6 @@ interface BqrsDecodeOptions {
*/
export class CodeQLCliServer implements Disposable {
/**
* CLI version where --kind=DIL was introduced
*/
private static CLI_VERSION_WITH_DECOMPILE_KIND_DIL = new SemVer('2.3.0');
/**
* CLI version where languages are exposed during a `codeql resolve database` command.
*/
private static CLI_VERSION_WITH_LANGUAGE = new SemVer('2.4.1');
/**
* CLI version where `codeql resolve upgrades` supports
* the `--allow-downgrades` flag
*/
private static CLI_VERSION_WITH_DOWNGRADES = new SemVer('2.4.4');
/**
* CLI version where the `codeql resolve qlref` command is available.
*/
public static CLI_VERSION_WITH_RESOLVE_QLREF = new SemVer('2.5.1');
/** The process for the cli server, or undefined if one doesn't exist yet */
process?: child_process.ChildProcessWithoutNullStreams;
@@ -168,6 +148,8 @@ export class CodeQLCliServer implements Disposable {
/** Path to current codeQL executable, or undefined if not running yet. */
codeQlPath: string | undefined;
cliConstraints = new CliVersionConstraint(this);
/**
* When set to true, ignore some modal popups and assume user has clicked "yes".
*/
@@ -716,7 +698,7 @@ export class CodeQLCliServer implements Disposable {
const args = ['--additional-packs', searchPath.join(path.delimiter), '--dbscheme', dbScheme];
if (targetDbScheme) {
args.push('--target-dbscheme', targetDbScheme);
if (allowDowngradesIfPossible && await this.supportsDowngrades()) {
if (allowDowngradesIfPossible && await this.cliConstraints.supportsDowngrades()) {
args.push('--allow-downgrades');
}
}
@@ -769,7 +751,7 @@ export class CodeQLCliServer implements Disposable {
}
async generateDil(qloFile: string, outFile: string): Promise<void> {
const extraArgs = await this.supportsDecompileDil()
const extraArgs = await this.cliConstraints.supportsDecompileDil()
? ['--kind', 'dil', '-o', outFile, qloFile]
: ['-o', outFile, qloFile];
await this.runCodeQlCliCommand(
@@ -786,22 +768,6 @@ export class CodeQLCliServer implements Disposable {
return this._version;
}
private async supportsDecompileDil() {
return (await this.getVersion()).compare(CodeQLCliServer.CLI_VERSION_WITH_DECOMPILE_KIND_DIL) >= 0;
}
public async supportsLanguageName() {
return (await this.getVersion()).compare(CodeQLCliServer.CLI_VERSION_WITH_LANGUAGE) >= 0;
}
public async supportsDowngrades() {
return (await this.getVersion()).compare(CodeQLCliServer.CLI_VERSION_WITH_DOWNGRADES) >= 0;
}
public async supportsResolveQlref() {
return (await this.getVersion()).compare(CodeQLCliServer.CLI_VERSION_WITH_RESOLVE_QLREF) >= 0;
}
private async refreshVersion() {
const distribution = await this.distributionProvider.getDistribution();
switch (distribution.kind) {
@@ -1030,3 +996,60 @@ export function shouldDebugQueryServer() {
&& process.env.QUERY_SERVER_JAVA_DEBUG !== '0'
&& process.env.QUERY_SERVER_JAVA_DEBUG?.toLocaleLowerCase() !== 'false';
}
export class CliVersionConstraint {
/**
* CLI version where --kind=DIL was introduced
*/
public static CLI_VERSION_WITH_DECOMPILE_KIND_DIL = new SemVer('2.3.0');
/**
* CLI version where languages are exposed during a `codeql resolve database` command.
*/
public static CLI_VERSION_WITH_LANGUAGE = new SemVer('2.4.1');
/**
* CLI version where `codeql resolve upgrades` supports
* the `--allow-downgrades` flag
*/
public static CLI_VERSION_WITH_DOWNGRADES = new SemVer('2.4.4');
/**
* CLI version where the `codeql resolve qlref` command is available.
*/
public static CLI_VERSION_WITH_RESOLVE_QLREF = new SemVer('2.5.1');
/**
* CLI version where database registration was introduced
*/
public static CLI_VERSION_WITH_DB_REGISTRATION = new SemVer('2.4.1');
constructor(private readonly cli: CodeQLCliServer) {
/**/
}
private async isVersionAtLeast(v: SemVer) {
return (await this.cli.getVersion()).compare(v) >= 0;
}
public async supportsDecompileDil() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_DECOMPILE_KIND_DIL);
}
public async supportsLanguageName() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_LANGUAGE);
}
public async supportsDowngrades() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_DOWNGRADES);
}
public async supportsResolveQlref() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_RESOLVE_QLREF);
}
async supportsDatabaseRegistration() {
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_WITH_DB_REGISTRATION);
}
}

View File

@@ -808,7 +808,7 @@ export class DatabaseManager extends DisposableObject {
token: vscode.CancellationToken,
dbItem: DatabaseItem,
) {
if (dbItem.contents && (await this.qs.supportsDatabaseRegistration())) {
if (dbItem.contents && (await this.cli.cliConstraints.supportsDatabaseRegistration())) {
const databases: Dataset[] = [{
dbDir: dbItem.contents.datasetUri.fsPath,
workingSet: 'default'
@@ -822,7 +822,7 @@ export class DatabaseManager extends DisposableObject {
token: vscode.CancellationToken,
dbItem: DatabaseItem,
) {
if (dbItem.contents && (await this.qs.supportsDatabaseRegistration())) {
if (dbItem.contents && (await this.cli.cliConstraints.supportsDatabaseRegistration())) {
const databases: Dataset[] = [{
dbDir: dbItem.contents.datasetUri.fsPath,
workingSet: 'default'
@@ -852,7 +852,7 @@ export class DatabaseManager extends DisposableObject {
}
private async getPrimaryLanguage(dbPath: string) {
if (!(await this.cli.supportsLanguageName())) {
if (!(await this.cli.cliConstraints.supportsLanguageName())) {
// return undefined so that we recalculate on restart until the cli is at a version that
// supports this feature. This recalculation is cheap since we avoid calling into the cli
// unless we know it can return the langauges property.

View File

@@ -18,7 +18,7 @@ import { testExplorerExtensionId, TestHub } from 'vscode-test-adapter-api';
import { AstViewer } from './astViewer';
import * as archiveFilesystemProvider from './archive-filesystem-provider';
import { CodeQLCliServer } from './cli';
import { CodeQLCliServer, CliVersionConstraint } from './cli';
import {
CliConfigListener,
DistributionConfigListener,
@@ -484,7 +484,7 @@ async function activateWithInstalledDistribution(
selectedQuery: Uri
): Promise<void> {
if (qs !== undefined) {
if (await cliServer.supportsResolveQlref()) {
if (await cliServer.cliConstraints.supportsResolveQlref()) {
const resolved = await cliServer.resolveQlref(selectedQuery.path);
const uri = Uri.file(resolved.resolvedPath);
await window.showTextDocument(uri, { preview: false });
@@ -493,7 +493,7 @@ async function activateWithInstalledDistribution(
'Jumping from a .qlref file to the .ql file it references is not '
+ 'supported with the CLI version you are running.\n'
+ `Please upgrade your CLI to version ${
CodeQLCliServer.CLI_VERSION_WITH_RESOLVE_QLREF
CliVersionConstraint.CLI_VERSION_WITH_RESOLVE_QLREF
} or later to use this feature.`);
}
}

View File

@@ -367,7 +367,7 @@ export class CachedOperation<U> {
* `cli.CodeQLCliServer.resolveDatabase` and use the first entry in the
* `languages` property.
*
* @see cli.CodeQLCliServer.supportsLanguageName
* @see cli.CliVersionConstraint.supportsLanguageName
* @see cli.CodeQLCliServer.resolveDatabase
*/
const dbSchemeToLanguage = {

View File

@@ -8,7 +8,6 @@ import { QueryServerConfig } from './config';
import { Logger, ProgressReporter } from './logging';
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './pure/messages';
import * as messages from './pure/messages';
import { SemVer } from 'semver';
import { ProgressCallback, ProgressTask } from './commandRunner';
type ServerOpts = {
@@ -50,11 +49,6 @@ type WithProgressReporting = (task: (progress: ProgressReporter, token: Cancella
*/
export class QueryServerClient extends DisposableObject {
/**
* Query Server version where database registration was introduced
*/
private static VERSION_WITH_DB_REGISTRATION = new SemVer('2.4.1');
serverProcess?: ServerProcess;
evaluationResultCallbacks: { [key: number]: (res: EvaluationResult) => void };
progressCallbacks: { [key: number]: ((res: ProgressMessage) => void) | undefined };
@@ -145,7 +139,7 @@ export class QueryServerClient extends DisposableObject {
args.push(this.config.cacheSize.toString());
}
if (await this.supportsDatabaseRegistration()) {
if (await this.cliServer.cliConstraints.supportsDatabaseRegistration()) {
args.push('--require-db-registration');
}
@@ -202,10 +196,6 @@ export class QueryServerClient extends DisposableObject {
this.evaluationResultCallbacks = {};
}
async supportsDatabaseRegistration() {
return (await this.cliServer.getVersion()).compare(QueryServerClient.VERSION_WITH_DB_REGISTRATION) >= 0;
}
registerCallback(callback: (res: EvaluationResult) => void): number {
const id = this.nextCallback++;
this.evaluationResultCallbacks[id] = callback;

View File

@@ -129,7 +129,7 @@ describe('using the query server', function() {
const parsedResults = new Checkpoint<void>();
it('should register the database if necessary', async () => {
if (await qs.supportsDatabaseRegistration()) {
if (await cliServer.cliConstraints.supportsDatabaseRegistration()) {
await qs.sendRequest(messages.registerDatabases, { databases: [db] }, token, (() => { /**/ }) as any);
}
});

View File

@@ -67,11 +67,13 @@ describe('databases', () => {
} as unknown as ExtensionContext,
{
sendRequest: sendRequestSpy,
supportsDatabaseRegistration: supportsDatabaseRegistrationSpy,
onDidStartQueryServer: () => { /**/ }
} as unknown as QueryServerClient,
{
supportsLanguageName: supportsLanguageNameSpy,
cliConstraints: {
supportsLanguageName: supportsLanguageNameSpy,
supportsDatabaseRegistration: supportsDatabaseRegistrationSpy,
},
resolveDatabase: resolveDatabaseSpy
} as unknown as CodeQLCliServer,
{} as Logger,