예제 #1
0
        private void SendFeatureChangesTelemetry(LanguageServerSettingsWrapper incomingSettings)
        {
            if (incomingSettings is null)
            {
                this._logger.LogTrace("Incoming settings were null");
                return;
            }

            var configChanges = new Dictionary <string, bool>();

            // Send telemetry if the user opted-out of ScriptAnalysis
            if (incomingSettings.Powershell.ScriptAnalysis.Enable == false &&
                _configurationService.CurrentSettings.ScriptAnalysis.Enable != incomingSettings.Powershell.ScriptAnalysis.Enable)
            {
                configChanges["ScriptAnalysis"] = incomingSettings.Powershell.ScriptAnalysis.Enable ?? false;
            }

            // Send telemetry if the user opted-out of CodeFolding
            if (!incomingSettings.Powershell.CodeFolding.Enable &&
                _configurationService.CurrentSettings.CodeFolding.Enable != incomingSettings.Powershell.CodeFolding.Enable)
            {
                configChanges["CodeFolding"] = incomingSettings.Powershell.CodeFolding.Enable;
            }

            // Send telemetry if the user opted-out of the prompt to update PackageManagement
            if (!incomingSettings.Powershell.PromptToUpdatePackageManagement &&
                _configurationService.CurrentSettings.PromptToUpdatePackageManagement != incomingSettings.Powershell.PromptToUpdatePackageManagement)
            {
                configChanges["PromptToUpdatePackageManagement"] = incomingSettings.Powershell.PromptToUpdatePackageManagement;
            }

            // Send telemetry if the user opted-out of Profile loading
            if (!incomingSettings.Powershell.EnableProfileLoading &&
                _configurationService.CurrentSettings.EnableProfileLoading != incomingSettings.Powershell.EnableProfileLoading)
            {
                configChanges["ProfileLoading"] = incomingSettings.Powershell.EnableProfileLoading;
            }

            // Send telemetry if the user opted-in to Pester 5+ CodeLens
            if (!incomingSettings.Powershell.Pester.UseLegacyCodeLens &&
                _configurationService.CurrentSettings.Pester.UseLegacyCodeLens != incomingSettings.Powershell.Pester.UseLegacyCodeLens)
            {
                // From our perspective we want to see how many people are opting in to this so we flip the value
                configChanges["Pester5CodeLens"] = !incomingSettings.Powershell.Pester.UseLegacyCodeLens;
            }

            // No need to send any telemetry since nothing changed
            if (configChanges.Count == 0)
            {
                return;
            }

            _languageServer.Window.SendTelemetryEvent(new TelemetryEventParams
            {
                ExtensionData = new PsesTelemetryEvent
                {
                    EventName = "NonDefaultPsesFeatureConfiguration",
                    Data      = JObject.FromObject(configChanges)
                }
            });
        }
        public async Task <Unit> Handle(DidChangeConfigurationParams request, CancellationToken cancellationToken)
        {
            LanguageServerSettingsWrapper incomingSettings = request.Settings.ToObject <LanguageServerSettingsWrapper>();

            if (incomingSettings == null)
            {
                return(await Unit.Task.ConfigureAwait(false));
            }

            bool oldLoadProfiles          = _configurationService.CurrentSettings.EnableProfileLoading;
            bool oldScriptAnalysisEnabled =
                _configurationService.CurrentSettings.ScriptAnalysis.Enable ?? false;
            string oldScriptAnalysisSettingsPath =
                _configurationService.CurrentSettings.ScriptAnalysis?.SettingsPath;

            _configurationService.CurrentSettings.Update(
                incomingSettings.Powershell,
                _workspaceService.WorkspacePath,
                _logger);

            if (!this._profilesLoaded &&
                _configurationService.CurrentSettings.EnableProfileLoading &&
                oldLoadProfiles != _configurationService.CurrentSettings.EnableProfileLoading)
            {
                await _powerShellContextService.LoadHostProfilesAsync().ConfigureAwait(false);

                this._profilesLoaded = true;
            }

            // Wait until after profiles are loaded (or not, if that's the
            // case) before starting the interactive console.
            if (!this._consoleReplStarted)
            {
                // Start the interactive terminal
                _powerShellContextService.ConsoleReader.StartCommandLoop();
                this._consoleReplStarted = true;
            }

            // If there is a new settings file path, restart the analyzer with the new settings.
            bool   settingsPathChanged = false;
            string newSettingsPath     = _configurationService.CurrentSettings.ScriptAnalysis.SettingsPath;

            if (!string.Equals(oldScriptAnalysisSettingsPath, newSettingsPath, StringComparison.OrdinalIgnoreCase))
            {
                if (_analysisService != null)
                {
                    _analysisService.SettingsPath = newSettingsPath;
                    settingsPathChanged           = true;
                }
            }

            // If script analysis settings have changed we need to clear & possibly update the current diagnostic records.
            if ((oldScriptAnalysisEnabled != _configurationService.CurrentSettings.ScriptAnalysis?.Enable) || settingsPathChanged)
            {
                // If the user just turned off script analysis or changed the settings path, send a diagnostics
                // event to clear the analysis markers that they already have.
                if (!_configurationService.CurrentSettings.ScriptAnalysis.Enable.Value || settingsPathChanged)
                {
                    foreach (var scriptFile in _workspaceService.GetOpenedFiles())
                    {
                        _analysisService.ClearMarkers(scriptFile);
                    }
                }
            }

            // Convert the editor file glob patterns into an array for the Workspace
            // Both the files.exclude and search.exclude hash tables look like (glob-text, is-enabled):
            // "files.exclude" : {
            //     "Makefile": true,
            //     "*.html": true,
            //     "build/*": true
            // }
            var excludeFilePatterns = new List <string>();

            if (incomingSettings.Files?.Exclude != null)
            {
                foreach (KeyValuePair <string, bool> patternEntry in incomingSettings.Files.Exclude)
                {
                    if (patternEntry.Value)
                    {
                        excludeFilePatterns.Add(patternEntry.Key);
                    }
                }
            }
            if (incomingSettings.Search?.Exclude != null)
            {
                foreach (KeyValuePair <string, bool> patternEntry in incomingSettings.Files.Exclude)
                {
                    if (patternEntry.Value && !excludeFilePatterns.Contains(patternEntry.Key))
                    {
                        excludeFilePatterns.Add(patternEntry.Key);
                    }
                }
            }
            _workspaceService.ExcludeFilesGlob = excludeFilePatterns;

            // Convert the editor file search options to Workspace properties
            if (incomingSettings.Search?.FollowSymlinks != null)
            {
                _workspaceService.FollowSymlinks = incomingSettings.Search.FollowSymlinks;
            }

            return(await Unit.Task.ConfigureAwait(false));
        }
        public async Task <Unit> Handle(DidChangeConfigurationParams request, CancellationToken cancellationToken)
        {
            LanguageServerSettingsWrapper incomingSettings = request.Settings.ToObject <LanguageServerSettingsWrapper>();

            if (incomingSettings == null)
            {
                return(await Unit.Task.ConfigureAwait(false));
            }

            bool oldLoadProfiles          = _configurationService.CurrentSettings.EnableProfileLoading;
            bool oldScriptAnalysisEnabled =
                _configurationService.CurrentSettings.ScriptAnalysis.Enable ?? false;
            string oldScriptAnalysisSettingsPath =
                _configurationService.CurrentSettings.ScriptAnalysis?.SettingsPath;

            _configurationService.CurrentSettings.Update(
                incomingSettings.Powershell,
                _workspaceService.WorkspacePath,
                _logger);

            if (!this._cwdSet)
            {
                if (!string.IsNullOrEmpty(_configurationService.CurrentSettings.Cwd) &&
                    Directory.Exists(_configurationService.CurrentSettings.Cwd))
                {
                    await _powerShellContextService.SetWorkingDirectoryAsync(
                        _configurationService.CurrentSettings.Cwd,
                        isPathAlreadyEscaped : false).ConfigureAwait(false);
                }
                else if (_workspaceService.WorkspacePath != null &&
                         Directory.Exists(_workspaceService.WorkspacePath))
                {
                    await _powerShellContextService.SetWorkingDirectoryAsync(
                        _workspaceService.WorkspacePath,
                        isPathAlreadyEscaped : false).ConfigureAwait(false);
                }

                this._cwdSet = true;
            }

            if (!this._profilesLoaded &&
                _configurationService.CurrentSettings.EnableProfileLoading &&
                oldLoadProfiles != _configurationService.CurrentSettings.EnableProfileLoading)
            {
                await _powerShellContextService.LoadHostProfilesAsync().ConfigureAwait(false);

                this._profilesLoaded = true;
            }

            // Wait until after profiles are loaded (or not, if that's the
            // case) before starting the interactive console.
            if (!this._consoleReplStarted)
            {
                // Start the interactive terminal
                _powerShellContextService.ConsoleReader.StartCommandLoop();
                this._consoleReplStarted = true;
            }

            // Run any events subscribed to configuration updates
            ConfigurationUpdated(this, _configurationService.CurrentSettings);

            // Convert the editor file glob patterns into an array for the Workspace
            // Both the files.exclude and search.exclude hash tables look like (glob-text, is-enabled):
            // "files.exclude" : {
            //     "Makefile": true,
            //     "*.html": true,
            //     "build/*": true
            // }
            var excludeFilePatterns = new List <string>();

            if (incomingSettings.Files?.Exclude != null)
            {
                foreach (KeyValuePair <string, bool> patternEntry in incomingSettings.Files.Exclude)
                {
                    if (patternEntry.Value)
                    {
                        excludeFilePatterns.Add(patternEntry.Key);
                    }
                }
            }
            if (incomingSettings.Search?.Exclude != null)
            {
                foreach (KeyValuePair <string, bool> patternEntry in incomingSettings.Search.Exclude)
                {
                    if (patternEntry.Value && !excludeFilePatterns.Contains(patternEntry.Key))
                    {
                        excludeFilePatterns.Add(patternEntry.Key);
                    }
                }
            }
            _workspaceService.ExcludeFilesGlob = excludeFilePatterns;

            // Convert the editor file search options to Workspace properties
            if (incomingSettings.Search?.FollowSymlinks != null)
            {
                _workspaceService.FollowSymlinks = incomingSettings.Search.FollowSymlinks;
            }

            return(await Unit.Task.ConfigureAwait(false));
        }
        public override async Task <Unit> Handle(DidChangeConfigurationParams request, CancellationToken cancellationToken)
        {
            LanguageServerSettingsWrapper incomingSettings = request.Settings.ToObject <LanguageServerSettingsWrapper>();

            _logger.LogTrace("Handling DidChangeConfiguration");
            if (incomingSettings is null || incomingSettings.Powershell is null)
            {
                _logger.LogTrace("Incoming settings were null");
                return(await Unit.Task.ConfigureAwait(false));
            }

            SendFeatureChangesTelemetry(incomingSettings);

            bool   profileLoadingPreviouslyEnabled = _configurationService.CurrentSettings.EnableProfileLoading;
            bool   oldScriptAnalysisEnabled        = _configurationService.CurrentSettings.ScriptAnalysis.Enable;
            string oldScriptAnalysisSettingsPath   = _configurationService.CurrentSettings.ScriptAnalysis?.SettingsPath;

            _configurationService.CurrentSettings.Update(
                incomingSettings.Powershell,
                _workspaceService.WorkspacePath,
                _logger);

            // We need to load the profiles if:
            // - Profile loading is configured, AND
            //   - Profiles haven't been loaded before, OR
            //   - The profile loading configuration just changed
            bool loadProfiles = _configurationService.CurrentSettings.EnableProfileLoading &&
                                (!_profilesLoaded || !profileLoadingPreviouslyEnabled);

            if (!_psesHost.IsRunning)
            {
                _logger.LogTrace("Starting command loop");

                if (loadProfiles)
                {
                    _logger.LogTrace("Loading profiles...");
                }

                await _psesHost.TryStartAsync(new HostStartOptions { LoadProfiles = loadProfiles }, CancellationToken.None).ConfigureAwait(false);

                if (loadProfiles)
                {
                    _profilesLoaded = true;
                    _logger.LogTrace("Loaded!");
                }
            }

            // TODO: Load profiles when the host is already running? Note that this might mess up
            // the ordering and require the foreground.
            if (!_cwdSet)
            {
                if (!string.IsNullOrEmpty(_configurationService.CurrentSettings.Cwd) &&
                    Directory.Exists(_configurationService.CurrentSettings.Cwd))
                {
                    _logger.LogTrace($"Setting CWD (from config) to {_configurationService.CurrentSettings.Cwd}");
                    await _psesHost.SetInitialWorkingDirectoryAsync(
                        _configurationService.CurrentSettings.Cwd,
                        CancellationToken.None).ConfigureAwait(false);
                }
                else if (_workspaceService.WorkspacePath is not null &&
                         Directory.Exists(_workspaceService.WorkspacePath))
                {
                    _logger.LogTrace($"Setting CWD (from workspace) to {_workspaceService.WorkspacePath}");
                    await _psesHost.SetInitialWorkingDirectoryAsync(
                        _workspaceService.WorkspacePath,
                        CancellationToken.None).ConfigureAwait(false);
                }
                else
                {
                    _logger.LogTrace("Tried to set CWD but in bad state");
                }

                _cwdSet = true;
            }