/// <inheritdoc/>
        public async Task <Connection> ActivateAsync(CancellationToken token)
        {
            var path      = this.optionsModel.RustupPath == string.Empty ? "rustup" : this.optionsModel.RustupPath;
            var rustup    = new Rustup(path);
            var toolchain = this.optionsModel.Toolchain;
            var env       = await this.MakeEnvironmentAsync(rustup, toolchain);

            var directoryPath = this.workspaceService.CurrentWorkspace?.Location ?? string.Empty;
            var startInfo     = new ProcessStartInfo()
            {
                FileName               = path,
                Arguments              = $"run {toolchain} rls",
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                CreateNoWindow         = true,
                WorkingDirectory       = directoryPath,
            };

            foreach (var pair in env)
            {
                startInfo.Environment[pair.Key] = pair.Value;
            }

            var p = Process.Start(startInfo);

            return(new Connection(p.StandardOutput.BaseStream, p.StandardInput.BaseStream));
        }
        /// <inheritdoc/>
        public async Task OnLoadedAsync()
        {
            var rustup = new Rustup(this.optionsModel.RustupPath);

            if (!await rustup.IsInstalledAsync())
            {
                var infoBar = new VsUtilities.InfoBar("could not start the rls: rustup is not installed or not on the path");
                await VsUtilities.ShowInfoBarAsync(infoBar, this.serviceProvider);

                return;
            }

            var toolchain = this.optionsModel.Toolchain;

            if (!await rustup.HasToolchainAsync(toolchain))
            {
                var infoBar = new VsUtilities.InfoBar($"configured toolchain {toolchain} is not installed", new VsUtilities.InfoBarButton("Install"));
                if (await Utilities.WaitForSingleButtonInfoBarAsync(infoBar, this.serviceProvider))
                {
                    var task = rustup.InstallToolchainAsync(toolchain);
                    await VsUtilities.CreateTaskAsync($"Installing {toolchain}", this.serviceProvider, task);

                    if (await task != 0)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            // Check for necessary rls components
            if (!await rustup.HasComponentAsync("rls", toolchain) ||
                !await rustup.HasComponentAsync("rust-analysis", toolchain) ||
                !await rustup.HasComponentAsync("rust-src", toolchain))
            {
                if (!await this.InstallComponentsAsync(rustup, toolchain, "rls-preview", "rust-analysis", "rust-src"))
                {
                    var infoBar = new VsUtilities.InfoBar("could not install one of the required rls components");
                    await VsUtilities.ShowInfoBarAsync(infoBar, this.serviceProvider);

                    return;
                }
            }

            if (this.StartAsync != null)
            {
                await this.StartAsync.InvokeAsync(this, EventArgs.Empty);
            }
        }
        public async System.Threading.Tasks.Task OnLoadedAsync()
        {
            var toolchain = OptionsModel.Toolchain;

            if (!await Rustup.HasToolchain(toolchain))
            {
                var infoBar = new VsUtilities.InfoBar($"configured toolchain {toolchain} is not installed", new VsUtilities.InfoBarButton("Install"));
                if (await Utilities.WaitForSingleButtonInfoBarAsync(infoBar))
                {
                    var task = Rustup.InstallToolchain(toolchain).ContinueWith(t => t.Result == 0);
                    await VsUtilities.CreateTask($"Installing {toolchain}", task);

                    if (!await task)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            if (!await Rustup.HasComponent("rls-preview", toolchain))
            {
                if (!await InstallComponent("rls-preview", toolchain))
                {
                    return;
                }
            }

            if (!await Rustup.HasComponent("rust-analysis", toolchain))
            {
                if (!await InstallComponent("rust-analysis", toolchain))
                {
                    return;
                }
            }

            if (!await Rustup.HasComponent("rust-src", toolchain))
            {
                if (!await InstallComponent("rust-src", toolchain))
                {
                    return;
                }
            }

            if (StartAsync != null)
            {
                await StartAsync.InvokeAsync(this, EventArgs.Empty);
            }
        }
        private async Task <IDictionary <string, string> > MakeEnvironmentAsync(Rustup rustup, string toolchain)
        {
            var newEnv = new Dictionary <string, string>();

            if (Environment.GetEnvironmentVariable("RUST_SRC_PATH") == null)
            {
                var sysRoot = await this.GetSysRootAsync(rustup, toolchain);

                var srcPath = Path.Combine(sysRoot, "lib\\rustlib\\src\\rust\\src");
                newEnv["RUST_SRC_PATH"] = srcPath;
            }

            return(newEnv);
        }
        private async Task <bool> InstallComponent(string component, string toolchain)
        {
            var infoBar = new VsUtilities.InfoBar($"component '{component}' is not installed", new VsUtilities.InfoBarButton("Install"));

            if (await Utilities.WaitForSingleButtonInfoBarAsync(infoBar))
            {
                var task = Rustup.InstallComponent(component, toolchain).ContinueWith(t => t.Result == 0);
                await VsUtilities.CreateTask($"Installing {component}", task);

                return(await task);
            }
            else
            {
                return(false);
            }
        }
        private async Task <bool> InstallComponentsAsync(Rustup rustup, string toolchain, params string[] components)
        {
            VsUtilities.InfoBar infoBar;
            if (components.Length == 1)
            {
                infoBar = new VsUtilities.InfoBar($"component '{components[0]}' is not installed", new VsUtilities.InfoBarButton("Install"));
            }
            else
            {
                infoBar = new VsUtilities.InfoBar("required components are not installed", new VsUtilities.InfoBarButton("Install"));
            }

            if (await Utilities.WaitForSingleButtonInfoBarAsync(infoBar, this.serviceProvider))
            {
                var task = rustup.InstallComponentsAsync(toolchain, components);
                await VsUtilities.CreateTaskAsync($"Installing components", this.serviceProvider, task);

                return(await task == 0);
            }
            else
            {
                return(false);
            }
        }
        private async Task <string> GetSysRootAsync(Rustup rustup, string toolchain)
        {
            var result = await rustup.RunAsync("rustc --print sysroot", toolchain);

            return(result.Output.Replace("\n", string.Empty).Replace("\r", string.Empty));
        }
        private async Task <string> GetSysRoot(string toolchain)
        {
            var(sysRoot, _) = await Rustup.Run("rustc --print sysroot", toolchain);

            return(sysRoot.Replace("\n", "").Replace("\r", ""));
        }