Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
75 changes: 75 additions & 0 deletions Extension/src/LanguageServer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ interface ConfigStateReceived {
timeout: boolean;
}

interface PendingTagParsingCall {
promise: ManualPromise<boolean>;
timer: NodeJS.Timeout;
cancellationListener: vscode.Disposable;
}

let workspaceHash: string = "";

let workspaceDisposables: vscode.Disposable[] = [];
Expand Down Expand Up @@ -805,6 +811,7 @@ export interface Client {
setCurrentConfigName(configurationName: string): Thenable<void>;
getCurrentConfigName(): Thenable<string | undefined>;
getCurrentConfigCustomVariable(variableName: string): Thenable<string>;
waitForTagParsing(timeout: number, token: vscode.CancellationToken): Promise<boolean>;
getVcpkgInstalled(): Thenable<boolean>;
getVcpkgEnabled(): Thenable<boolean>;
getCurrentCompilerPathAndArgs(): Thenable<util.CompilerPathAndArgs | undefined>;
Expand Down Expand Up @@ -919,6 +926,7 @@ export class DefaultClient implements Client {

private configStateReceived: ConfigStateReceived = { compilers: false, compileCommands: false, configProviders: undefined, timeout: false };
private showConfigureIntelliSenseButton: boolean = false;
private pendingTagParsingCalls: PendingTagParsingCall[] = [];

/** 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>]>();
Expand Down Expand Up @@ -1008,6 +1016,62 @@ export class DefaultClient implements Client {
};
}

// If there are any pending calls that were waiting for tag parsing to complete, we can resolve them since it's finished. If there are no pending calls, this does nothing.
private resolvePendingTagParsingCallsIfReady(): void {
if (!this.pendingTagParsingCalls.length || this.IsTagParsing) {
return;
}

const pendingCalls: PendingTagParsingCall[] = this.pendingTagParsingCalls;
this.pendingTagParsingCalls = [];
pendingCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.cancellationListener.dispose();
pendingCall.promise.resolve(true);
});
}

public async waitForTagParsing(timeout: number, token: vscode.CancellationToken): Promise<boolean> {
// On initialization, the client has UI bools all set to false which could cause an early return. We want to ensure it's ready first.
await this.ready;

if (!this.IsTagParsing) {
return true;
}

if (token.isCancellationRequested) {
throw new vscode.CancellationError();
Comment thread
sergior2 marked this conversation as resolved.
}

const pendingCall: PendingTagParsingCall = {
promise: new ManualPromise<boolean>(),

timer: global.setTimeout(() => {
const index: number = this.pendingTagParsingCalls.indexOf(pendingCall);
if (index !== -1) {
this.pendingTagParsingCalls.splice(index, 1);
}
pendingCall.cancellationListener.dispose();
pendingCall.promise.resolve(false);
}, timeout),

cancellationListener: token.onCancellationRequested(() => {
const index: number = this.pendingTagParsingCalls.indexOf(pendingCall);
if (index !== -1) {
this.pendingTagParsingCalls.splice(index, 1);
}
clearTimeout(pendingCall.timer);
pendingCall.cancellationListener.dispose();
pendingCall.promise.reject(new vscode.CancellationError());
})
};

this.pendingTagParsingCalls.push(pendingCall);
return pendingCall.promise;
}

private getName(workspaceFolder?: vscode.WorkspaceFolder): string {
return workspaceFolder ? workspaceFolder.name : "untitled";
}
Expand Down Expand Up @@ -2893,6 +2957,8 @@ export class DefaultClient implements Client {
} else if (message.includes("/")) {
this.lastInvokedLspMessage = message;
}

this.resolvePendingTagParsingCallsIfReady();
Comment thread
bobbrow marked this conversation as resolved.
}

private updateTagParseStatus(tagParseStatus: TagParseStatus): void {
Expand Down Expand Up @@ -4208,6 +4274,14 @@ export class DefaultClient implements Client {
}

public dispose(): void {
this.pendingTagParsingCalls.forEach(pendingCall => {
if (pendingCall.timer) {
clearTimeout(pendingCall.timer);
}
pendingCall.cancellationListener.dispose();
pendingCall.promise.resolve(false);
});
this.pendingTagParsingCalls = [];
this.disposables.forEach((d) => d.dispose());
this.disposables = [];
if (this.documentFormattingProviderDisposable) {
Expand Down Expand Up @@ -4360,6 +4434,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(""); }
waitForTagParsing(timeout: number, token: vscode.CancellationToken): 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); }
Expand Down
5 changes: 5 additions & 0 deletions Extension/src/LanguageServer/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,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('cpptools.waitForTagParsing', enabled ? onWaitForTagParsing : () => true));
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));
Expand Down Expand Up @@ -977,6 +978,10 @@ function onGetActiveConfigCustomVariable(variableName: string): Thenable<string>
return clients.ActiveClient.getCurrentConfigCustomVariable(variableName);
}

async function onWaitForTagParsing(timeout: number, token: vscode.CancellationToken): Promise<boolean> {
Comment thread
sergior2 marked this conversation as resolved.
return clients.getDefaultClient().waitForTagParsing(timeout, token);
}

function onLogDiagnostics(): Promise<void> {
return clients.ActiveClient.logDiagnostics();
}
Expand Down
Loading