Skip to content

Commit 5571121

Browse files
Fixed configuration issue where data was being cleared of previous sections (#317)
* Fixed configuration issue where data was being cleared of previous sections * Updated scoped configuration to better handler on reload
1 parent 1497f35 commit 5571121

14 files changed

+396
-121
lines changed

sample/SampleServer/TextDocumentHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public async Task<Unit> Handle(DidOpenTextDocumentParams notification, Cancellat
6363
{
6464
await Task.Yield();
6565
_logger.LogInformation("Hello world!");
66-
await _configuration.GetScopedConfiguration(notification.TextDocument.Uri);
66+
await _configuration.GetScopedConfiguration(notification.TextDocument.Uri, token);
6767
return Unit.Value;
6868
}
6969

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,38 @@
1+
using System;
12
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
23

34
namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
45
{
5-
public class ConfigurationItem
6+
public class ConfigurationItem : IEquatable<ConfigurationItem>
67
{
78
[Optional] public DocumentUri ScopeUri { get; set; }
89
[Optional] public string Section { get; set; }
10+
11+
public bool Equals(ConfigurationItem other)
12+
{
13+
if (ReferenceEquals(null, other)) return false;
14+
if (ReferenceEquals(this, other)) return true;
15+
return Equals(ScopeUri, other.ScopeUri) && Section == other.Section;
16+
}
17+
18+
public override bool Equals(object obj)
19+
{
20+
if (ReferenceEquals(null, obj)) return false;
21+
if (ReferenceEquals(this, obj)) return true;
22+
if (obj.GetType() != this.GetType()) return false;
23+
return Equals((ConfigurationItem) obj);
24+
}
25+
26+
public override int GetHashCode()
27+
{
28+
unchecked
29+
{
30+
return ( ( ScopeUri != null ? ScopeUri.GetHashCode() : 0 ) * 397 ) ^ ( Section != null ? Section.GetHashCode() : 0 );
31+
}
32+
}
33+
34+
public static bool operator ==(ConfigurationItem left, ConfigurationItem right) => Equals(left, right);
35+
36+
public static bool operator !=(ConfigurationItem left, ConfigurationItem right) => !Equals(left, right);
937
}
1038
}

src/Protocol/Server/ILanguageServerConfiguration.cs

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
1-
using System.Threading.Tasks;
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
24
using Microsoft.Extensions.Configuration;
35
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
46

57
namespace OmniSharp.Extensions.LanguageServer.Protocol.Server
68
{
79
public interface ILanguageServerConfiguration : IConfiguration
810
{
11+
/// <summary>
12+
/// Adds a set of configuration items to be tracked by the server
13+
/// </summary>
14+
/// <param name="configurationItems"></param>
15+
/// <returns></returns>
16+
ILanguageServerConfiguration AddConfigurationItems(IEnumerable<ConfigurationItem> configurationItems);
17+
18+
/// <summary>
19+
/// Stops tracking a given set of configuration items
20+
/// </summary>
21+
/// <param name="configurationItems"></param>
22+
/// <returns></returns>
23+
ILanguageServerConfiguration RemoveConfigurationItems(IEnumerable<ConfigurationItem> configurationItems);
24+
925
/// <summary>
1026
/// Gets the current configuration values from the client
1127
/// This configuration object is stateless such that it won't change with any other configuration changes
@@ -18,12 +34,13 @@ public interface ILanguageServerConfiguration : IConfiguration
1834
/// Gets the current configuration for a given document uri
1935
/// This re-uses all the sections from the <see cref="ConfigurationItem" />s that
2036
/// the root configuration uses.
21-
///
37+
///
2238
/// This will watch for changes of the scoped documents and update the configuration.
2339
/// </summary>
2440
/// <param name="scopeUri"></param>
41+
/// <param name="cancellationToken"></param>
2542
/// <returns></returns>
26-
Task<IScopedConfiguration> GetScopedConfiguration(DocumentUri scopeUri);
43+
Task<IScopedConfiguration> GetScopedConfiguration(DocumentUri scopeUri, CancellationToken cancellationToken);
2744

2845
/// <summary>
2946
/// Attempt to get an existing scoped configuration so that it can be disposed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
4+
5+
namespace OmniSharp.Extensions.LanguageServer.Protocol.Server
6+
{
7+
public static class LanguageServerConfigurationExtensions
8+
{
9+
/// <summary>
10+
/// Adds a set of configuration items to be tracked by the server
11+
/// </summary>
12+
/// <param name="configuration"></param>
13+
/// <param name="configurationItem"></param>
14+
/// <param name="configurationItems"></param>
15+
/// <returns></returns>
16+
public static ILanguageServerConfiguration AddConfigurationItem(this ILanguageServerConfiguration configuration, ConfigurationItem configurationItem, params ConfigurationItem[] configurationItems)
17+
{
18+
return configuration.AddConfigurationItems(new[] { configurationItem }.Concat(configurationItems));
19+
}
20+
21+
/// <summary>
22+
/// Stops tracking a given set of configuration items
23+
/// </summary>
24+
/// <param name="configuration"></param>
25+
/// <param name="configurationItem"></param>
26+
/// <param name="configurationItems"></param>
27+
/// <returns></returns>
28+
public static ILanguageServerConfiguration RemoveConfigurationItem(this ILanguageServerConfiguration configuration, ConfigurationItem configurationItem, params ConfigurationItem[] configurationItems)
29+
{
30+
return configuration.RemoveConfigurationItems(new[] { configurationItem }.Concat(configurationItems));
31+
}
32+
33+
/// <summary>
34+
/// Adds a set of configuration items to be tracked by the server
35+
/// </summary>
36+
/// <param name="configuration"></param>
37+
/// <param name="section"></param>
38+
/// <param name="sections"></param>
39+
/// <returns></returns>
40+
public static ILanguageServerConfiguration AddSection(this ILanguageServerConfiguration configuration, string section, params string[] sections)
41+
{
42+
return configuration.AddConfigurationItems(new[] { section }.Concat(sections).Select(z => new ConfigurationItem() { Section = z}));
43+
}
44+
45+
/// <summary>
46+
/// Stops tracking a given set of configuration items
47+
/// </summary>
48+
/// <param name="configuration"></param>
49+
/// <param name="section"></param>
50+
/// <param name="sections"></param>
51+
/// <returns></returns>
52+
public static ILanguageServerConfiguration RemoveSection(this ILanguageServerConfiguration configuration, string section, params string[] sections)
53+
{
54+
return configuration.RemoveConfigurationItems(new[] { section }.Concat(sections).Select(z => new ConfigurationItem() { Section = z}));
55+
}
56+
57+
/// <summary>
58+
/// Adds a set of configuration items to be tracked by the server
59+
/// </summary>
60+
/// <param name="configuration"></param>
61+
/// <param name="sections"></param>
62+
/// <returns></returns>
63+
public static ILanguageServerConfiguration AddSections(this ILanguageServerConfiguration configuration, IEnumerable<string> sections)
64+
{
65+
return configuration.AddConfigurationItems(sections.Select(z => new ConfigurationItem() { Section = z}));
66+
}
67+
68+
/// <summary>
69+
/// Stops tracking a given set of configuration items
70+
/// </summary>
71+
/// <param name="configuration"></param>
72+
/// <param name="sections"></param>
73+
/// <returns></returns>
74+
public static ILanguageServerConfiguration RemoveSections(this ILanguageServerConfiguration configuration, IEnumerable<string> sections)
75+
{
76+
return configuration.RemoveConfigurationItems(sections.Select(z => new ConfigurationItem() { Section = z}));
77+
}
78+
}
79+
}

src/Server/Configuration/BaseWorkspaceConfigurationProvider.cs renamed to src/Server/Configuration/ConfigurationConverter.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@
66
using Microsoft.Extensions.Configuration;
77
using Newtonsoft.Json;
88
using Newtonsoft.Json.Linq;
9+
using OmniSharp.Extensions.LanguageServer.Protocol;
910

1011
namespace OmniSharp.Extensions.LanguageServer.Server.Configuration
1112
{
12-
internal class BaseWorkspaceConfigurationProvider : ConfigurationProvider
13+
class ConfigurationConverter
1314
{
14-
protected void ParseClientConfiguration(JToken settings, string prefix = null)
15-
{
15+
public void ParseClientConfiguration(IDictionary<string, string> data, JToken settings, string prefix = null)
16+
{
1617
if (settings == null || settings.Type == JTokenType.Null || settings.Type == JTokenType.None) return;
1718
// The null request (appears) to always come second
1819
// this handler is set to use the SerialAttribute
1920

20-
Data.Clear();
21-
2221
// TODO: Figure out the best way to plugin to handle additional configurations (toml, yaml?)
2322
try
2423
{
@@ -35,7 +34,7 @@ protected void ParseClientConfiguration(JToken settings, string prefix = null)
3534
)
3635
))
3736
{
38-
Data[item.Key] = item.Value;
37+
data[item.Key] = item.Value;
3938
}
4039
}
4140
catch (JsonReaderException)
@@ -50,12 +49,12 @@ protected void ParseClientConfiguration(JToken settings, string prefix = null)
5049
new KeyValuePair<string, string>(GetKey(item, prefix), item.ToString())
5150
))
5251
{
53-
Data[item.Key] = item.Value;
52+
data[item.Key] = item.Value;
5453
}
5554
}
5655
}
5756

58-
private string GetKey(JToken token, string prefix)
57+
private static string GetKey(JToken token, string prefix)
5958
{
6059
var items = new Stack<string>();
6160

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

85-
private string GetKey(XElement token, string prefix)
84+
private static string GetKey(XElement token, string prefix)
8685
{
8786
var items = new Stack<string>();
8887

0 commit comments

Comments
 (0)