Skip to content

Fixed configuration issue where data was being cleared of previous sections #317

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 15, 2020
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
2 changes: 1 addition & 1 deletion sample/SampleServer/TextDocumentHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public async Task<Unit> Handle(DidOpenTextDocumentParams notification, Cancellat
{
await Task.Yield();
_logger.LogInformation("Hello world!");
await _configuration.GetScopedConfiguration(notification.TextDocument.Uri);
await _configuration.GetScopedConfiguration(notification.TextDocument.Uri, token);
return Unit.Value;
}

Expand Down
30 changes: 29 additions & 1 deletion src/Protocol/Models/ConfigurationItem.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
using System;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
{
public class ConfigurationItem
public class ConfigurationItem : IEquatable<ConfigurationItem>
{
[Optional] public DocumentUri ScopeUri { get; set; }
[Optional] public string Section { get; set; }

public bool Equals(ConfigurationItem other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(ScopeUri, other.ScopeUri) && Section == other.Section;
}

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConfigurationItem) obj);
}

public override int GetHashCode()
{
unchecked
{
return ( ( ScopeUri != null ? ScopeUri.GetHashCode() : 0 ) * 397 ) ^ ( Section != null ? Section.GetHashCode() : 0 );
}
}

public static bool operator ==(ConfigurationItem left, ConfigurationItem right) => Equals(left, right);

public static bool operator !=(ConfigurationItem left, ConfigurationItem right) => !Equals(left, right);
}
}
23 changes: 20 additions & 3 deletions src/Protocol/Server/ILanguageServerConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Server
{
public interface ILanguageServerConfiguration : IConfiguration
{
/// <summary>
/// Adds a set of configuration items to be tracked by the server
/// </summary>
/// <param name="configurationItems"></param>
/// <returns></returns>
ILanguageServerConfiguration AddConfigurationItems(IEnumerable<ConfigurationItem> configurationItems);

/// <summary>
/// Stops tracking a given set of configuration items
/// </summary>
/// <param name="configurationItems"></param>
/// <returns></returns>
ILanguageServerConfiguration RemoveConfigurationItems(IEnumerable<ConfigurationItem> configurationItems);

/// <summary>
/// Gets the current configuration values from the client
/// This configuration object is stateless such that it won't change with any other configuration changes
Expand All @@ -18,12 +34,13 @@ public interface ILanguageServerConfiguration : IConfiguration
/// Gets the current configuration for a given document uri
/// This re-uses all the sections from the <see cref="ConfigurationItem" />s that
/// the root configuration uses.
///
///
/// This will watch for changes of the scoped documents and update the configuration.
/// </summary>
/// <param name="scopeUri"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IScopedConfiguration> GetScopedConfiguration(DocumentUri scopeUri);
Task<IScopedConfiguration> GetScopedConfiguration(DocumentUri scopeUri, CancellationToken cancellationToken);

/// <summary>
/// Attempt to get an existing scoped configuration so that it can be disposed
Expand Down
79 changes: 79 additions & 0 deletions src/Protocol/Server/LanguageServerConfigurationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Server
{
public static class LanguageServerConfigurationExtensions
{
/// <summary>
/// Adds a set of configuration items to be tracked by the server
/// </summary>
/// <param name="configuration"></param>
/// <param name="configurationItem"></param>
/// <param name="configurationItems"></param>
/// <returns></returns>
public static ILanguageServerConfiguration AddConfigurationItem(this ILanguageServerConfiguration configuration, ConfigurationItem configurationItem, params ConfigurationItem[] configurationItems)
{
return configuration.AddConfigurationItems(new[] { configurationItem }.Concat(configurationItems));
}

/// <summary>
/// Stops tracking a given set of configuration items
/// </summary>
/// <param name="configuration"></param>
/// <param name="configurationItem"></param>
/// <param name="configurationItems"></param>
/// <returns></returns>
public static ILanguageServerConfiguration RemoveConfigurationItem(this ILanguageServerConfiguration configuration, ConfigurationItem configurationItem, params ConfigurationItem[] configurationItems)
{
return configuration.RemoveConfigurationItems(new[] { configurationItem }.Concat(configurationItems));
}

/// <summary>
/// Adds a set of configuration items to be tracked by the server
/// </summary>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="sections"></param>
/// <returns></returns>
public static ILanguageServerConfiguration AddSection(this ILanguageServerConfiguration configuration, string section, params string[] sections)
{
return configuration.AddConfigurationItems(new[] { section }.Concat(sections).Select(z => new ConfigurationItem() { Section = z}));
}

/// <summary>
/// Stops tracking a given set of configuration items
/// </summary>
/// <param name="configuration"></param>
/// <param name="section"></param>
/// <param name="sections"></param>
/// <returns></returns>
public static ILanguageServerConfiguration RemoveSection(this ILanguageServerConfiguration configuration, string section, params string[] sections)
{
return configuration.RemoveConfigurationItems(new[] { section }.Concat(sections).Select(z => new ConfigurationItem() { Section = z}));
}

/// <summary>
/// Adds a set of configuration items to be tracked by the server
/// </summary>
/// <param name="configuration"></param>
/// <param name="sections"></param>
/// <returns></returns>
public static ILanguageServerConfiguration AddSections(this ILanguageServerConfiguration configuration, IEnumerable<string> sections)
{
return configuration.AddConfigurationItems(sections.Select(z => new ConfigurationItem() { Section = z}));
}

/// <summary>
/// Stops tracking a given set of configuration items
/// </summary>
/// <param name="configuration"></param>
/// <param name="sections"></param>
/// <returns></returns>
public static ILanguageServerConfiguration RemoveSections(this ILanguageServerConfiguration configuration, IEnumerable<string> sections)
{
return configuration.RemoveConfigurationItems(sections.Select(z => new ConfigurationItem() { Section = z}));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol;

namespace OmniSharp.Extensions.LanguageServer.Server.Configuration
{
internal class BaseWorkspaceConfigurationProvider : ConfigurationProvider
class ConfigurationConverter
{
protected void ParseClientConfiguration(JToken settings, string prefix = null)
{
public void ParseClientConfiguration(IDictionary<string, string> data, JToken settings, string prefix = null)
{
if (settings == null || settings.Type == JTokenType.Null || settings.Type == JTokenType.None) return;
// The null request (appears) to always come second
// this handler is set to use the SerialAttribute

Data.Clear();

// TODO: Figure out the best way to plugin to handle additional configurations (toml, yaml?)
try
{
Expand All @@ -35,7 +34,7 @@ protected void ParseClientConfiguration(JToken settings, string prefix = null)
)
))
{
Data[item.Key] = item.Value;
data[item.Key] = item.Value;
}
}
catch (JsonReaderException)
Expand All @@ -50,12 +49,12 @@ protected void ParseClientConfiguration(JToken settings, string prefix = null)
new KeyValuePair<string, string>(GetKey(item, prefix), item.ToString())
))
{
Data[item.Key] = item.Value;
data[item.Key] = item.Value;
}
}
}

private string GetKey(JToken token, string prefix)
private static string GetKey(JToken token, string prefix)
{
var items = new Stack<string>();

Expand All @@ -82,7 +81,7 @@ private string GetKey(JToken token, string prefix)
return string.Join(":", items);
}

private string GetKey(XElement token, string prefix)
private static string GetKey(XElement token, string prefix)
{
var items = new Stack<string>();

Expand Down
Loading