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:
@@ -132,26 +132,6 @@ interface BqrsDecodeOptions {
|
|||||||
*/
|
*/
|
||||||
export class CodeQLCliServer implements Disposable {
|
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 */
|
/** The process for the cli server, or undefined if one doesn't exist yet */
|
||||||
process?: child_process.ChildProcessWithoutNullStreams;
|
process?: child_process.ChildProcessWithoutNullStreams;
|
||||||
@@ -168,6 +148,8 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
/** Path to current codeQL executable, or undefined if not running yet. */
|
/** Path to current codeQL executable, or undefined if not running yet. */
|
||||||
codeQlPath: string | undefined;
|
codeQlPath: string | undefined;
|
||||||
|
|
||||||
|
cliConstraints = new CliVersionConstraint(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When set to true, ignore some modal popups and assume user has clicked "yes".
|
* 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];
|
const args = ['--additional-packs', searchPath.join(path.delimiter), '--dbscheme', dbScheme];
|
||||||
if (targetDbScheme) {
|
if (targetDbScheme) {
|
||||||
args.push('--target-dbscheme', targetDbScheme);
|
args.push('--target-dbscheme', targetDbScheme);
|
||||||
if (allowDowngradesIfPossible && await this.supportsDowngrades()) {
|
if (allowDowngradesIfPossible && await this.cliConstraints.supportsDowngrades()) {
|
||||||
args.push('--allow-downgrades');
|
args.push('--allow-downgrades');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,7 +751,7 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generateDil(qloFile: string, outFile: string): Promise<void> {
|
async generateDil(qloFile: string, outFile: string): Promise<void> {
|
||||||
const extraArgs = await this.supportsDecompileDil()
|
const extraArgs = await this.cliConstraints.supportsDecompileDil()
|
||||||
? ['--kind', 'dil', '-o', outFile, qloFile]
|
? ['--kind', 'dil', '-o', outFile, qloFile]
|
||||||
: ['-o', outFile, qloFile];
|
: ['-o', outFile, qloFile];
|
||||||
await this.runCodeQlCliCommand(
|
await this.runCodeQlCliCommand(
|
||||||
@@ -786,22 +768,6 @@ export class CodeQLCliServer implements Disposable {
|
|||||||
return this._version;
|
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() {
|
private async refreshVersion() {
|
||||||
const distribution = await this.distributionProvider.getDistribution();
|
const distribution = await this.distributionProvider.getDistribution();
|
||||||
switch (distribution.kind) {
|
switch (distribution.kind) {
|
||||||
@@ -1030,3 +996,60 @@ export function shouldDebugQueryServer() {
|
|||||||
&& process.env.QUERY_SERVER_JAVA_DEBUG !== '0'
|
&& process.env.QUERY_SERVER_JAVA_DEBUG !== '0'
|
||||||
&& process.env.QUERY_SERVER_JAVA_DEBUG?.toLocaleLowerCase() !== 'false';
|
&& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -808,7 +808,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
dbItem: DatabaseItem,
|
dbItem: DatabaseItem,
|
||||||
) {
|
) {
|
||||||
if (dbItem.contents && (await this.qs.supportsDatabaseRegistration())) {
|
if (dbItem.contents && (await this.cli.cliConstraints.supportsDatabaseRegistration())) {
|
||||||
const databases: Dataset[] = [{
|
const databases: Dataset[] = [{
|
||||||
dbDir: dbItem.contents.datasetUri.fsPath,
|
dbDir: dbItem.contents.datasetUri.fsPath,
|
||||||
workingSet: 'default'
|
workingSet: 'default'
|
||||||
@@ -822,7 +822,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
dbItem: DatabaseItem,
|
dbItem: DatabaseItem,
|
||||||
) {
|
) {
|
||||||
if (dbItem.contents && (await this.qs.supportsDatabaseRegistration())) {
|
if (dbItem.contents && (await this.cli.cliConstraints.supportsDatabaseRegistration())) {
|
||||||
const databases: Dataset[] = [{
|
const databases: Dataset[] = [{
|
||||||
dbDir: dbItem.contents.datasetUri.fsPath,
|
dbDir: dbItem.contents.datasetUri.fsPath,
|
||||||
workingSet: 'default'
|
workingSet: 'default'
|
||||||
@@ -852,7 +852,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getPrimaryLanguage(dbPath: string) {
|
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
|
// 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
|
// supports this feature. This recalculation is cheap since we avoid calling into the cli
|
||||||
// unless we know it can return the langauges property.
|
// unless we know it can return the langauges property.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { testExplorerExtensionId, TestHub } from 'vscode-test-adapter-api';
|
|||||||
|
|
||||||
import { AstViewer } from './astViewer';
|
import { AstViewer } from './astViewer';
|
||||||
import * as archiveFilesystemProvider from './archive-filesystem-provider';
|
import * as archiveFilesystemProvider from './archive-filesystem-provider';
|
||||||
import { CodeQLCliServer } from './cli';
|
import { CodeQLCliServer, CliVersionConstraint } from './cli';
|
||||||
import {
|
import {
|
||||||
CliConfigListener,
|
CliConfigListener,
|
||||||
DistributionConfigListener,
|
DistributionConfigListener,
|
||||||
@@ -484,7 +484,7 @@ async function activateWithInstalledDistribution(
|
|||||||
selectedQuery: Uri
|
selectedQuery: Uri
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (qs !== undefined) {
|
if (qs !== undefined) {
|
||||||
if (await cliServer.supportsResolveQlref()) {
|
if (await cliServer.cliConstraints.supportsResolveQlref()) {
|
||||||
const resolved = await cliServer.resolveQlref(selectedQuery.path);
|
const resolved = await cliServer.resolveQlref(selectedQuery.path);
|
||||||
const uri = Uri.file(resolved.resolvedPath);
|
const uri = Uri.file(resolved.resolvedPath);
|
||||||
await window.showTextDocument(uri, { preview: false });
|
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 '
|
'Jumping from a .qlref file to the .ql file it references is not '
|
||||||
+ 'supported with the CLI version you are running.\n'
|
+ 'supported with the CLI version you are running.\n'
|
||||||
+ `Please upgrade your CLI to version ${
|
+ `Please upgrade your CLI to version ${
|
||||||
CodeQLCliServer.CLI_VERSION_WITH_RESOLVE_QLREF
|
CliVersionConstraint.CLI_VERSION_WITH_RESOLVE_QLREF
|
||||||
} or later to use this feature.`);
|
} or later to use this feature.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ export class CachedOperation<U> {
|
|||||||
* `cli.CodeQLCliServer.resolveDatabase` and use the first entry in the
|
* `cli.CodeQLCliServer.resolveDatabase` and use the first entry in the
|
||||||
* `languages` property.
|
* `languages` property.
|
||||||
*
|
*
|
||||||
* @see cli.CodeQLCliServer.supportsLanguageName
|
* @see cli.CliVersionConstraint.supportsLanguageName
|
||||||
* @see cli.CodeQLCliServer.resolveDatabase
|
* @see cli.CodeQLCliServer.resolveDatabase
|
||||||
*/
|
*/
|
||||||
const dbSchemeToLanguage = {
|
const dbSchemeToLanguage = {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { QueryServerConfig } from './config';
|
|||||||
import { Logger, ProgressReporter } from './logging';
|
import { Logger, ProgressReporter } from './logging';
|
||||||
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './pure/messages';
|
import { completeQuery, EvaluationResult, progress, ProgressMessage, WithProgressId } from './pure/messages';
|
||||||
import * as messages from './pure/messages';
|
import * as messages from './pure/messages';
|
||||||
import { SemVer } from 'semver';
|
|
||||||
import { ProgressCallback, ProgressTask } from './commandRunner';
|
import { ProgressCallback, ProgressTask } from './commandRunner';
|
||||||
|
|
||||||
type ServerOpts = {
|
type ServerOpts = {
|
||||||
@@ -50,11 +49,6 @@ type WithProgressReporting = (task: (progress: ProgressReporter, token: Cancella
|
|||||||
*/
|
*/
|
||||||
export class QueryServerClient extends DisposableObject {
|
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;
|
serverProcess?: ServerProcess;
|
||||||
evaluationResultCallbacks: { [key: number]: (res: EvaluationResult) => void };
|
evaluationResultCallbacks: { [key: number]: (res: EvaluationResult) => void };
|
||||||
progressCallbacks: { [key: number]: ((res: ProgressMessage) => void) | undefined };
|
progressCallbacks: { [key: number]: ((res: ProgressMessage) => void) | undefined };
|
||||||
@@ -145,7 +139,7 @@ export class QueryServerClient extends DisposableObject {
|
|||||||
args.push(this.config.cacheSize.toString());
|
args.push(this.config.cacheSize.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await this.supportsDatabaseRegistration()) {
|
if (await this.cliServer.cliConstraints.supportsDatabaseRegistration()) {
|
||||||
args.push('--require-db-registration');
|
args.push('--require-db-registration');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,10 +196,6 @@ export class QueryServerClient extends DisposableObject {
|
|||||||
this.evaluationResultCallbacks = {};
|
this.evaluationResultCallbacks = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
async supportsDatabaseRegistration() {
|
|
||||||
return (await this.cliServer.getVersion()).compare(QueryServerClient.VERSION_WITH_DB_REGISTRATION) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerCallback(callback: (res: EvaluationResult) => void): number {
|
registerCallback(callback: (res: EvaluationResult) => void): number {
|
||||||
const id = this.nextCallback++;
|
const id = this.nextCallback++;
|
||||||
this.evaluationResultCallbacks[id] = callback;
|
this.evaluationResultCallbacks[id] = callback;
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ describe('using the query server', function() {
|
|||||||
const parsedResults = new Checkpoint<void>();
|
const parsedResults = new Checkpoint<void>();
|
||||||
|
|
||||||
it('should register the database if necessary', async () => {
|
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);
|
await qs.sendRequest(messages.registerDatabases, { databases: [db] }, token, (() => { /**/ }) as any);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -67,11 +67,13 @@ describe('databases', () => {
|
|||||||
} as unknown as ExtensionContext,
|
} as unknown as ExtensionContext,
|
||||||
{
|
{
|
||||||
sendRequest: sendRequestSpy,
|
sendRequest: sendRequestSpy,
|
||||||
supportsDatabaseRegistration: supportsDatabaseRegistrationSpy,
|
|
||||||
onDidStartQueryServer: () => { /**/ }
|
onDidStartQueryServer: () => { /**/ }
|
||||||
} as unknown as QueryServerClient,
|
} as unknown as QueryServerClient,
|
||||||
{
|
{
|
||||||
supportsLanguageName: supportsLanguageNameSpy,
|
cliConstraints: {
|
||||||
|
supportsLanguageName: supportsLanguageNameSpy,
|
||||||
|
supportsDatabaseRegistration: supportsDatabaseRegistrationSpy,
|
||||||
|
},
|
||||||
resolveDatabase: resolveDatabaseSpy
|
resolveDatabase: resolveDatabaseSpy
|
||||||
} as unknown as CodeQLCliServer,
|
} as unknown as CodeQLCliServer,
|
||||||
{} as Logger,
|
{} as Logger,
|
||||||
|
|||||||
Reference in New Issue
Block a user