constructor()

in Extension/src/LanguageServer/client.ts [882:1068]


    constructor(allClients: ClientCollection, workspaceFolder?: vscode.WorkspaceFolder) {
        this.rootFolder = workspaceFolder;
        this.rootRealPath = this.RootPath ? (fs.existsSync(this.RootPath) ? fs.realpathSync(this.RootPath) : this.RootPath) : "";
        let storagePath: string | undefined;
        if (util.extensionContext) {
            const path: string | undefined = util.extensionContext.storageUri?.fsPath;
            if (path) {
                storagePath = path;
            }
        }

        if (!storagePath) {
            storagePath = this.RootPath ? path.join(this.RootPath, "/.vscode") : "";
        }
        if (workspaceFolder && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 1) {
            storagePath = path.join(storagePath, util.getUniqueWorkspaceStorageName(workspaceFolder));
        }
        this.storagePath = storagePath;
        const rootUri: vscode.Uri | undefined = this.RootUri;
        this.settingsTracker = getTracker(rootUri);
        try {
            let firstClient: boolean = false;
            if (!languageClient || languageClientCrashedNeedsRestart) {
                if (languageClientCrashedNeedsRestart) {
                    languageClientCrashedNeedsRestart = false;
                }
                languageClient = this.createLanguageClient(allClients);
                clientCollection = allClients;
                languageClient.registerProposedFeatures();
                languageClient.start();  // This returns Disposable, but doesn't need to be tracked because we call .stop() explicitly in our dispose()
                util.setProgress(util.getProgressExecutableStarted());
                firstClient = true;
            }
            ui = getUI();
            ui.bind(this);

            // requests/notifications are deferred until this.languageClient is set.
            this.queueBlockingTask(async () => {
                await languageClient.onReady();
                try {
                    const workspaceFolder: vscode.WorkspaceFolder | undefined = this.rootFolder;
                    this.innerConfiguration = new configs.CppProperties(rootUri, workspaceFolder);
                    this.innerConfiguration.ConfigurationsChanged((e) => this.onConfigurationsChanged(e));
                    this.innerConfiguration.SelectionChanged((e) => this.onSelectedConfigurationChanged(e));
                    this.innerConfiguration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
                    this.disposables.push(this.innerConfiguration);

                    this.innerLanguageClient = languageClient;
                    telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
                    failureMessageShown = false;

                    class CodeActionProvider implements vscode.CodeActionProvider {
                        private client: DefaultClient;
                        constructor(client: DefaultClient) {
                            this.client = client;
                        }

                        public async provideCodeActions(document: vscode.TextDocument, range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise<(vscode.Command | vscode.CodeAction)[]> {
                            return this.client.requestWhenReady(async () => {
                                let r: Range;
                                if (range instanceof vscode.Selection) {
                                    if (range.active.isBefore(range.anchor)) {
                                        r = Range.create(Position.create(range.active.line, range.active.character), Position.create(range.anchor.line, range.anchor.character));
                                    } else {
                                        r = Range.create(Position.create(range.anchor.line, range.anchor.character), Position.create(range.active.line, range.active.character));
                                    }
                                } else {
                                    r = Range.create(Position.create(range.start.line, range.start.character), Position.create(range.end.line, range.end.character));
                                }

                                const params: GetCodeActionsRequestParams = {
                                    range: r,
                                    uri: document.uri.toString()
                                };

                                const commands: CodeActionCommand[] = await this.client.languageClient.sendRequest(GetCodeActionsRequest, params);
                                const resultCodeActions: vscode.CodeAction[] = [];

                                // Convert to vscode.CodeAction array
                                commands.forEach((command) => {
                                    const title: string = util.getLocalizedString(command.localizeStringParams);
                                    let edit: vscode.WorkspaceEdit | undefined;
                                    if (command.edit) {
                                        edit = new vscode.WorkspaceEdit();
                                        edit.replace(document.uri, new vscode.Range(
                                            new vscode.Position(command.edit.range.start.line, command.edit.range.start.character),
                                            new vscode.Position(command.edit.range.end.line, command.edit.range.end.character)),
                                        command.edit.newText);
                                    }
                                    const vscodeCodeAction: vscode.CodeAction = {
                                        title: title,
                                        command: command.command === "edit" ? undefined : {
                                            title: title,
                                            command: command.command,
                                            arguments: command.arguments
                                        },
                                        edit: edit,
                                        kind: edit === undefined ? vscode.CodeActionKind.QuickFix : vscode.CodeActionKind.RefactorInline
                                    };
                                    resultCodeActions.push(vscodeCodeAction);
                                });

                                return resultCodeActions;
                            });
                        }
                    }

                    // Semantic token types are identified by indexes in this list of types, in the legend.
                    const tokenTypesLegend: string[] = [];
                    for (const e in SemanticTokenTypes) {
                        // An enum is actually a set of mappings from key <=> value.  Enumerate over only the names.
                        // This allow us to represent the constants using an enum, which we can match in native code.
                        if (isNaN(Number(e))) {
                            tokenTypesLegend.push(e);
                        }
                    }
                    // Semantic token modifiers are bit indexes corresponding to the indexes in this list of modifiers in the legend.
                    const tokenModifiersLegend: string[] = [];
                    for (const e in SemanticTokenModifiers) {
                        if (isNaN(Number(e))) {
                            tokenModifiersLegend.push(e);
                        }
                    }
                    this.semanticTokensLegend = new vscode.SemanticTokensLegend(tokenTypesLegend, tokenModifiersLegend);

                    if (firstClient) {
                        workspaceReferences = new refs.ReferencesManager(this);

                        // The configurations will not be sent to the language server until the default include paths and frameworks have been set.
                        // The event handlers must be set before this happens.
                        const inputCompilerDefaults: configs.CompilerDefaults = await languageClient.sendRequest(QueryCompilerDefaultsRequest, {});
                        compilerDefaults = inputCompilerDefaults;
                        this.configuration.CompilerDefaults = compilerDefaults;

                        // Only register file watchers, providers, and the real commands after the extension has finished initializing,
                        // e.g. prevents empty c_cpp_properties.json from generation.
                        registerCommands();

                        this.registerFileWatcher();

                        this.disposables.push(vscode.languages.registerRenameProvider(this.documentSelector, new RenameProvider(this)));
                        this.disposables.push(vscode.languages.registerReferenceProvider(this.documentSelector, new FindAllReferencesProvider(this)));
                        this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this)));
                        this.disposables.push(vscode.languages.registerDocumentSymbolProvider(this.documentSelector, new DocumentSymbolProvider(this), undefined));
                        this.disposables.push(vscode.languages.registerCodeActionsProvider(this.documentSelector, new CodeActionProvider(this), undefined));
                        const settings: CppSettings = new CppSettings();
                        if (settings.formattingEngine !== "Disabled") {
                            this.documentFormattingProviderDisposable = vscode.languages.registerDocumentFormattingEditProvider(this.documentSelector, new DocumentFormattingEditProvider(this));
                            this.formattingRangeProviderDisposable = vscode.languages.registerDocumentRangeFormattingEditProvider(this.documentSelector, new DocumentRangeFormattingEditProvider(this));
                            this.onTypeFormattingProviderDisposable = vscode.languages.registerOnTypeFormattingEditProvider(this.documentSelector, new OnTypeFormattingEditProvider(this), ";", "}", "\n");
                        }
                        if (settings.codeFolding) {
                            this.codeFoldingProvider = new FoldingRangeProvider(this);
                            this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(this.documentSelector, this.codeFoldingProvider);
                        }
                        if (settings.enhancedColorization && this.semanticTokensLegend) {
                            this.semanticTokensProvider = new SemanticTokensProvider(this);
                            this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(this.documentSelector, this.semanticTokensProvider, this.semanticTokensLegend);
                        }
                        // Listen for messages from the language server.
                        this.registerNotifications();
                    } else {
                        this.configuration.CompilerDefaults = compilerDefaults;
                    }
                } catch (err) {
                    this.isSupported = false;   // Running on an OS we don't support yet.
                    if (!failureMessageShown) {
                        failureMessageShown = true;
                        vscode.window.showErrorMessage(localize("unable.to.start", "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}", String(err)));
                    }
                }
            });
        } catch (errJS) {
            const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException;
            this.isSupported = false;   // Running on an OS we don't support yet.
            if (!failureMessageShown) {
                failureMessageShown = true;
                let additionalInfo: string;
                if (err.code === "EPERM") {
                    additionalInfo = localize('check.permissions', "EPERM: Check permissions for '{0}'", getLanguageServerFileName());
                } else {
                    additionalInfo = String(err);
                }
                vscode.window.showErrorMessage(localize("unable.to.start", "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}", additionalInfo));
            }
        }
    }