Compare commits

...
2 changed files with 70 additions and 0 deletions
+62
View File
@@ -805,6 +805,7 @@ export interface Client {
setCurrentConfigName(configurationName: string): Thenable<void>;
getCurrentConfigName(): Thenable<string | undefined>;
getCurrentConfigCustomVariable(variableName: string): Thenable<string>;
waitForIdle(timeout?: number): Promise<boolean>;
getVcpkgInstalled(): Thenable<boolean>;
getVcpkgEnabled(): Thenable<boolean>;
getCurrentCompilerPathAndArgs(): Thenable<util.CompilerPathAndArgs | undefined>;
@@ -919,6 +920,7 @@ export class DefaultClient implements Client {
private configStateReceived: ConfigStateReceived = { compilers: false, compileCommands: false, configProviders: undefined, timeout: false };
private showConfigureIntelliSenseButton: boolean = false;
private pendingIdleCalls: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout }[] = [];
/** A queue of asynchronous tasks that need to be processed befofe ready is considered active. */
private static queue = new Array<[ManualPromise<unknown>, () => Promise<unknown>] | [ManualPromise<unknown>]>();
@@ -1008,6 +1010,56 @@ export class DefaultClient implements Client {
};
}
private isIdle(): boolean {
return !this.model.isInitializingWorkspace.Value
&& !this.model.isIndexingWorkspace.Value
&& !this.model.isParsingWorkspace.Value
&& !this.model.isParsingFiles.Value
&& !this.model.isUpdatingIntelliSense.Value;
}
private resolvePendingIdleCallsIfReady(): void {
if (!this.pendingIdleCalls.length || !this.isIdle()) {
return;
}
const pendingCalls: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout }[] = this.pendingIdleCalls;
this.pendingIdleCalls = [];
pendingCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.promise.resolve(true);
});
}
public async waitForIdle(timeout?: number): Promise<boolean> {
if (this.isIdle()) {
return true;
}
if (timeout !== undefined && timeout <= 0) {
return false;
}
const pendingCall: { promise: ManualPromise<boolean>; timer?: NodeJS.Timeout } = {
promise: new ManualPromise<boolean>()
};
if (timeout !== undefined) {
pendingCall.timer = global.setTimeout(() => {
const index: number = this.pendingIdleCalls.indexOf(pendingCall);
if (index !== -1) {
this.pendingIdleCalls.splice(index, 1);
}
pendingCall.promise.resolve(false);
}, timeout);
}
this.pendingIdleCalls.push(pendingCall);
return pendingCall.promise;
}
private getName(workspaceFolder?: vscode.WorkspaceFolder): string {
return workspaceFolder ? workspaceFolder.name : "untitled";
}
@@ -2892,6 +2944,8 @@ export class DefaultClient implements Client {
} else if (message.includes("/")) {
this.lastInvokedLspMessage = message;
}
this.resolvePendingIdleCallsIfReady();
}
private updateTagParseStatus(tagParseStatus: TagParseStatus): void {
@@ -4207,6 +4261,13 @@ export class DefaultClient implements Client {
}
public dispose(): void {
this.pendingIdleCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.promise.resolve(false);
});
this.pendingIdleCalls = [];
this.disposables.forEach((d) => d.dispose());
this.disposables = [];
if (this.documentFormattingProviderDisposable) {
@@ -4359,6 +4420,7 @@ class NullClient implements Client {
setCurrentConfigName(configurationName: string): Thenable<void> { return Promise.resolve(); }
getCurrentConfigName(): Thenable<string> { return Promise.resolve(""); }
getCurrentConfigCustomVariable(variableName: string): Thenable<string> { return Promise.resolve(""); }
waitForIdle(timeout?: number): Promise<boolean> { return Promise.resolve(true); }
getVcpkgInstalled(): Thenable<boolean> { return Promise.resolve(false); }
getVcpkgEnabled(): Thenable<boolean> { return Promise.resolve(false); }
getCurrentCompilerPathAndArgs(): Thenable<util.CompilerPathAndArgs | undefined> { return Promise.resolve(undefined); }
@@ -422,6 +422,7 @@ export async function registerCommands(enabled: boolean): Promise<void> {
commandDisposables.push(vscode.commands.registerCommand('cpptools.activeConfigName', enabled ? onGetActiveConfigName : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('cpptools.activeConfigCustomVariable', enabled ? onGetActiveConfigCustomVariable : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('cpptools.setActiveConfigName', enabled ? onSetActiveConfigName : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.waitForIdle', enabled ? onWaitForIdle : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.RestartIntelliSenseForFile', enabled ? onRestartIntelliSenseForFile : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.GenerateDoxygenComment', enabled ? onGenerateDoxygenComment : onDisabledCommand));
commandDisposables.push(vscode.commands.registerCommand('C_Cpp.CreateDeclarationOrDefinition', enabled ? onCreateDeclarationOrDefinition : onDisabledCommand));
@@ -906,6 +907,13 @@ function onRescanWorkspace(): Promise<void> {
return clients.ActiveClient.rescanFolder();
}
async function onWaitForIdle(timeout?: number): Promise<boolean> {
const pending: Promise<boolean>[] = [];
clients.forEach(client => pending.push(client.waitForIdle(timeout)));
const results: boolean[] = await Promise.all(pending);
return results.every(result => result);
}
function onShowRefCommand(arg?: TreeNode): void {
if (!arg) {
return;