private async Task ProjectConfigurationFilePathStore_ChangedAsync(ProjectConfigurationFilePathChangedEventArgs args, CancellationToken cancellationToken) { try { var parameter = new MonitorProjectConfigurationFilePathParams() { ProjectFilePath = args.ProjectFilePath, ConfigurationFilePath = args.ConfigurationFilePath, }; await _requestInvoker.ReinvokeRequestOnServerAsync <MonitorProjectConfigurationFilePathParams, object>( LanguageServerConstants.RazorMonitorProjectConfigurationFilePathEndpoint, RazorLSPConstants.RazorLanguageServerName, parameter, cancellationToken); } catch (Exception) { // We're fire and forgetting here, if the request fails we're ok with that. // // Note: When moving between solutions this can fail with a null reference exception because the underlying LSP platform's // JsonRpc object will be `null`. This can happen in two situations: // 1. There's currently a race in the platform on shutting down/activating so we don't get the opportunity to properly detatch // from the configuration file path store changed event properly. // Tracked by: https://github.com/dotnet/aspnetcore/issues/23819 // 2. The LSP platform failed to shutdown our language server properly due to a JsonRpc timeout. There's currently a limitation in // the LSP platform APIs where we don't know if the LSP platform requested shutdown but our language server never saw it. Therefore, // we will null-ref until our language server client boot-logic kicks back in and re-activates resulting in the old server being // being cleaned up. } }
public override void Set(string projectFilePath, string configurationFilePath) { if (projectFilePath is null) { throw new ArgumentNullException(nameof(projectFilePath)); } if (configurationFilePath is null) { throw new ArgumentNullException(nameof(configurationFilePath)); } lock (_mappingsLock) { // Resolve any relative pathing in the configuration path so we can talk in absolutes configurationFilePath = Path.GetFullPath(configurationFilePath); if (_mappings.TryGetValue(projectFilePath, out var existingConfigurationFilePath) && FilePathComparer.Instance.Equals(configurationFilePath, existingConfigurationFilePath)) { // Already have this mapping, don't invoke changed. return; } _mappings[projectFilePath] = configurationFilePath; } var args = new ProjectConfigurationFilePathChangedEventArgs(projectFilePath, configurationFilePath); Changed?.Invoke(this, args); }
private void ServerStarted() { _projectConfigurationFilePathStore.Changed += ProjectConfigurationFilePathStore_Changed; var mappings = _projectConfigurationFilePathStore.GetMappings(); foreach (var mapping in mappings) { var args = new ProjectConfigurationFilePathChangedEventArgs(mapping.Key, mapping.Value); ProjectConfigurationFilePathStore_Changed(this, args); } }
public override void Remove(string projectFilePath) { if (projectFilePath is null) { throw new ArgumentNullException(nameof(projectFilePath)); } lock (_mappingsLock) { if (!_mappings.Remove(projectFilePath)) { // We weren't tracking the project file path, no-op. return; } } var args = new ProjectConfigurationFilePathChangedEventArgs(projectFilePath, configurationFilePath: null); Changed?.Invoke(this, args); }
private void ProjectConfigurationFilePathStore_Changed(object sender, ProjectConfigurationFilePathChangedEventArgs args) { _ = ProjectConfigurationFilePathStore_ChangedAsync(args, CancellationToken.None); }