Skip to content
11 changes: 6 additions & 5 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ indent_style=space
indent_size=4
insert_final_newline=true

[*.{json,xml,yml,yaml}]
[*.{xml,yml,yaml}]
indent_style=space
indent_size=2
insert_final_newline=true

[*.{xml,csproj,props,targets}]
[*.json]
indent_style=space
indent_size=4
insert_final_newline=true

[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
[*.{xml,csproj,props,targets}]
indent_style=space
indent_size=2

[{*.yaml,*.yml}]
[{*.har,*.inputactions,*.jsb2,*.jsb3,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
indent_style=space
indent_size=2

Expand Down
46 changes: 39 additions & 7 deletions src/Client/LanguageClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using DryIoc;
Expand Down Expand Up @@ -42,6 +43,7 @@ public class LanguageClient : JsonRpcServerBase, ILanguageClient
private readonly IEnumerable<IOnLanguageClientInitialize> _initializeHandlers;
private readonly IEnumerable<OnLanguageClientInitializedDelegate> _initializedDelegates;
private readonly IEnumerable<IOnLanguageClientInitialized> _initializedHandlers;
private readonly ISerializer _serializer;
private readonly IResponseRouter _responseRouter;
private readonly ISubject<InitializeResult> _initializeComplete = new AsyncSubject<InitializeResult>();
private readonly CompositeDisposable _disposable = new CompositeDisposable();
Expand Down Expand Up @@ -140,7 +142,8 @@ internal LanguageClient(
IRegistrationManager registrationManager,
ILanguageClientWorkspaceFoldersManager languageClientWorkspaceFoldersManager, IEnumerable<OnLanguageClientInitializeDelegate> initializeDelegates,
IEnumerable<IOnLanguageClientInitialize> initializeHandlers, IEnumerable<OnLanguageClientInitializedDelegate> initializedDelegates,
IEnumerable<IOnLanguageClientInitialized> initializedHandlers
IEnumerable<IOnLanguageClientInitialized> initializedHandlers,
ISerializer serializer
) : base(handlerCollection, responseRouter)
{
_connection = connection;
Expand All @@ -167,6 +170,7 @@ IEnumerable<IOnLanguageClientInitialized> initializedHandlers
_initializeHandlers = initializeHandlers;
_initializedDelegates = initializedDelegates;
_initializedHandlers = initializedHandlers;
_serializer = serializer;
_concurrency = options.Value.Concurrency;

// We need to at least create Window here in case any handler does loggin in their constructor
Expand Down Expand Up @@ -205,15 +209,43 @@ public async Task Initialize(CancellationToken token)
{
var @params = new InitializeParams {
Trace = _trace,
Capabilities = _clientCapabilities,
ClientInfo = _clientInfo,
Capabilities = _clientCapabilities,
RootUri = _rootUri,
RootPath = _rootUri?.GetFileSystemPath(),
WorkspaceFolders = new Container<WorkspaceFolder>(WorkspaceFoldersManager.CurrentWorkspaceFolders),
InitializationOptions = _initializationOptions
};

RegisterCapabilities(@params.Capabilities);
var capabilitiesObject = new JObject();
foreach (var capability in _capabilities)
{
var keys = capability.GetType().GetCustomAttribute<CapabilityKeyAttribute>()?.Keys.Select(key => char.ToLower(key[0]) + key.Substring(1)).ToArray();
if (keys != null)
{
var value = capabilitiesObject;
foreach (var key in keys.Take(keys.Length - 1))
{
if (value.TryGetValue(key, out var t) && t is JObject to)
{
value = to;
}
else
{
value[key] = value = new JObject();
}
}
var lastKey = keys[keys.Length - 1];
value[lastKey] = JToken.FromObject(capability, _serializer.JsonSerializer);
}
}

using (var reader = capabilitiesObject.CreateReader())
{
_serializer.JsonSerializer.Populate(reader, _clientCapabilities);
}

RegisterCapabilities(_clientCapabilities);

WorkDoneManager.Initialize(@params.Capabilities.Window);

Expand All @@ -229,7 +261,7 @@ await LanguageProtocolEventingHelper.Run(
);

_connection.Open();
var serverParams = await this.RequestLanguageProtocolInitialize(ClientSettings, token);
var serverParams = await SendRequest(ClientSettings, token);
_receiver.Initialized();

ServerSettings = serverParams;
Expand Down Expand Up @@ -334,17 +366,17 @@ public async Task Shutdown()
_connection.Dispose();
}

private T UseOrTryAndFindCapability<T>(Supports<T> supports)
private Supports<T> UseOrTryAndFindCapability<T>(Supports<T> supports) where T : class
{
var value = supports.IsSupported
? supports.Value
: _capabilities.OfType<T>().FirstOrDefault() ?? Activator.CreateInstance<T>();
: _capabilities.OfType<T>().FirstOrDefault();
if (value is IDynamicCapability dynamicCapability)
{
dynamicCapability.DynamicRegistration = _collection.ContainsHandler(typeof(IRegisterCapabilityHandler));
}

return value;
return Supports.OfValue(value);
}

public IObservable<InitializeResult> Start => _initializeComplete.AsObservable();
Expand Down
11 changes: 8 additions & 3 deletions src/JsonRpc.Generators/GenerateHandlerMethodsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public Task<RichGenerationResult> GenerateRichAsync(TransformationContext contex
}
);

var isInternal = handlerInterface.Modifiers.Any(z => z.IsKind(SyntaxKind.InternalKeyword));

return Task.FromResult(
new RichGenerationResult {
Usings = List(newUsings),
Expand All @@ -88,9 +90,12 @@ public Task<RichGenerationResult> GenerateRichAsync(TransformationContext contex
.WithAttributeLists(attributes)
.WithModifiers(
TokenList(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword),
Token(SyntaxKind.PartialKeyword)
new[] { isInternal ? Token(SyntaxKind.InternalKeyword) : Token(SyntaxKind.PublicKeyword) }.Concat(
new[] {
Token(SyntaxKind.StaticKeyword),
Token(SyntaxKind.PartialKeyword)
}
)
)
)
.WithMembers(List(methods))
Expand Down
10 changes: 7 additions & 3 deletions src/JsonRpc.Generators/GenerateRequestMethodsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public Task<RichGenerationResult> GenerateRichAsync(TransformationContext contex
.Except(existingUsings)
.Select(z => UsingDirective(IdentifierName(z)))
;
var isInternal = handlerInterface.Modifiers.Any(z => z.IsKind(SyntaxKind.InternalKeyword));
return Task.FromResult(
new RichGenerationResult {
Usings = List(newUsings),
Expand All @@ -108,9 +109,12 @@ public Task<RichGenerationResult> GenerateRichAsync(TransformationContext contex
.WithAttributeLists(attributes)
.WithModifiers(
TokenList(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword),
Token(SyntaxKind.PartialKeyword)
new[] { isInternal ? Token(SyntaxKind.InternalKeyword) : Token(SyntaxKind.PublicKeyword) }.Concat(
new[] {
Token(SyntaxKind.StaticKeyword),
Token(SyntaxKind.PartialKeyword)
}
)
)
)
.WithMembers(List(methods))
Expand Down
6 changes: 5 additions & 1 deletion src/JsonRpc/HandlerTypeDescriptorProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,11 @@ internal static IEnumerable<IHandlerTypeDescriptor> GetDescriptors(IEnumerable<A
.Select(HandlerTypeDescriptorHelper.GetMethodType)
.Distinct()
.ToLookup(x => MethodAttribute.From(x).Method)
.SelectMany(x => x.Select(z => new HandlerTypeDescriptor(z) as IHandlerTypeDescriptor));
.SelectMany(
x => x
.Distinct()
.Select(z => new HandlerTypeDescriptor(z) as IHandlerTypeDescriptor)
);

public IHandlerTypeDescriptor GetHandlerTypeDescriptor<A>() => GetHandlerTypeDescriptor(typeof(A));

Expand Down
11 changes: 11 additions & 0 deletions src/Protocol/CapabilitiesBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace OmniSharp.Extensions.LanguageServer.Protocol
{
public abstract class CapabilitiesBase
{
[JsonExtensionData] public IDictionary<string, JToken> ExtensionData { get; set; } = new Dictionary<string, JToken>();
}
}
17 changes: 17 additions & 0 deletions src/Protocol/CapabilityKeyAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace OmniSharp.Extensions.LanguageServer.Protocol
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public sealed class CapabilityKeyAttribute : Attribute
{
public IEnumerable<string> Keys { get; }

public CapabilityKeyAttribute(string key, params string[] additionalKeys)
{
Keys = new[] { key }.Concat(additionalKeys).ToArray();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
/// @since 3.16.0
/// </summary>
[Obsolete(Constants.Proposal)]
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CallHierarchy))]
public class CallHierarchyCapability : DynamicCapability, ConnectedCapability<ICallHierarchyHandler>,
ConnectedCapability<ICallHierarchyIncomingHandler>, ConnectedCapability<ICallHierarchyOutgoingHandler>
{
Expand Down
2 changes: 1 addition & 1 deletion src/Protocol/Client/Capabilities/ClientCapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class ClientCapabilities
public class ClientCapabilities : CapabilitiesBase
{
/// <summary>
/// Workspace specific client capabilities.
Expand Down
3 changes: 2 additions & 1 deletion src/Protocol/Client/Capabilities/CodeActionCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeAction))]
public class CodeActionCapability : DynamicCapability, ConnectedCapability<ICodeActionHandler>
{
/// <summary>
Expand All @@ -12,7 +13,7 @@ public class CodeActionCapability : DynamicCapability, ConnectedCapability<ICode
/// Since 3.8.0
/// </summary>
[Optional]
public CodeActionLiteralSupportCapability CodeActionLiteralSupport { get; set; }
public CodeActionLiteralSupportOptions CodeActionLiteralSupport { get; set; }

/// <summary>
/// Whether code action supports the `isPreferred` property.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class CodeActionKindCapability
public class CodeActionKindCapabilityOptions
{
/// <summary>
/// The code action kind values the client supports. When this
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class CodeActionLiteralSupportCapability
public class CodeActionLiteralSupportOptions
{
/// <summary>
/// The code action kind is support with the following value
/// set.
/// </summary>

public CodeActionKindCapability CodeActionKind { get; set; }
public CodeActionKindCapabilityOptions CodeActionKind { get; set; }
}
}
1 change: 1 addition & 0 deletions src/Protocol/Client/Capabilities/CodeLensCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.CodeLens))]
public class CodeLensCapability : DynamicCapability, ConnectedCapability<ICodeLensHandler>
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.ColorProvider))]
public class ColorProviderCapability : DynamicCapability, ConnectedCapability<IDocumentColorHandler>, ConnectedCapability<IColorPresentationHandler>
{
}
Expand Down
5 changes: 3 additions & 2 deletions src/Protocol/Client/Capabilities/CompletionCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Completion))]
public class CompletionCapability : DynamicCapability, ConnectedCapability<ICompletionHandler>
{
/// <summary>
/// The client supports the following `CompletionItem` specific
/// capabilities.
/// </summary>
[Optional]
public CompletionItemCapability CompletionItem { get; set; }
public CompletionItemCapabilityOptions CompletionItem { get; set; }

/// <summary>
/// Specific capabilities for the `CompletionItemKind` in the `textDocument/completion` request.
/// </summary>
[Optional]
public CompletionItemKindCapability CompletionItemKind { get; set; }
public CompletionItemKindCapabilityOptions CompletionItemKind { get; set; }

/// <summary>
/// The client supports to send additional context information for a `textDocument/completion` request.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class CompletionItemCapability
public class CompletionItemCapabilityOptions
{
/// <summary>
/// Client supports snippets as insert text.
Expand Down Expand Up @@ -50,7 +50,7 @@ public class CompletionItemCapability
/// @since 3.15.0
/// </summary>
[Optional]
public Supports<CompletionItemTagSupportCapability> TagSupport { get; set; }
public Supports<CompletionItemTagSupportCapabilityOptions> TagSupport { get; set; }

/// <summary>
/// Client support insert replace edit to control different behavior if a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class CompletionItemKindCapability
public class CompletionItemKindCapabilityOptions
{
/// <summary>
/// The completion item kind values the client supports. When this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
public class CompletionItemTagSupportCapability
public class CompletionItemTagSupportCapabilityOptions
{
/// <summary>
/// The tags supported by the client.
Expand Down
1 change: 1 addition & 0 deletions src/Protocol/Client/Capabilities/ConnectedCapability.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
Expand Down
1 change: 1 addition & 0 deletions src/Protocol/Client/Capabilities/DeclarationCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Declaration))]
public class DeclarationCapability : LinkSupportCapability, ConnectedCapability<IDeclarationHandler>
{
}
Expand Down
1 change: 1 addition & 0 deletions src/Protocol/Client/Capabilities/DefinitionCapability.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(TextDocumentClientCapabilities.Definition))]
public class DefinitionCapability : LinkSupportCapability, ConnectedCapability<IDefinitionHandler>
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.Configuration))]
public class DidChangeConfigurationCapability : DynamicCapability
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
{
[CapabilityKey(nameof(ClientCapabilities.TextDocument), nameof(WorkspaceClientCapabilities.DidChangeWatchedFiles))]
public class DidChangeWatchedFilesCapability : DynamicCapability
{
}
Expand Down
Loading